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:
| Flag | Effect |
|---|---|
--port <n> | Serve on a specific port (default 4173). |
--no-open | Don't open the browser automatically. |
--no-watch | Load once; skip live reload. |
--validate | Check 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:
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:
Compare composes with the metadata filter. Click a single milestone to exit compare mode.
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:
| Check | What 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
| Field | Notes |
|---|---|
id | Unique identifier, referenced by lifespans. |
label | Short display text (1–2 words). |
description | Optional longer detail, shown on hover. |
Element
| Field | Notes |
|---|---|
id | Unique identifier. |
label | Name shown on the box. |
icon | A lucide icon name (kebab-case). |
type | Short caption under the label (e.g. “service”). |
parentId | Optional — nests this element inside a container. |
lifespan | Optional { startMilestone, endMilestone }; open ends span to first/last. |
metadata | Optional property → [values] tags. |
Connector
| Field | Notes |
|---|---|
source | Id of the origin element. |
target | Id of the destination element. |
label | Optional text on the arrow. |
lifespan | Optional; defaults to the endpoints' shared window. |
CLI & shortcuts
Command
morffy <diagram.json|yaml> [--port <n>] [--no-open] [--no-watch]
morffy --validate <file>
Keyboard
| Key | Action |
|---|---|
| ← → | Step to the previous / next milestone. |
| ‹ › | Page the timeline strip when milestones overflow. |
| Esc | Close the entity detail panel or a popover. |