Skip to content
design
Components

Mermaid

Render flowcharts, architecture and sequence diagrams across interfaces, documentation and reports.

On this page

Loading diagram…

Architecture from the supplied visual reference. Control connections are neutral, content paths contrast, and snapshot seeding is dashed.
Diagram source
flowchart LR
  subgraph clients[Clients]
    antique["<b>Antique</b>"]:::client
    developers["<b>Developer machines</b>"]:::client
    jobs["<b>CI and cluster jobs</b>"]:::client
  end
  server["<b>scion-server</b>"]:::service
  daemon["<b>scion-daemon</b><br/>Per node"]:::service
  cache["<b>scion-cache</b><br/>Regional"]:::service
  spanner["<b>Spanner</b><br/>Changesets,<br/>branches, trees"]:::storage
  storage["<b>Cloud Storage</b><br/>File contents"]:::storage
  snapshot["<b>Periodic snapshot</b>"]:::storage

  clients control@-->|"<b>Branches, history, diffs: upload, commit, land</b><br/><small>Control plane · every client</small>"| server
  developers content1@-->|"<b>Trees and file contents</b><br/><small>Object plane</small>"| cache
  jobs content2@--> daemon
  daemon content3@-->|"<b>Misses</b>"| cache
  cache content4@-->|"<b>Misses</b>"| server
  server metadata@--> spanner
  server files@--> storage
  snapshot seed@-.->|"<b>Seeds new nodes</b>"| daemon
  class content1,content2,content3,content4 dataflow
An architecture diagram uses grouped clients, softly tinted services and labeled paths. Open Desktop preview to inspect it on a larger display.
Code
import type { ReactElement } from "react";
import { Mermaid, type MermaidLayout } from "@bosunkit/components/mermaid";
export const description: string =
  "The supplied architecture reference, expressed as editable Mermaid with authored geometry: neutral clients and stores, blue services, contrasting content paths and a dashed snapshot dependency.";

// Coordinates describe the reference's diagram geometry, not CSS sizes. The shared renderer scales
// the complete drawing to the reading column and uses foundation tokens for every visual role.
const layout: MermaidLayout = {
  width: 1200,
  height: 512,
  boxes: {
    clients: { x: 39, y: 39, width: 231, height: 307, labelInset: [20, 11.5] },
    antique: { x: 58, y: 110, width: 92, height: 48, labelInset: [12, 10] },
    developers: { x: 58, y: 193, width: 192, height: 48, labelInset: [12, 10] },
    jobs: { x: 58, y: 276, width: 176, height: 48, labelInset: [12, 10] },
    server: { x: 752, y: 39, width: 169, height: 63, labelInset: [20, 16.5] },
    daemon: { x: 296, y: 266, width: 185, height: 80, labelInset: [20, 12.5] },
    cache: { x: 573, y: 159, width: 169, height: 187, labelInset: [20, 10.5] },
    spanner: { x: 993, y: 39, width: 169, height: 100, labelInset: [20, 16] },
    storage: { x: 993, y: 159, width: 169, height: 80, labelInset: [20, 16] },
    snapshot: { x: 296, y: 411, width: 185, height: 62, labelInset: [20, 20] },
  },
  routes: {
    control: {
      points: [
        [270, 70],
        [733, 70],
      ],
      label: { x: 296, y: 44.5, width: 440 },
    },
    content1: {
      points: [
        [250, 217],
        [567, 217],
      ],
      label: { x: 296, y: 188.5, width: 260 },
    },
    content2: {
      points: [
        [234, 300],
        [290, 300],
      ],
    },
    content3: {
      points: [
        [481, 306],
        [567, 306],
      ],
      label: { x: 499, y: 273.1, width: 80 },
    },
    content4: {
      points: [
        [742, 261],
        [837, 261],
        [837, 109],
      ],
      label: { x: 760, y: 228.1, width: 80 },
    },
    metadata: {
      points: [
        [921, 70],
        [987, 70],
      ],
    },
    files: {
      points: [
        [921, 70],
        [954, 70],
        [954, 199],
        [987, 199],
      ],
    },
    seed: {
      points: [
        [388, 411],
        [388, 352],
      ],
      label: { x: 323, y: 371, width: 145, mask: true },
    },
  },
};

