Morffy documentation

Watch your architecture morph across releases.

Morffy is a read-only visualizer. Give it one JSON or YAML file and it renders your system as twin views — a graph canvas and a timeline — that stay in lock-step as you scrub through milestones.

What is Morffy

Two representations of the same data, kept in perfect sync — so you can see both what a system looks like and how it got there.

AI can rewrite an architecture in seconds, but it explains the change in walls of markdown or disconnected diagrams. Morffy takes a single time-aware file and turns it into an interactive, time-traveling topology of your components, modules, or services — running entirely on your machine.

Morffy never edits your file — it only reads and visualizes. The two views are:

Graph canvas — the “Visio” view

The architecture at one milestone: boxes (elements) joined by directional arrows (connectors), automatically laid out, with nested containers drawn as titled boxes.

Timeline — the “Gantt” view

One row per element, its lifespan drawn across the milestones — so a component's whole life is legible at a glance.

Quick start

Two ways in — a zero-setup command, or the in-app file picker.

Run from the command line

No install, no build step. Point Morffy at your file:

# serves the app, opens the browser, live-reloads on save
npx morffy diagram.json

Morffy serves the prebuilt app, auto-loads your file, and watches it — edit the file on disk and the diagram refreshes on its own. Handy flags:

FlagEffect
--port <n>Serve on a specific port (default 4173).
--no-openDon't open the browser automatically.
--no-watchLoad once; skip live reload.
--validateCheck the file and print issues without serving the app.

Load in the app

Open Morffy and click Load file (in the top bar, or on the empty-state prompt) to pick a JSON or YAML file from disk. A status indicator shows empty → loading → Loaded, or Invalid if the file has problems.

Core concepts

The vocabulary that shows up everywhere else in these docs.

Diagram
The whole file: a title, a timeline, elements, and connectors.
Milestone
An ordered point on the timeline — a release tick. Milestones are points, not ranges; their order drives every temporal calculation. Keep labels short; put detail in the description (shown on hover).
Element
A component — a box on the canvas. Has a label, an icon, a type caption (e.g. “service”, “datastore”), an optional parent, a lifespan, and metadata.
Connector
A directional link from a source element to a target, drawn as a labeled arrow.
Lifespan
The window an element or connector is alive — a start and end milestone. Omit the start to run from the first milestone; omit the end to run to the last.
Parent container / nesting
An element can nest inside a container element via its parent. The parent must exist, can't be itself, can't form a cycle, and the child must live within its parent's lifespan.
Metadata
Free-form property → values tags on elements (e.g. environment: ["prod", "staging"]). Drives filtering and coloring.
Compare status
Added, Removed, or Unchanged — computed between any two milestones.

Exploring a diagram

Everything below is read-only exploration — select, scrub, filter, and compare. Your file is never modified.

Timeline scrubber — top strip

Milestones appear as points on a track. Click a dot or label, or drag along the track, to move through history — the diagram fades components in and out as their lifespans start and end. Use and to step; the strip pages with arrows when milestones overflow and keeps the active one in view.

Graph canvas — the Visio view

Boxes and arrows under one stable layout, with nested containers drawn as titled boxes. Pan and zoom freely; click a node to select it, click the empty pane to deselect. A node takes one of three states, shown below with a real node:

Checkout API service
Alive — present at the current milestone. Full color, a thicker border, and it's clickable.
Checkout API service
Not alive — outside its lifespan at this milestone. Fades back to 20% opacity with a thin border, and can't be selected.
Checkout API service
Filtered out — hidden by a metadata filter. Uses the same recede treatment as “not alive,” so a filtered node stays in place for context but drops out of focus.

Timeline view — the Gantt view

One row per element with its lifespan bar drawn across the milestone columns; the active column is highlighted and children are indented under their parents. It honors the same filter, coloring, and compare status as the canvas. Click a row to inspect it; click the background to deselect.

Entity detail — slide-over panel

Click any node or row to open a panel showing its tags (all metadata, grouped by property), its lifespan, and every connector touching it — in a milestone-aligned table with a valid/total count. Clicking another entity switches directly; dismiss with , Esc, or an empty-area click.

