Embedding diagrams

Put a Marrow diagram inside an existing docs site, wiki, or portal — and keep it current in CI.

A built diagram is an HTML document, not a fragment. That makes embedding simple and slightly opinionated: you embed it in an <iframe> rather than splicing its markup into your page.

The basic embed

<iframe
  src="/diagrams/branch.html"
  title="Branch office network"
  loading="lazy"
  style="width:100%; height:640px; border:1px solid #27272a; border-radius:12px"
></iframe>

That's the whole integration. The diagram brings its own styles and runtime, so it cannot collide with your site's CSS — which is exactly why the iframe is the right container rather than a limitation.

Height matters more than width. A network diagram in a 300 px strip is unreadable; 560–720 px is a sensible range for an inline figure, and a full-viewport height for a dedicated page.

Theme

A diagram carries the theme from its topology's theme: key — dark, light, or auto. In an embed you usually want it to match the host page, and there are two ways to get that without rebuilding the file.

Follow the viewer's OS — theme: auto

theme: auto

The diagram resolves dark/light from the viewer's prefers-color-scheme before it paints, and switches live if they change it. No host code — a sensible default for a diagram embedded on a site that itself follows the OS.

Follow the host's own toggle — postMessage

If your page has its own light/dark switch, drive the diagram over postMessage. The diagram announces itself when its runtime is ready; answer with the theme, and re-send whenever yours changes:

const frame = document.querySelector('iframe.marrow');

addEventListener('message', (e) => {
  if (e.data?.type === 'marrow:ready') sendTheme();   // answer the ready ping
});
function sendTheme() {
  const theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
  frame.contentWindow.postMessage({ type: 'marrow:theme', theme }, '*');
}

The message is { type: 'marrow:theme', theme: 'dark' | 'light' | 'auto' }. A host-driven theme overrides the baked theme: and isn't persisted — opening the same file standalone still shows its authored theme — and it works whatever theme: the file was built with.

Linking straight to a device

Multi-page sites have real URLs, so you can deep-link:

/diagrams/global/index.html              overview
/diagrams/global/zones/campus.html       one zone
/diagrams/global/devices/core-sw-01.html one device
/diagrams/global/inventory.html          the table

Linking to a device page from a runbook is often more useful than embedding the whole diagram.

Content Security Policy

The output loads nothing external, so a strict policy is fine. What it does need is inline styles and inline script — everything is inlined by design:

frame-src 'self';

on the host page, and for the diagram document itself:

default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; script-src 'unsafe-inline';

Keeping it current in CI

The diagram is generated, so treat it like any other build artifact. A minimal GitHub Actions job:

.github/workflows/diagrams.yml
name: diagrams
on:
  push:
    paths: ['input/**.yaml']

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 24 }
      - run: npm ci && npm run compile
      - run: npm run marrow -- icons fetch --yes      # if you use cloud packs
      - run: npm run marrow -- validate input/*.yaml  # exit 1 on errors
      - run: npm run marrow -- build input/branch.yaml -o site/diagrams/branch.html
      - uses: actions/upload-artifact@v4
        with: { name: diagrams, path: site/diagrams }

validate exits 1 on validation errors and 2 on usage or I/O errors, so it gates a pipeline correctly with no extra scripting. Add --json if you want to post the diagnostics somewhere.

Because output is deterministic, committing the built HTML produces a clean diff: the file only changes when the topology actually changed.

Where this is going

A live, in-page editor — YAML on the left, diagram on the right — is a natural next step for this documentation site and isn't built yet. The embedding story above is the durable part; the demo is additive.