export default function ReportArchitecture(): ReactElement {
  return (
    <Mermaid
      label="Reference architecture. Clients use scion-server for branches, history and diffs. Developer machines retrieve content through scion-cache; cluster jobs use scion-daemon. Cache misses reach the server. A periodic snapshot seeds the daemon."
      caption="Architecture from the supplied visual reference. Control connections are neutral, content paths contrast, and snapshot seeding is dashed."
      layout={layout}
      chart={`flowchart LR
  subgraph clients[Clients]
    antique["<b>Antique</b>"]:::client
    developers["<b>Developer machines</b>"]:::client
    jobs["<b>CI and cluster jobs</b>"]:::client
  end
  server["<b>scion-server</b>"]:::service
  daemon["<b>scion-daemon</b><br/>Per node"]:::service
  cache["<b>scion-cache</b><br/>Regional"]:::service
  spanner["<b>Spanner</b><br/>Changesets,<br/>branches, trees"]:::storage
  storage["<b>Cloud Storage</b><br/>File contents"]:::storage
  snapshot["<b>Periodic snapshot</b>"]:::storage

  clients control@-->|"<b>Branches, history, diffs: upload, commit, land</b><br/><small>Control plane · every client</small>"| server
  developers content1@-->|"<b>Trees and file contents</b><br/><small>Object plane</small>"| cache
  jobs content2@--> daemon
  daemon content3@-->|"<b>Misses</b>"| cache
  cache content4@-->|"<b>Misses</b>"| server
  server metadata@--> spanner
  server files@--> storage
  snapshot seed@-.->|"<b>Seeds new nodes</b>"| daemon
  class content1,content2,content3,content4 dataflow`}
    />
  );
}
01Editable diagramsKeep the source beside the drawing and explain the important relationships in prose.
02Readable in contextDiagrams follow the nearest theme and fit the reading column; expand provides access to dense labels.
03Local renderingThe renderer loads when a diagram approaches the viewport. Source remains available during loading and after an error.

Mermaid is a shared diagram component under Charts and displays. Use it for system boundaries, processes and conversations wherever an editable drawing helps explain relationships. Use the same renderer in report pages and application interfaces.

Diagram style

The shared renderer uses spacious flowchart ranks, rounded boxes and connectors, quiet group panels and foundation typography. The diagram canvas has a rounded border and room around the drawing. Use a wide figure area for architecture diagrams, while keeping the explanation within a comfortable reading measure.

Use Mermaid subgraphs for system boundaries and label the connections with what moves between them. Dashed connections can show a different relationship, such as snapshot seeding; explain that distinction nearby.

The renderer supplies these optional classes from foundation diagram roles. No color values are needed in the source. An authored classDef dataflow takes precedence over the connection preset.

ClassUseAppearance
serviceNamed software servicesSoft blue fill and outline; bold names use the code face
clientPeople or client applicationsNeutral outlined boxes
storageDurable stores and snapshotsNeutral outlined boxes, with an explicit role in the label
dataflowA named content pathContrasting connector; retain a text label

Loading diagram…

Diagram source
flowchart LR
  client[Reader]:::client
  service["<b>report-service</b><br/>Content delivery"]:::service
  client content@-->|Report content| service
  class content dataflow

The blue and contrasting connection colors follow the active theme, including the subdued Night palette. A color is not a status or alert priority. Existing authored style, classDef and configuration remain part of the source. Ordinary diagrams use Mermaid's automatic arrangement.

Authored layouts

Use the optional layout prop when an architecture diagram needs a deliberate composition like the hero above. It describes a drawing width and height, boxes keyed by node/subgraph IDs, and connector routes keyed by explicit edge IDs (content@-->). Coordinates are units within the drawing; the complete SVG scales to the page. Labels, relationships, colors, line patterns and arrow types come from Mermaid and the shared renderer.

Each route supplies its ordered bend points and, when labeled, the label's top-left position and available width. The renderer rounds bends, preserves HTML line breaks and aligns labels to the left. Every rectangular node, subgraph and edge needs a placement. Unknown or missing IDs show the unavailable state with the source retained, so adding a node cannot silently hide it. Other diagram types use Mermaid's native layout and notation.

The hero's source panel includes its complete placement data. Source disclosure and Markdown exports retain the Mermaid relationships; exact authored placement belongs to the JSX layout object. The reference's geometry and palette guide the example. Foundation diagram type roles use a neutral sans serif for labels and the shared code face for service names; diagram colors and spacing continue to follow the surrounding theme.

Details on nodes and lines

details lets a reader open what a node or a line stands for. Each entry is keyed as the source names it: a node by its id (bosund), a line by its ends (bosund-->db, the first such line) or by its own id (content@-->). It opens a tooltip on hover or focus, a popover beside it on a press, or a dialog for more than a few lines. Each gets a clear target over its node, or over its line's label; a line without a label gets a round target on its middle. The targets are buttons named by their titles, in the order of the keys, and follow the drawing when it is expanded or the page is resized. A key that names nothing in the diagram gets no target. The diagram keeps its description, and the relationships belong in nearby prose too.

Loading diagram…

Diagram source
flowchart LR
  crew["Crew"] -->|"asks"| bosund["bosund"]
  bosund -->|"replies"| crew
  bosund --> db[(SQLite)]
A diagram whose parts open their details: point at or tab to bosund for a tooltip, press the Writes line or the Replies line for a popover, and press SQLite for a dialog.
Code
import type { ReactElement } from "react";
import { Mermaid, type MermaidDetail } from "@bosunkit/components/mermaid";

export const description: string =
  "A diagram whose parts open their details: point at or tab to bosund for a tooltip, press the Writes line or the " +
  "Replies line for a popover, and press SQLite for a dialog.";

const CHART: string =
  'flowchart LR\n  crew["Crew"] -->|"asks"| bosund["bosund"]\n  bosund -->|"replies"| crew\n  bosund --> db[(SQLite)]';

