asopi tech
asopi techIndie Developer
Embedding Animated Diagrams in Astro Markdown with Starch

[August 2026 edition]

Embedding Animated Diagrams in Astro Markdown with Starch

Published: Aug 19, 2026
Reading time: ~4 min

We introduced animation as a way to explain abstract concepts and complex processing flows more clearly in blog articles.

On this site, we added an <animated-diagram> component that displays diagrams defined with the Starch DSL in Markdown. This article presents the actual result and how we wrapped Starch for the site.

What is Starch?

Starch is a DSL for defining shapes, paths, and changes over time as text, then rendering an animated diagram in the browser from that definition.

Shapes and paths go in objects, and time-based changes go in animate. In the following example, a packet moves from the start of a path to its end over two seconds.

DSL

name "Starch basics"
background #071015
viewport 480x260

style routeStyle
  stroke #557c50 width=3

objects
  route: path (60,120) (420,120) @routeStyle
  packet: ellipse 24x24 fill #a6d65f pathFollow=route pathProgress=0
  start: text "start" size=14 fill #eaf4f6 at 60,165
  end: text "end" size=14 fill #eaf4f6 at 420,165

animate 2 loop easing=linear autoKey=false
  0 packet.transform.pathProgress: 0
  2 packet.transform.pathProgress: 1

Starch rendering result

objects defines the path and packet, while animate changes pathProgress from 0 to 1. Starch loads this definition and renders the diagram for the current time as SVG.

The diagram we embedded

In this example, one animated diagram compares Stateful MCP and Stateless MCP. Readers can see the sessions, Instances, authentication paths, and packet movement in one diagram.

The player supports play, pause, restart, and seeking. Diagrams with chapters support previous and next chapter controls, and the expand button opens the diagram at full-screen size.

The browser loads the DSL and renders the SVG for the current time from the diagram definition. Readers can therefore seek to an intermediate state.

Display it from Markdown

In this implementation, the article provides a custom element with the public DSL URL and a description of the diagram.

<animated-diagram
  src="https://example.com/diagram.starch"
  aria-label="A comparison of Stateful MCP and Stateless MCP"
  autoplay
></animated-diagram>

src provides the public DSL URL, and aria-label describes the diagram. The article only needs to provide the diagram definition and description.

How we wrapped Starch

We leave diagram rendering to Starch and add article-facing display and controls in this site’s component. When the custom element connects in the browser, it fetches the DSL and passes it to StarchDiagram.

The core of the implementation is:

const source = this.getAttribute('src');
if (!source) {
  this.showError(`${this.copy.failed} src is required.`);
  return;
}

const response = await fetch(source, { signal: this.abortController.signal });
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);

const dsl = await response.text();
this.diagram = new StarchDiagram(stage, {
  autoplay: false,
  onEvent: () => this.syncControls(),
});

const result = this.diagram.setDSL(dsl);
if (!result.ok) throw new Error(result.error);

this.dataset.ready = 'true';
this.dataset.warningCount = String(result.warnings.length);
this.dataset.duration = String(this.diagram.duration);
this.range.max = String(this.diagram.duration);

The wrapper fetches the DSL, connects StarchDiagram to the stage, and parses it with setDSL. It displays an error when parsing fails and passes the duration to the seek bar when parsing succeeds. Starch renders the SVG; our component handles the article-facing controls.

Features added as a component

This component groups the features that improve accessibility for animated diagrams and provide playback controls such as play, pause, and seeking:

  • play, pause, restart, seek, chapter navigation, and full-screen display
  • role="img", aria-label, labelled controls, and playback-status announcements
  • a still frame when prefers-reduced-motion is enabled
  • an error message when loading fails and fallback text when JavaScript is unavailable
  • responsive sizing and larger controls for pointer-based interaction

The Starch definition and description vary by diagram. Playback and accessibility behavior live in the shared component, so we do not reimplement the same behavior for each article.

Why VHS and Starch use different embed syntax

With VHS, the Astro build generates MP4, GIF, or PNG files from a VHS tape, then displays those generated files as HTML in the article. The browser plays or displays the generated files.

Starch loads a DSL in the browser instead of displaying a completed video. <animated-diagram> fetches the DSL, passes it to StarchDiagram, and renders an SVG for the current time. The component also manages the live state, such as seeking and reduced motion.

For this reason, we use a Markdown video code block to specify generated VHS media, while we use a browser-side custom element for Starch. We show the Starch DSL in a code block so it is easy to read, and use <animated-diagram> for the actual animation.

Summary

On this site, we added a component that embeds Starch animation diagrams in Markdown so that abstract concepts and complex processing flows are easier to explain in articles.

  • Starch defines shapes, paths, and changes over time
  • the component loads the DSL and lets Starch render the SVG
  • the shared component provides controls, accessibility, and error display
  • MCP structure and state changes can be explained with an animation

References