# Nanoodle Workflow JSON Format (the downloadable "save") Verified against /home/ntc/dev/nanoodle/index.html (editor). The πŸ’Ύ Save button writes `noodle-graph.json` = exactly `JSON.stringify(serializeGraph(), null, 2)` β€” no wrapper. ## Top-level shape ```json { "v": 1, "nodes": [ { "id":"n1", "type":"text", "x":60, "y":130, "fields":{...}, "w":220, "sizes":{"system":120}, "name":"optional custom name" } ], "links": [ { "id":"l1", "from":{"node":"n1","port":"text"}, "to":{"node":"n2","port":"prompt"} } ], "nid": 4, "lid": 3, "view": { "panX":40, "panY":60, "scale":1 } } ``` - `v` β€” always 1. - Node: `id` (string "nN"), `type` (NODE_TYPES key), `x/y/w/sizes` layout-only (ignore), `fields` (param bag, type-specific), `name` (optional user label β€” the display name). - Link: `{id, from:{node,port}, to:{node,port}}`. - `nid/lid/view` β€” editor counters/camera; ignore for execution. - ALL keys except `nodes` are optional to a loader: `d.nodes||[]`, `d.links||[]`. Accept `{nodes, links}` minimal form. ## Loader semantics (applyGraphData, index.html:8815-8860) β€” REPLICATE THESE - Type alias: `audio` β†’ `tts` (legacy). - Unknown node type β†’ node silently skipped (library: keep node but error only if it must run β€” see DESIGN; simplest faithful behavior: drop unknown-type nodes AND their links, but surface a warning). - Links kept only if BOTH endpoints exist after node filtering. - Migration: links into a `music`/`tts` node with `to.port === "text"` are rewritten to `"prompt"`. - Media fields are `data:` URLs inline in `fields` (image/audio/video/mask). Share links may have them blanked to "". ## Node type registry (NODE_TYPES, index.html:5015-5679) Port kinds: text | image | audio | video. Only matching kinds connect. Every `