Files
gstack/docs/howto-diagrams-and-formats.md
T
SinaandClaude Fable 5.1 f7d68c253e docs: Aside first, gstack browser fallback
README, BROWSER.md, docs/, CONTRIBUTING, CLAUDE.md, ARCHITECTURE, AGENTS.md, TODOS and the root router describe the one product story: Aside is the browser gstack drives first; the bundled headless browser is the automatic fallback (Linux, Windows, app closed) where cookie import, GStack Browser, pair-agent and browser-skills still apply.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-05 16:48:38 -04:00

6.2 KiB

How to put diagrams in your documents (and export beyond PDF)

This guide covers the diagram + multi-format engine that ships with /make-pdf and /diagram (v1.58.0.0+). Everything here runs fully offline: the mermaid and excalidraw runtimes are vendored in lib/diagram-render/ and loaded into a browser by bin/gstack-render.ts, which serves the bundle from your machine on loopback for the length of one render. No CDN, no network at render time. The browser is your Aside browser when it is open (macOS 15+); when it is not — Linux, Windows, or the app closed — the same bundle renders in gstack's own bundled browser, so it renders offline on every platform (PNGs come out at 1x on the fallback, 2x through Aside).

Render a mermaid diagram inside a PDF

Put a fence in your markdown. That's it.

```mermaid title="Render pipeline"
graph LR
  A[markdown] --> B[prepass]
  B --> C[browser]
  C --> D[PDF]
```
make-pdf generate doc.md out.pdf

The fence renders as a vector diagram (crisp at any zoom, selectable text), with the title as caption and accessibility label. The raw mermaid source is preserved base64-encoded in a data-gstack-source attribute on the figure for debugging and round-trips (an HTML comment would corrupt mermaid's --> arrows). One catch: the fence must start at column 0 — indented fences (inside lists, for example) stay plain code blocks by design.

Fence options (space-separated in the info string):

Option Effect
title="..." caption below the diagram + aria-label
render=false keep the fence as a plain code block
page=landscape force this diagram onto its own landscape page
page=portrait veto auto-landscape for this diagram

A fence that fails to parse renders as a loud red diagnostic block with the parse error and source excerpt — your document still builds, and the error is impossible to miss.

```excalidraw fences work the same way; the body is a full .excalidraw scene file (what excalidraw.com saves with File → Save).

Control image size and orientation

Local images are inlined automatically (relative paths resolve against the markdown file) and never truncate — every image caps at the content box. Oversized photos downscale to print resolution (300dpi at the content width), so a phone photo doesn't bloat the document.

Image safety defaults: remote (http/https) images are blocked with a visible placeholder unless you pass --allow-network. An image path that resolves outside the markdown's directory (even through a symlink) still inlines but warns loudly. Files over 64MB and non-regular files (fifos, devices) degrade to a placeholder instead of hanging the render.

Per-image directives go immediately after the image:

![quarterly chart](chart.png){width=full}
![logo](logo.png){width=2in}
![wide architecture](arch.png){page=landscape}
![wide screenshot](shot.png){page=portrait}

width= accepts full, a percentage (50%), or a dimension (3in, 8cm, 200px). page= forces or vetoes a dedicated landscape page.

Auto-landscape: a wide, small-text, diagram-like image gets its own vertically-centered landscape page automatically — inside an otherwise portrait document. The heuristic is deliberately conservative (aspect ratio ≥ 1.8, intrinsic width over ~2.5x the content box, and a diagram-ish alt word: diagram / architecture / flowchart / chart / graph). If it doesn't fire when you want it, add {page=landscape}; if it fires when you don't, add {page=portrait}.

Export single-file HTML or Word

make-pdf generate doc.md out.html --to html
make-pdf generate doc.md out.docx --to docx
  • --to html writes ONE self-contained file: diagrams as inline SVG, images as data URIs, zero network references (under the default offline posture — --allow-network deliberately keeps remote image tags live), plus a screen-reading layer (centered measure, padding). Email it, attach it, open it anywhere.
  • --to docx is a content-fidelity export: headings, tables, code blocks, lists, and diagrams (embedded as 300dpi PNGs with alt text) carry over. Page-perfect layout does not — that's Word's job once it's open.

Heads-up: --to is the output format. --format is an old alias for --page-size — different thing.

Generate a diagram from English

/diagram make a flowchart of our deploy pipeline: build, test, canary, promote

The skill authors mermaid and emits a triplet:

File Use it for
<slug>.mmd the source of truth — edit and re-render
<slug>.excalidraw open at excalidraw.com (File → Open), move boxes, hand back
<slug>.svg / <slug>.png docs, issues, READMEs, chat

Flowcharts convert to fully editable excalidraw scenes. Other mermaid types (sequence, state, gantt) render to SVG/PNG fine but skip the .excalidraw artifact — an upstream converter limitation the skill will tell you about.

For documents, embed the .mmd source in your markdown instead of the PNG — /make-pdf renders it as vector and the diagram stays editable forever.

CI: fail loud instead of shipping placeholders

make-pdf generate docs.md --strict

Missing local images, blocked remote images, out-of-tree image reads (a path or symlink resolving outside the markdown's directory), oversized files (>64MB), and non-regular files all exit non-zero instead of degrading to a warning or placeholder — for docs pipelines where a broken image should break the build.

Troubleshooting

  • "diagram-render bundle not found" → run bun run build:diagram-render in the gstack repo, or re-run ./setup.
  • Diagram renders but looks squished inline → it's wide; give it room with page=landscape on the fence.
  • A two-row "racetrack" loop instead of one long line: mermaid subgraph trick — top-level flowchart TB, two subgraphs with direction LR and direction RL, connect the subgraphs (node-level edges across subgraph boundaries silently disable direction).
  • "[remote image blocked]" placeholder → remote images are never fetched by default (offline posture); the tag is replaced with a visible placeholder so the browser can't fetch it at print time either. Pass --allow-network to opt in.