# File format

> What's inside a .flozu.json map file and a .flozu-bundle.json bundle, how Flozu checks them, and how older files keep opening.

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.

## What’s inside

```ts
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](https://docs.flozu.app/guides/response-times-and-cost.md). 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](https://docs.flozu.app/guides/maps-inside-parts.md) 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`](https://github.com/flozu-app/flozu/blob/main/packages/core/src/model.ts), and `mapJsonSchema()` exports it as JSON Schema.

## What a file doesn’t hold

- **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.

## Bundles

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:

```ts
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](https://docs.flozu.app/guides/import-export.md#import) for what happens to each when it comes in.

## Outlines

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](https://docs.flozu.app/guides/map-your-code.md), and Flozu lays it out as a new map when you import it.

```ts
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](https://docs.flozu.app/guides/maps-inside-parts.md), 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](https://docs.flozu.app/map-your-code.md).

## Checked before it opens

Flozu checks every file against the schema and [the map’s rules](https://docs.flozu.app/concepts/the-map.md#what-the-map-keeps-true) before it opens it, whether it comes from storage, an import, a share link or a version. A file that fails says why.

## Older and newer files

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.