const DETAILS: Readonly<Record<string, MermaidDetail>> = {
  bosund: { open: "tooltip", title: "bosund", content: "The daemon on the vessel: voice, chat and every lookout." },
  "crew-->bosund": { open: "popover", title: "Asks", content: "By voice at the helm, or in the chat on a phone." },
  "bosund-->crew": { open: "popover", title: "Replies", content: "Spoken and written, usually within two seconds." },
  "bosund-->db": { open: "popover", title: "Writes", content: "Readings to history.db, the ship's log to bosun.db." },
  db: {
    open: "dialog",
    title: "SQLite",
    content:
      "Five files in the data directory: bosun.db for what the crew typed, history.db for what the instruments " +
      "measured, cep.db, state.db and cache.db for what can be rebuilt.",
  },
};

export default function Details(): ReactElement {
  return <Mermaid label="The crew ask bosund, which replies and writes to SQLite." chart={CHART} details={DETAILS} />;
}

Decision flow

Loading diagram…

Diagram source
flowchart LR
  Source[Source evidence] --> Review{Reviewed?}
  Review -->|Yes| Report[Report]
  Review -->|No| Followup[Follow-up]
An illustrative review flow, with source disclosure and expand/fit controls.
Code
import type { ReactElement } from "react";
import { Mermaid } from "@bosunkit/components/mermaid";
export const description: string = "An illustrative review flow, with source disclosure and expand/fit controls.";
export default function ReviewFlow(): ReactElement {
  return (
    <Mermaid
      label="Evidence is reviewed before publication; incomplete evidence returns for follow-up."
      chart={
        "flowchart LR\n  Source[Source evidence] --> Review{Reviewed?}\n  Review -->|Yes| Report[Report]\n  Review -->|No| Followup[Follow-up]"
      }
    />
  );
}

Markdown fences

Both sites register Fumadocs’ remarkMdxMermaid transform and the shared @bosunkit/components/mermaid renderer. A fenced block and explicit JSX use the same component. No CDN or diagram service receives the source.

```mermaid
sequenceDiagram
  participant Author
  participant Reviewer
  Author->>Reviewer: Evidence and draft
  Reviewer-->>Author: Findings and questions
```

Loading diagram…

Diagram source
sequenceDiagram
  participant Author
  participant Reviewer
  Author->>Reviewer: Evidence and draft
  Reviewer-->>Author: Findings and questions

The reviewer receives the draft and its evidence, then returns findings and questions. For a specific accessible name or a caption, use <Mermaid chart={source} label="Description of the relationships" caption="Source context" />.

Scoped themes

Loading diagram…

Day scope
Diagram source
flowchart LR
  Collect --> Review

Loading diagram…

Night scope
Diagram source
flowchart LR
  Collect --> Review
Independent Day and Night scopes use their own palettes on the same page.
Code
import type { ReactElement } from "react";
import { PresentationScope } from "@bosunkit/provider";
import { Mermaid } from "@bosunkit/components/mermaid";
import { ReportGrid } from "@bosunkit/components/report-blocks";
export const description: string = "Independent Day and Night scopes use their own palettes on the same page.";
export default function DiagramScopes(): ReactElement {
  return (
    <ReportGrid>
      <PresentationScope theme="day">
        <Mermaid caption="Day scope" label="Day review flow" chart={"flowchart LR\n  Collect --> Review"} />
      </PresentationScope>
      <PresentationScope theme="night">
        <Mermaid caption="Night scope" label="Night review flow" chart={"flowchart LR\n  Collect --> Review"} />
      </PresentationScope>
    </ReportGrid>
  );
}

Night, Dusk, Day and Bright use foundation tokens. Explicit colors authored inside a diagram can override those roles; omit custom colors when the diagram should follow the site theme. Separate scopes render independently.

Inspection and unavailable states

Expand preserves the drawing’s natural width inside a horizontal scroll region. Fit returns it to the column. The controls are keyboard buttons and expose their pressed state. Print fits the drawing and hides the button. Malformed source shows a readable error and retains the source disclosure. Rendering uses Mermaid’s strict mode; do not rely on embedded HTML or diagram click handlers for essential content.

Props

PropTypeDefaultDescription
chartrequiredstring–Mermaid source with authored newlines. Rendered locally with strict security.
labelstring–Accessible description of the diagram; a generic translated name is the fallback.
captionstring–Optional visible caption. Put detailed relationships in nearby prose too.
layoutMermaidLayout–Optional complete box/route geometry for rectangular flowcharts; IDs match the editable source.
detailsReadonly<Record<string, MermaidDetail>> | undefined–What the reader can open from the diagram's nodes and lines, keyed as the source names them: a node by its id (bosund), a line by its ends (bosund-->db, the first such line) or by its own id (content@-->). Each gets a target over it, a button in the reading order of these keys; a key that names nothing in the diagram gets none.
Do

Publication follows review; incomplete evidence returns to its author.

Explain the relationship in text as well as the drawing.
Don't

Name each branch, keep source text and provide a nearby explanation.

Do not make color or a tiny diagram the only source of meaning.