Diagrams

Specular's markdown renderer drops raw HTML, so you cannot paste <svg> into md"…". The specular-mermoid module (pulled in by specular-site) embeds mermoid via mermoid-ascent: hybrid HTML nodes + SVG edges at docs-build time, with optional live selection and viewport reflow in the browser. Parse failures fail the build.

Fenced mermaid blocks inside md"…" pick up ThemeTokens.diagramConfig from your site theme (defaults to Mermoid.chalkboard). Tweak it when you compose layers:

Theme.fromTokens(
  ThemeTokens.default.copy(
    diagramConfig = RenderConfig(theme = ThemeName.Forest)
  )
) >>> DocsSite.themedStack

Prefer Mermoid.diagram inside an example for a static hybrid snapshot, and Mermoid.diagramInteractive inside exampleIO + .interactive when you want selection, tooltips, and Narrow/Medium/Wide reflow:

import specular.mermoid.Mermoid

val src = "flowchart LR\n  A --> B"
example { Mermoid.diagram(src) }

exampleIO {
  Mermoid.diagramInteractive(src, initialWidth = 640)
}.interactive

For a Scala.js docs client that remounts diagrams live, add the JS artifact:

libraryDependencies += "rocks.earlyeffect" %%% "specular-mermoid" % "<version>"

mermoid cross-builds JVM and Scala.js with byte-identical inert SVG for the same input. Coverage today is flowcharts and state diagrams. Use Mermoid.svgDiagram when you need an inert SVG tree for structure assertions.

Mermoid.diagram(flow)

Same chart: SSR vs Scala.js

Both examples use the same Mermaid source. The first is a plain example — SiteBuilder SSRs a hybrid diagram at build time and that snapshot stays put. The second is exampleIO + .interactive — the Scala.js client clears the SSR node and remounts diagramInteractive so you can select nodes and reflow with Narrow/Medium/Wide.

SSR only (build-time hybrid snapshot; not remounted):

Mermoid.diagram(shared)

Live (Scala.js) — selection + viewport reflow:

Mermoid.diagramInteractive(shared, initialWidth = 560)
viewport 560px

Mermaid click becomes hover tooltips and link wrappers. Hover Parse / Layout; Paint opens earlyeffect.rocks. Remount this example to exercise selection too.

Mermoid.diagramInteractive(tooltips, initialWidth = 640)
viewport 640px
PaintOpen Early Effect

Fenced mermaid in Prose

A mermaid fence inside Prose is enough for a static hybrid diagram. Parse errors fail the site build. Use example / exampleIO when you want DocSpec assertions or .interactive remount — Prose is skipped by the test interpreter.