Filtering — left rail

Filters are opt-out: every metadata value starts checked, and you uncheck the ones to hide. Filtering is collapsible per property, resets per property, and combines with AND across properties. Filtered-out elements are faded back rather than removed, so context stays intact.

Coloring — left rail

Pick one property to Color by. Morffy generates a stable color palette and legend for its values; an element with several values shows stacked color stripes. A great way to read “which team owns what” or “what's still on staging” at a glance.

Comparing milestones

Drag across the timeline strip to select a range — milestone X to milestone Y — and enter compare mode. Every element and connector is classified against those two points, tinted across the graph, the timeline rows, and the sidebar legend:

Added — appeared by Y Removed — gone by Y Unchanged — present in both

Compare composes with the metadata filter. Click a single milestone to exit compare mode.

Authoring the file

A Morffy diagram is one JSON or YAML file. Write it by hand, or let an AI generate it.

A minimal diagram needs a timeline, some elements, and the connectors between them. Icons are lucide icon names; metadata is whatever properties you want to track.

{
  "title": "Checkout service",
  "timeline": [
    { "id": "v1", "label": "v1" },
    { "id": "v2", "label": "v2" }
  ],
  "elements": [
    {
      "id": "api", "label": "Checkout API",
      "icon": "server", "type": "service",
      "metadata": { "team": ["payments"] }
    },
    {
      "id": "cache", "label": "Redis",
      "icon": "database", "type": "datastore",
      "lifespan": { "startMilestone": "v2" }
    }
  ],
  "connectors": [
    { "source": "api", "target": "cache", "label": "reads" }
  ]
}

Here cache declares no end, so it lives from v2 onward; the connector is automatically clamped to the window its two endpoints share.

Two accepted shapes

Morffy loads two file shapes and auto-detects which you gave it. The runtime shape above uses timeline, lifespan, source/target. The generator shape emitted by the AI skill uses milestones, sms/ems, and sourceId/targetId — Morffy converts it on load. Author in whichever you prefer; both render identically.

Generate with AI

Morffy ships a generator skill — morffy-dynamic-topology-generator — that turns an architecture narrative, PRD, or design transcript into a valid file. It runs a short consultation (which metadata properties to track, what the milestones are, how to caption element types) and then emits the JSON, ready to load.

Validation

Morffy checks every file it loads and tells you exactly what's wrong.

A validation badge in the top bar counts the issues; its popover lists each one with a humanized reason and a type chip. Issues also surface in the entity detail for the entity they affect. Three kinds of check run:

CheckWhat it catches
Schema Missing or malformed fields — anything that doesn't match the data model.
Connector lifecycle A connector must live within the overlap of its two endpoints. Spans that start before, outlive an endpoint, are empty, or reference a missing endpoint are flagged. Invalid connectors are hidden on the canvas.
Nesting The parent must exist; no self-parenting and no cycles; a child's lifespan must stay within its parent's.

A connector with no declared lifespan is not an error — Morffy clamps it to the window its endpoints share.

Data model reference

Fields in the runtime file shape. Only id and structural links are required.

Milestone

FieldNotes
idUnique identifier, referenced by lifespans.
labelShort display text (1–2 words).
descriptionOptional longer detail, shown on hover.

Element

FieldNotes
idUnique identifier.
labelName shown on the box.
iconA lucide icon name (kebab-case).
typeShort caption under the label (e.g. “service”).
parentIdOptional — nests this element inside a container.
lifespanOptional { startMilestone, endMilestone }; open ends span to first/last.
metadataOptional property → [values] tags.

Connector

FieldNotes
sourceId of the origin element.
targetId of the destination element.
labelOptional text on the arrow.
lifespanOptional; defaults to the endpoints' shared window.

CLI & shortcuts

Command

morffy <diagram.json|yaml> [--port <n>] [--no-open] [--no-watch]
morffy --validate <file>

Keyboard

KeyAction
Step to the previous / next milestone.
Page the timeline strip when milestones overflow.
EscClose the entity detail panel or a popover.
Morffy is open source (MIT). Runs 100% locally — your diagrams never leave your machine. · Home · Playground