← Hashito System home 日本語 Tools Blog
Drawing JSON
Samples:
Preview and export
SVG is the real output. A drawing made of lines keeps its edges at any scale in SVG, and you can still change colors and widths afterwards. The PNG is rasterized on the spot by the browser canvas.
Spec prompt for an AI

The point of this tool is to hand the spec below to an AI, add a description of the drawing you want, and paste the JSON that comes back into the box above. The whole spec is printed here.

You write drawings in the Circle-Line Spec v1, an SVG format made only of circles and lines.
Reply with JSON in this format and nothing else (no prose, no code fences).

# Overall shape
{
  "version": 1,
  "canvas": { "w": 800, "h": 800, "bg": "#0b0b10" },
  "stroke": { "color": "#ffffff", "width": 1.5, "cap": "round", "join": "round", "dash": "", "opacity": 1 },
  "shapes": [ put the shapes here ]
}
- canvas.w / canvas.h are numbers from 16 to 4000. bg is the background color; "none" means transparent.
- stroke holds the defaults for every shape. Omit it and the values above are used.
- shapes holds at most 5000 entries.

# Only three kinds of shape
circle  { "t": "c", "x": centerX, "y": centerY, "r": radius }
line    { "t": "l", "x1": startX, "y1": startY, "x2": endX, "y2": endY }
arc     { "t": "a", "x": centerX, "y": centerY, "r": radius, "a0": startAngle, "a1": endAngle }

# Angles
- Degrees. 0 degrees points right (+X), 90 is down, 180 is left, 270 is up, because the screen Y axis points down.
- The arc runs from a0 towards a1: clockwise when a1 is larger, counter-clockwise when it is smaller.
- A difference of 360 or more is a full turn. a0 and a1 must not be equal.

# Per-shape overrides (all optional)
"s"  stroke color ("#ff0044" / "orange" / "rgb(255,0,68)")
"w"  stroke width (0 or greater)
"d"  dash pattern ("6 4" or [6,4]; omit for a solid line)
"f"  fill color (omit for no fill)
"o"  opacity (0 to 1)

# Rules
- Keep coordinates inside the canvas. Three decimal places are plenty.
- Bezier curves, polygons, text, images and gradients do not exist. Build curves by chaining arcs.
- Always compute coordinates and write concrete numbers. No expressions, no variables.
- For symmetric figures divide the angle evenly, and for repeated motifs write out every instance.

# Example (circle, cross, dashed half circle)
{"version":1,"canvas":{"w":400,"h":400,"bg":"#0b0b10"},"stroke":{"color":"#ffffff","width":1.5},"shapes":[
{"t":"c","x":200,"y":200,"r":150},
{"t":"l","x1":50,"y1":200,"x2":350,"y2":200},
{"t":"l","x1":200,"y1":50,"x2":200,"y2":350},
{"t":"a","x":200,"y":200,"r":90,"a0":0,"a1":180,"d":"6 4"}
]}

Now express the following drawing as JSON in this format.
Drawing:

Key reference

WhereKeyMeaning
Top levelversionSpec version, currently 1. A different value raises a notice and the drawing is still attempted.
canvasw / h / bgWidth and height (16 to 4000) and background color. Defaults are 800 / 800 / #0b0b10. Use none for no background.
strokecolor / width / cap / join / dash / opacityDefaults for every shape. cap is butt / round / square, join is miter / round / bevel.
shapes[]tKind: c (circle), l (line) or a (arc).
t = cx / y / rCenter and radius. r must be greater than 0.
t = lx1 / y1 / x2 / y2Start and end point.
t = ax / y / r / a0 / a1Center, radius, start angle and end angle in degrees.
shapes[] optionals / w / d / f / oStroke color, width, dash, fill and opacity for that shape alone. Anything omitted falls back to stroke.

The keys are short so that the same drawing costs fewer characters: shorter model output and shorter share links. Having only three kinds of shape is what keeps the abbreviations readable.

Things worth knowing

Watch the direction of angles

The screen Y axis points down, so growing angles look clockwise. {"t":"a","x":400,"y":400,"r":200,"a0":0,"a1":90} runs from the 3 o'clock position to the 6 o'clock position, a quarter circle through the lower right. To go the other way, make the end angle smaller, as in "a0":90,"a1":0. When you want to start from the top, using -90 as the origin is the easiest to reason about.

Errors come back with line numbers

A broken JSON document reports the line and column of the syntax error; an off-spec value reports the line where that shape is written. Syntax errors stop at the first one, but value problems are all listed together, so you can paste the whole list back to the model. If even one shape is invalid nothing is drawn, because a partial figure that looks plausible is worse than no figure.

Build curves by chaining arcs

There are no Bezier curves here. When you need a smooth curve, place arcs whose centers sit where they touch. The arc tiling sample is nothing more than two quarter circles per square cell, centered on opposite corners, but the endpoints line up with the neighbouring cells so the curve reads as continuous. The trick when joining arcs is to put the next center on the line through the previous center and its endpoint.

What is inside a share link

A share link carries the drawing itself in ?d=. The first character is the method: z for deflate-raw compression, u for uncompressed. The rest is base64url, so nothing breaks inside a URL. The drawing is never stored on a server, which means only the people you send the link to can see it, and losing the link loses the drawing.

Frequently Asked Questions

Why only circles, lines and arcs?

With three primitives, a drawing is fully determined by a list of numbers. There are no Bezier control points to reason about, so a person can read the document and a model only has to compute coordinates. Fewer forms are reachable, but chaining arcs still gives you curves.

How do I get an AI to write the JSON?

Copy the spec prompt on this page, append a description of the drawing you want, and hand it to the model. Paste the JSON that comes back into the input box and it is drawn immediately. Anything that breaks the spec is reported with a line number, so you can paste that text straight back to the model.

How long does a share link get?

The JSON is stripped of whitespace, compressed with deflate-raw and encoded as base64url in the URL. Around 100 shapes lands near 1000 characters. Browsers without compression support fall back to the uncompressed form, which is longer. The drawing itself lives in the link, so nothing is stored on a server.