# Diagrams in Markdown and on GitHub

> Page: https://docs.plotwork.dev/markdown-and-github. Index of every page: https://docs.plotwork.dev/llms.txt

How a `diagram` fence in a Markdown file becomes a picture that GitHub displays, and how to keep it current. It is for anyone adding diagrams to a README or a doc.

## TL;DR

| Rule | Yes | No |
|---|---|---|
| Source | Write a `diagram` fence and have your agent sync the file with `sync_markdown` | Paste SVG by hand |
| Pictures | Commit the generated `.svg` and `.dark.svg` files | Leave them out of git; the page would show broken images |
| Freshness | Run `npx @buun_group/plotwork sync --check` in CI; see [Keep diagrams in sync in CI](https://docs.plotwork.dev/diagrams-in-ci.md) | Trust that nobody forgot to sync |
| Edits | Change the fence, then sync | Edit the generated block between the markers |
| Paths | Keep the pictures in `assets/diagrams` next to the document, or choose a folder with `assetsDir` | Move the files without syncing again |

## 1. What GitHub does and does not render

GitHub draws Mermaid fences itself, in the page. It does not draw custom fences, and it will not run a renderer for them. Plotwork therefore renders before commit: the picture is a file in the repository, and the Markdown refers to it.

**Diagram source**

```diagram
flow "From fence to picture" desc="An author writes a diagram fence, sync renders it to SVG files and a picture block, and GitHub shows the picture."

node author person   "Author or agent"      sub="Writes a diagram fence"
node sync   function "sync_markdown"        sub="Parses, lays out, renders"
node svgs   storage  "SVG files"            sub="Light and dark, committed"
node block  step     "Picture block"        sub="Inserted under the fence"
node github terminal "GitHub page"          icon=status:success

author -> sync  : "Markdown file"
sync   -> svgs  : "writes" role=data
sync   -> block : "writes" role=data
svgs   -> github : "loaded by"
block  -> github : "references"
```

*Picture: From fence to picture: 5 nodes, 5 connections. An author writes a diagram fence, sync renders it to SVG files and a picture block, and GitHub shows the picture.*

**Text description**

**Nodes:**

- Author or agent (Writes a diagram fence), person
- sync_markdown (Parses, lays out, renders), function
- SVG files (Light and dark, committed), storage
- Picture block (Inserted under the fence), step
- GitHub page, terminal

**Connections:**

- Author or agent to sync_markdown: Markdown file
- sync_markdown to SVG files (stored data line): writes
- sync_markdown to Picture block (stored data line): writes
- SVG files to GitHub page: loaded by
- Picture block to GitHub page: references

## 2. What a sync produces

For each top-level `diagram` fence, a sync makes four changes. `sync_markdown` reads and writes no file itself: it returns the rewritten document and the SVG files, and the caller, usually your agent, saves them.

| Change | Where | Purpose |
|---|---|---|
| A collapsed "Diagram source" section | Around the fence | Readers see the picture first and can open the source. |
| A picture block | Directly under the section | An HTML `picture` element: the light SVG by default, the dark SVG when the reader's color scheme is dark. |
| A collapsed "Text description" | Inside the picture block | The diagram as plain text, so it can be read without the image and by tools that skip images. |
| Two SVG files | `assets/diagrams/<id>.svg` and `<id>.dark.svg` next to the document | The pictures. The id comes from the diagram title. |

The picture block starts and ends with marker comments and carries a hash. The hash covers the source and the rendered output, so a change to the diagram or to the renderer makes the block stale and the next sync rewrites it. Do not edit between the markers.

A fence that is indented, for example inside a list item, is still rendered but is not wrapped in the collapsed section.

A picture written by a sync carries its diagram source in its metadata, so `read_diagram` can give the source back from the picture alone. See [Editing an existing diagram](https://docs.plotwork.dev/editing-existing-diagrams.md).

## 3. Running a sync

Ask your agent: "Render the diagrams in README.md". The agent sends the whole file and its path to `sync_markdown`, then writes the `markdown` it gets back over the file and each entry of `files` at its `path`. The local server does this with no key and no account. The same operation is `POST /v1/markdown/sync` over HTTP, which needs an API key and the Pro plan; the [quick start](https://docs.plotwork.dev/quick-start.md#8-without-an-agent-markdown-and-the-http-api) has a request you can run.

| Input | What it does |
|---|---|
| `markdown` and `documentPath` | The whole document as it is on disk, and where it lives, relative to the repository root with forward slashes. Picture links and file paths are worked out from the path. |
| `mode` | `sync`, the default, returns the rewritten document and the files to write. `check` changes nothing and reports whether a picture is stale. |
| `assetsDir` | The folder for the SVG files, relative to the repository root. The default is `assets/diagrams` next to the document. |
| `prefix` | Starts every picture file name with this text. Use it when several documents share one asset folder. |
| `convertMermaid` | When true, every Mermaid fence that can be converted becomes a `diagram` fence first. See [Migrating from Mermaid](https://docs.plotwork.dev/migrating-from-mermaid.md). |

A diagram with an error is a normal result, not a failure: its fence is left as it was, the report names its line and column inside the document with a hint, and the other fences still sync. The limits on the size of a document are in the [tool reference](https://docs.plotwork.dev/mcp/tools/sync-markdown.md).

## 4. Where the pictures show up

| Place | Expected | Note |
|---|---|---|
| GitHub README and Markdown files | Yes | GitHub documents the `picture` element with a color-scheme source for light and dark images. |
| Editor preview (VS Code and similar) | Yes | Relative image paths load in the preview. |
| npm package page | Uncertain | npm may refuse to show SVG images in a README. |
| MCP (Model Context Protocol) clients | No | A client receives text and cannot show an SVG. Use `outline_diagram` for the text form. |
| GitLab and other hosts | Probably | They need to allow SVG in an image tag. |

## 5. Check your page after you push

| Check | What to look for |
|---|---|
| Light mode | The light picture loads and the text is crisp. |
| Dark mode | Switching GitHub to a dark theme loads the dark picture, with readable text and visible lines. |
| Phone width | The picture scales down to the screen and does not scroll sideways. |
| Collapsed sections | "Diagram source" and "Text description" open and show their content. |
| Nested folders | A picture in a subfolder loads; its path goes up to the shared assets folder, for example `../assets/diagrams`. |
| Alt text | Hovering or using a screen reader gives the diagram's summary. |

Most failures come from a path that points outside the repository or from a picture file that was not committed.

## 6. Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| The page shows a broken image | The SVG is not committed, or the path moved | Sync the file again, then commit the SVG files next to the document. |
| A check with `mode` set to `check` says a block is stale | The fence or the renderer changed | Sync the file again and commit the result. |
| An SVG is left over after a diagram was renamed or removed | A sync returns pictures and never deletes old ones | Delete the unused files. |
| The fence shows as plain code on GitHub | The file was never synced | Sync it, write the result, and commit. |
| Two documents show each other's picture | Same title in a shared asset folder | Give each document its own `prefix`. |

## See also

| Doc | Why |
|---|---|
| [Writing diagrams](https://docs.plotwork.dev/writing-diagrams.md) | The language by example |
| [Writing diagrams with an agent](https://docs.plotwork.dev/mcp/agent-loop.md) | The validate and fix loop |
| [How a diagram is drawn](https://docs.plotwork.dev/how-it-works.md) | How source becomes SVG |
