Skip to content

File format

A map saves as one .flozu.json file: indented JSON, readable in any text editor, and friendly to version control. The current format is version 17. Files saved before the rename end in .fflo.json and still open: the contents are the same, and only the ending changed.

FlozuMap { schemaVersion, id, name, description?,
components, connections, groups, notes, views, // each keyed by id
stories?, scenarios?, // left out while there are none
lineRoute?: "square" | "straight" } // how its lines run, curved if left out
Component { id, kind, name, description?, technology?, external?: true,
position, size?, layout?, visual?, style?, groupId?, flow?,
inside?: { mapId }, meta? } // the map it opens into
Connection { id, source: { componentId, port?, side? }, target: { componentId, port?, side? },
kind: "request" | "message", direction: "forward" | "both",
label?, protocol?, flow?, style?, standby?: true }
Group { id, kind, name, description?, position, size, parentId?, style? }
Note { id, text, position, width?, groupId?, style? }
View { id, name, audience: "technical" | "non-technical",
hidden, collapsed, wording }
Story { id, name, steps }

In a file, parts are components, lines are connections and zones are groups. Traffic lives on a connection’s flow (rate, unit), and limits on a component’s flow (capacity, limit, buffer, scaling, people). A component’s flow can also say how many seconds it takes to handle one thing (latency, such as 0.05) and what it costs to run for an hour, in dollars (cost, for one copy of a part that auto-scales), for a scenario’s estimates. Anything left at its default, such as a standard card or a kind’s own drawing, is left out of the file.

A line with standby: true carries nothing until a line beside it fails, then takes its traffic over. A saved scenario’s events can include failures: { kind: "failure", at, length?, target: { components?, connections?, zone? }, mode: "down" | "degraded", keep? }. A failure without a length lasts to the end, and keep is the share a degraded one keeps.

A line’s side on an end is the side of the part it meets (left, right, top or bottom), left out for the usual right side out and left side in. A line’s style can add hidden: true (draw only what moves along it), an effect (traffic, pulse, flow or none) and a route (curved, square or straight), which wins over the map’s lineRoute. A colour in any style is a palette name such as "blue", or a colour of your own as six hex digits such as "#3a7bd5".

A story’s steps can each show a moment of a saved scenario (scenario: { scenarioId, at }, at in seconds from its start) and compare one of the map’s proposals with where it began (compare: { proposalId }). The proposal lives in the map’s history, not in the file, so a copy without its history shows that step on the map.

A part’s inside names the map it opens into by its id alone, so moving or renaming either map never breaks the link. A line’s port on an end names the part inside that map it joins, when you’ve chosen one with Lands on or Leaves from.

The full schema lives in packages/core/src/model.ts, and mapJsonSchema() exports it as JSON Schema.

  • Where it was kept. A map’s project or folder belongs to storage, not to the map.
  • Its history. Versions and proposals are kept beside the map. A map file is always the map as it is now. A bundle carries the history.

A bundle (.flozu-bundle.json) holds several maps in one file: a map with its history, a project, a folder or every map. It’s JSON too:

Bundle { bundleFormat: 1, name, scope: "map" | "folder" | "library", exportedAt,
folders, // paths inside the bundle, such as "Payments/Services"
maps: BundledMap[] }
BundledMap { folder?, createdAt?, updatedAt?, map, versions?,
linked?: true } // only here because a part in the bundle opens into it

Each map and version in a bundle is checked and updated like any file, so an old bundle keeps importing. See import for what happens to each when it comes in.

An outline (.flozu-outline.json) is a map with nothing placed: its parts, the lines between them and the zones they sit in, how they look, the traffic they carry, and the notes, views, scenarios and stories that go with them. It’s what Claude writes when it maps your code, and Flozu lays it out as a new map when you import it.

Outline { outlineFormat: 2, // 1 still reads: parts, links and zones only
name, description?,
lineRoute?: "curved" | "square" | "straight",
parts: OutlinePart[], // 1 to 300
links?: OutlineLink[], // up to 1,000
zones?: OutlineZone[], // up to 100
notes?: OutlineNote[], // up to 100
views?: OutlineView[], // up to 20
scenarios?: OutlineScenario[], // up to 20
stories?: OutlineStory[] } // up to 20
OutlinePart { id, name,
kind?, preset?, // a kind, a ready-made part, or both
description?, technology?, external?: boolean,
zone?, // the id of the zone it sits in
code?, // where it lives, such as "services/orders"
meta?,
opens?, // the id of a saved map of what's inside it
layout?: "standard" | "showcase" | "wide" | "slim",
size?: "small" | "standard" | "large" | "extra-large",
drawing?, // a drawing's id, such as "hit-rate"
style?, // as a part's style in a map
flow? } // as a part's flow in a map
OutlineLink { id?, from, to, // part ids
kind?: "request" | "message" | "uses", // worked out from its ends if left out
label?, protocol?, direction?: "forward" | "both",
rate?, unit?, // per second; a unit needs a rate
fromSide?, toSide?, // "left" | "right" | "top" | "bottom"
style?, // as a line's style in a map
standby?: boolean }
OutlineZone { id, name, kind?: "zone" | "network" | "region" | "system" | "team",
description?, parent?, // the id of the zone it sits inside
style? }
OutlineNote { id?, text, zone?, width?, style? } // without a zone, it sits under the map
OutlineView { id?, name, audience: "technical" | "non-technical",
hide?: id[], collapse?: zoneId[], wording?: { [id]: { name?, description? } } }
OutlineScenario { id?, preset?, // a ready-made scenario's key
name?, duration?, // needed without a preset
...the rest of a scenario's plan } // anything set wins over the preset
OutlineStory { id?, name,
steps: { id?, title, text?, focus?: id[],
scenario?: { id, at }, // a moment of one of the outline's scenarios
overrides? }[] } // 1 to 60

Ids are yours to choose, such as orders-api, and they become the ids on the map. Every id is used once across the outline, and everything an outline names by id is in it. A part starts from its preset’s kind, technology, drawing, layout and limits, and anything set on the part wins. A named size is its layout’s own (a large wide card is 448 × 208). A part’s code shows under Code in its details, and opens makes it a part with a map inside, such as a repository’s own map on a project’s overview. A drill scenario, such as region-down, takes down what matters on the map as drawn. An outline that breaks a rule is refused with a message that says what to fix and where. outlineJsonSchema() in core exports the outline as JSON Schema, and the full guide Claude follows is at map-your-code.md.

Flozu checks every file against the schema and the map’s rules before it opens it, whether it comes from storage, an import, a share link or a version. A file that fails says why.

Every time the format changes, its version goes up and Flozu learns to update older files as they open, so a file from any earlier version keeps working. A file from a newer version of Flozu is refused with a message to update.

A map that names a drawing this version of Flozu doesn’t know still opens; that part shows its kind’s own drawing.