asopi tech
asopi techIndie Developer
Embedding Pikchr Diagrams in Astro Markdown: Build-Time SVG Conversion

[October 2026 edition]

Embedding Pikchr Diagrams in Astro Markdown: Build-Time SVG Conversion

Published: Oct 13, 2026
Reading time: ~5 min

I like PlantUML and Mermaid and often use them locally. But I had not used their UML diagrams on this Astro site because every change would require exporting and replacing an image. A rasterized diagram also makes its change history difficult to follow.

So I added Pikchr to this Astro site and implemented a build-time conversion from diagrams referenced in Markdown to SVG. Pikchr describes diagrams as text and generates SVG. The integration that calls a diagram from Markdown and adds it to the Astro build is specific to this site.

What is Pikchr?

Pikchr is a language for writing technical-documentation diagrams as text, developed by SQLite creator D. Richard Hipp. The official Pikchr source states that Hipp wrote the implementation from scratch without consulting the code of existing PIC implementations.

Beginning with version 3.34.0, SQLite’s official documentation has generated its syntax-diagram SVGs with Pikchr. Pikchr can generate SVG from descriptions of boxes, lines, arrows, labels, and their spatial relationships for use in documents such as Markdown.

The elements of a diagram are defined as text:

box "Rust embedded" wid 1.5 ht 0.55
box "Python" at last box + (1.62,0) wid 1.5 ht 0.55
arrow down from first box.s
box "SQL" wid 4.2 ht 0.5

Because coordinates, labels, and colors are text, their changes can be reviewed like code. This site stores the .pik files for static architecture diagrams in src/diagrams and tracks them with Git.

A Pikchr diagram displayed on this site

This architecture diagram also appears on the Alopex DB product page.

Rust embedded Python CLI HTTP server gRPC server DataFrame SQL Direct APIs Core Transactions Storage engine Vector search Columnar Single file (.alopex) Cluster (Chirps)

Both the Alopex DB features page and this article reference the same .pik file. One diagram remains the source of truth across multiple pages.

SVG generation is part of Astro’s Markdown processing. The .pik file is the source of truth, and both npm run dev and npm run build use the same process to embed SVG in each page’s HTML.

Referencing a diagram like an image in Markdown

The article uses ordinary Markdown image syntax. Instead of an image URL, it writes the name of a diagram from src/diagrams after pikchr:.

![Alopex DB architecture diagram](pikchr:alopex-architecture.en)

The article does not need to contain the Pikchr source or HTML. Its author specifies only the diagram name and alternative text.

Astro can extend Markdown processing with remark plugins. I used that mechanism to implement a site-specific remarkPikchr plugin for the pikchr: syntax. Pikchr describes and renders the diagram, Astro provides the extension point, and remarkPikchr connects them.

Converting to inline SVG with a remark plugin

The Astro Markdown configuration registers remarkPikchr alongside the existing plugins for code titles, reading time, and terminal videos.

markdown: {
  processor: unified({
    remarkPlugins: [
      remarkCodeTitles,
      remarkReadingTime,
      remarkTerminalVideo,
      remarkPikchr,
    ],
  }),
},

remarkPikchr walks the Markdown syntax tree and looks for a single pikchr: image in a paragraph. It reads the named .pik file from src/diagrams and passes it to the pinned pikchr-wasm package, the WebAssembly version of Pikchr, to generate SVG.

.pik Markdown remark SVG

The central transformation replaces the Markdown image node with an HTML node containing the SVG returned by Pikchr.

const img = child.type === 'paragraph' && child.children?.length === 1
  ? child.children[0]
  : undefined;

if (img?.type === 'image' && img.url?.startsWith('pikchr:')) {
  const name = img.url.slice('pikchr:'.length);
  jobs.push(renderDiagram(name, img.alt ?? '').then((svg) => {
    node.children![i] = { type: 'html', value: svg };
  }));
}

The resulting page contains the <svg> itself rather than an img element that loads an external SVG file. The page can display the diagram from its HTML alone, while site CSS controls its width and dark-mode colors.

Adding the information needed by the site

After pikchr-wasm generates the SVG, the plugin adds information needed to display and use it on the site.

  • Pass the Markdown alternative text to the SVG’s aria-label and add role="img"
  • Embed a font stack that can display Japanese in Japanese diagrams
  • Add a shared arch-diagram class so articles and product pages use the same presentation
  • Restrict diagram names to ASCII letters and digits, periods, hyphens, and underscores

The alternative text is escaped before it enters an HTML attribute. Restricting diagram names prevents Markdown from selecting files outside src/diagrams.

The following code adds the font and accessibility attributes to the SVG.

svg = svg
  .replace(
    '<svg ',
    `<svg class="arch-diagram" role="img" aria-label="${escapeAttr(alt)}" `,
  )
  .replace(
    /(<svg[^>]*>)/,
    `$1<style>text{font-family:${font};font-size:24px}</style>`,
  );

Each diagram supplies its Pikchr source and alternative text. The plugin handles shared display attributes and Japanese fonts.

Failing the Astro build when a diagram is broken

When Pikchr source contains a syntax error, pikchr-wasm returns an error message instead of SVG. The plugin checks that the output starts with <svg and fails the Astro build if any diagram cannot be converted.

let svg = await pikchr.render(source);
if (!svg.startsWith('<svg')) {
  throw new Error(`Pikchr error in ${file}:\n${svg}`);
}

This makes npm run dev report errors during development and lets npm run build detect broken diagrams before publication. It also prevents the Pikchr source and the published result from silently falling out of sync.

Separate mechanisms for animated and static diagrams

This site uses Starch for animated diagrams and Pikchr for static architecture diagrams.

Starch reads its DSL in the reader’s browser and updates SVG according to the playback position. Because it offers controls such as play, pause, and seek, the site displays it through an <animated-diagram> custom element.

Pikchr diagrams are converted to SVG during the Astro build, and that SVG is sent to the reader’s browser. In Markdown, they can be placed like images. The site chooses the conversion point and embedding method according to whether the diagram moves or presents static information.

Summary

This site references Pikchr architecture diagrams from Astro Markdown and converts them to inline SVG at build time. Pikchr renders the diagram, Astro provides the Markdown extension point, and a site-specific remark plugin connects them.

  • Store each diagram’s source of truth as a .pik file in src/diagrams
  • Select the diagram in Markdown with ordinary image syntax and a pikchr: URL
  • Convert it to SVG with pikchr-wasm in a remark plugin
  • Add alternative text, fonts, and a shared class to the SVG
  • Detect Pikchr syntax errors during the Astro build

After changing a diagram, updating the .pik file and running the Astro build are enough to carry the change through to the published page.

References