Skip to content

plan.json

plan.json is the derived stitch list in an open, machine-neutral form. It exists so that a third party can produce DST, PES, EXP, JEF or anything else without understanding the editable model. If you are writing an exporter, this is the only page you need.

It is optional. Exported .hoop files carry it; an application’s own library saves commonly do not, because it can always be regenerated. Readers MUST handle its absence.

  • Unit: millimetres, floating point.
  • Origin: the hoop centre.
  • y points up. Most machine formats have y pointing down; converting is a sign flip, and forgetting it is the single most common porting bug.
{
"stitches": [
{ "position": { "x": 11.844811, "y": 1.330744 }, "function": "jump" },
{ "position": { "x": 12.100000, "y": 1.500000 }, "function": "stitch" }
],
"commands": [
{ "kind": { "colorChange": { "index": 3 } }, "beforeStitchIndex": 0 },
{ "kind": { "trim": {} }, "beforeStitchIndex": 505 }
],
"colorTable": [
{ "red": 47, "green": 48, "blue": 50,
"catalogId": "madeira-polyneon", "code": "1800", "name": "Black" }
],
"objectRanges": [
{ "objectID": "63C5BD58-4BF0-434B-AE1A-E1018D8A9192", "start": 0, "end": 502 }
],
"stats": {
"stitchCount": 2214, "jumpCount": 9, "trimCount": 8, "colorChangeCount": 4,
"bounds": { "minX": -17.697304, "minY": -20.741376,
"maxX": 17.492767, "maxY": 21.952183 }
}
}

An ordered array of needle positions. Each entry is an absolute position — there are no deltas anywhere in this format, which is what keeps it immune to the drift that plagues delta-encoded machine formats.

function is one of:

ValueMeaning
stitchNeedle down. A normal stitch.
jumpPen-up movement. The machine moves without stitching.
travelA needle-down connecting run between parts of a design. Sewn exactly like a normal stitch.

travel exists so that tools which care can tell a structural connection from design stitching — for example to hide or re-route it. Readers that do not distinguish it MUST treat travel as stitch. Treating it as a jump would produce a file that skips stitches the design needs.

Machine commands anchored before the stitch at beforeStitchIndex. Several commands may share an index; they apply in array order.

KindPayloadMeaning
colorChange{ "index": Int }Change to the thread at that index in colorTable.
trim{}Cut the thread.
stop{}Pause the machine without a thread change.

The JSON shape is a single-key object naming the kind, with the payload as its value — including for payload-less kinds, which encode as an empty object ({"trim": {}}).

The threads the plan refers to, in plan order.

FieldTypeMeaning
red, green, blue0–255 integersDisplay colour.
catalogIdstring, optionalThread catalogue identifier, e.g. madeira-polyneon.
codestring, optionalCatalogue number, e.g. 1800.
namestring, optionalHuman-readable name, e.g. Black.

The three optional fields are what a machine format cannot carry. DST has no colours at all; PES and JEF map to a manufacturer’s fixed palette. Here the identity survives, so a worksheet can say Madeira Polyneon 1800 Black rather than the dark one.

Any of them may be null for a colour picked freely rather than from a catalogue. Only the RGB triple is guaranteed.

Maps regions of the stitch list back to the design objects that produced them.

{ "objectID": "63C5BD58-…", "start": 0, "end": 502 }

start is inclusive, end exclusive, both indexing stitches. Ranges are in stitch order and, taken together, cover the whole array.

This is what makes a stitch player able to say now sewing: Fill 1, and what lets a tool highlight one object’s stitches. objectID matches an object id in document.json when that entry is present; when it is not, the ranges still partition the plan usefully on their own.

Summary values, all derivable from the arrays above — provided so a reader can show a file’s size and extent without walking it.

FieldMeaning
stitchCountNumber of sewn stitches.
jumpCountNumber of jumps.
trimCountNumber of trim commands.
colorChangeCountNumber of colour-change commands.
boundsDesign extent in millimetres.

plan.json reflects document.json at the moment it was saved. It is output, and this is normative:

  • Editors MUST NOT import plan.json back into editable state. Doing so would replace a design with its own shadow — a stitch soup that cannot be re-digitised.
  • Re-writers MAY drop it, and SHOULD regenerate rather than copy it if the document changed.
  • If plan.json and document.json disagree, document.json is right and the plan is stale.

Tools that only consume — exporters, viewers, estimators, stitch players — are free to use it as their only input. The restriction is on writing back, not on reading.

The complete job of a Level-0 reader:

  1. Open the .hoop as a ZIP; verify entry CRCs and the manifest’s SHA-256 digests (Reader requirements).
  2. Inflate plan.json; parse it.
  3. Walk stitches, applying any commands whose beforeStitchIndex equals the current index before emitting the stitch.
  4. Convert millimetres to your target’s units and flip the y sign if it points down.
  5. Map colorTable to whatever colour representation the target format has.

Nothing in document.json is required for this, and nothing in it will change the result.