Trazo docs

Quick Start

Get up and running with Trazo in minutes.

Trazo is a deterministic code-to-diagram layout engine — flowcharts and git graphs. Pure-TypeScript core with an optional React SVG renderer.

Install

pnpm add @joycostudio/trazo

Flowchart

import { layoutFlow } from "@joycostudio/trazo";
import { Graph } from "@joycostudio/trazo/react";

const graph = layoutFlow({
  kind: "flow",
  nodes: [
    { id: "a", label: "Request", shape: "stadium", role: "primary" },
    { id: "b", label: "Process" },
    { id: "c", label: "Done", shape: "stadium", role: "success" },
  ],
  edges: [
    { from: "a", to: "b" },
    { from: "b", to: "c" },
  ],
});

// React (or any React Server Component):
<Graph graph={graph} title="My flowchart" />

Git graph

import { layoutGit } from "@joycostudio/trazo";

const graph = layoutGit({
  commits: [
    { id: "c1", parents: [],       message: "Initial commit" },
    { id: "c2", parents: ["c1"],   message: "Add feature",   branch: "feat/x" },
    { id: "c3", parents: ["c1"],   message: "Hotfix",        branch: "main" },
    { id: "c4", parents: ["c3", "c2"], message: "Merge feat/x" },
  ],
});

<Graph graph={graph} title="Commit history" />

From playground to code

The playground uses the same layout engine you call from TypeScript. Copy a diagram from the editor and translate it line-by-line to the API.

Flow DSL → layoutFlow

Each node line becomes a FlowNode, each arrow becomes a FlowEdge:

flow TD
A(["Request"]):primary ==> B["Process"]
B --> C["Done"]:success
layoutFlow({
  kind: "flow",
  nodes: [
    { id: "A", label: "Request", shape: "stadium", role: "primary" },
    { id: "B", label: "Process" },
    { id: "C", label: "Done",    role: "success" },
  ],
  edges: [
    { from: "A", to: "B" },
    { from: "B", to: "C" },
  ],
})

DSL shapes map to shape: [box]"box", (["stadium"])"stadium", {diamond}"diamond", [("cylinder")]"cylinder". :role suffixes map to role. ==> (thick arrow) maps to colored: true on the edge.

Git DSL → layoutGit

The DSL is imperative (branch/checkout/merge statements that build the graph as you go). The API is declarative — you provide the final commit graph directly, with explicit parents arrays:

commit a1 (Alice) : Initial commit
branch feat/x
commit b1 (Bob) : Add feature
checkout main
merge feat/x : Merge
layoutGit({
  commits: [
    { id: "a1", parents: [],           hash: "a1", author: "Alice", message: "Initial commit", branch: "main" },
    { id: "b1", parents: ["a1"],       author: "Bob",               message: "Add feature",   branch: "feat/x" },
    { id: "m1", parents: ["a1", "b1"],                              message: "Merge",          branch: "main" },
  ],
})

parents[0] is always the mainline parent. A merge commit has two or more parents — mainline first, merged-in branch second.


Key properties

  • Pure TypeScript. No DOM, no canvas, no window. The layout runs in Node just as well as in the browser — identical output on server and client.
  • Deterministic. Equal input always produces the same PositionedGraph. Safe for SSR: the server-rendered SVG and the first client render are byte-identical, so there are no hydration mismatches.
  • <Graph> is a pure function of props. No hooks, no effects, no browser globals — use it in a React Server Component and ship zero client JS for the diagram.

Playground

Try it interactively at / — the playground renders the SVG on the server and hydrates for live editing.

On this page