learn-mermaid-with-phoebe / Session 6 of 6
Learn Mermaid with Phoebe · Session 6 of 6

Make it yours: theming, config, and shipping

The finale: restyle every diagram with one config block, draw architecture-grade cloud layouts, then ship - CLI exports, CI rendering, and the ten lines of JavaScript that power this very course site.

🔴 Hardest Data & AI teams 45 min live + self-study depth
0-3 · Welcome 3-25 · Concepts (live cards) 25-43 · Three demos 43-45 · Q&A
Part 0

Why this session exists

Five sessions in, you can diagram Nova end to end - but everything still wears mermaid's default clothes and lives inside editors. The pro layer changes both: theming makes diagrams carry YOUR brand, config directives tune behavior per diagram, and the shipping toolchain (CLI, CI, embed script) puts rendered diagrams anywhere a browser or a build pipeline can reach. This is also where a five-session secret gets revealed. The live sessions end today, but the course does not: three self-paced deep dives follow, starting with mermaid's data chart types.

Live - presented in session Self-study - read after class ★ Try it now Every diagram on this page is REAL mermaid, rendered live
★ What you walk out with today The five built-in themes and the one that obeys you (base + themeVariables), frontmatter config vs the older init directive, an architecture-beta cloud layout and a C4 context diagram for Nova, mmdc exports in three formats, the exact embed script this site uses, and accessible diagrams via accTitle and accDescr. Plus the reveal: how every pink diagram you have seen was made.
Part 1 · covers "Theming" + config basics

Theming - one block restyles everything 8 min live

Mermaid ships five themes: default, neutral (print-friendly), dark, forest, and base. The first four are fixed palettes. Only base is designed to be customized - hand it themeVariables and it becomes your brand.

flowchart LR a[Source] --> b[Diagram] Your sourceunchanged - meaning lives here 4 fixed themesdefault · neutral · dark · forest theme: base+ primaryColor, lineColor, fontFamily, 40+ variables The theme layer Branded outputsame layout, your colors Only theme base reads your themeVariables - the other four politely ignore them.
🔍 Click to zoom - source stays put, the theme layer decides the clothes. Base is the only tailor.
LiveTwo ways to configure: frontmatter and init3 min▶

Per-diagram config attaches to the source itself, so it travels with the diagram. The modern way is a frontmatter block: YAML between --- fences, before the diagram type line. The older way is the init directive - a %%{init: ...}%% comment with JSON. Both work in v11; frontmatter is what current docs teach and what reads best in review.

Frontmatter - the modern way (YAML, top of the block)--- config: theme: forest --- flowchart LR a[Same source] --> b[New clothes]
Init directive - legacy, still valid (JSON in a comment)%%{init: {'theme': 'forest'}}%% flowchart LR a[Same source] --> b[New clothes]

And here it is live - this block overrides the page's own theme with forest, proving the config travels inside the source:

---
config:
  theme: forest
---
flowchart LR
  a[Same Nova source] --> b{Theme?}
  b -->|forest| c[Green diagram]
  b -->|none| d[Page default]
YAML bites once Frontmatter is real YAML: two-space indentation matters, and hex colors must be quoted ('#D6246E') or YAML eats everything after the # as a comment. Those two rules prevent most theming frustration.
LiveThe reveal: how every pink diagram was made3 min▶

Time to confess. Every pink diagram across all six sessions is stock mermaid - no CSS hacks, no SVG editing. The page initializes mermaid with theme: base plus pink themeVariables, and every diagram wears them automatically. Here is that exact trick, self-contained in one block:

---
config:
  theme: base
  themeVariables:
    primaryColor: '#FFEFF5'
    primaryBorderColor: '#D6246E'
    lineColor: '#C05585'
---
flowchart LR
  src[App events] --> ing[Ingestion]
  ing --> dw[(Warehouse)]
  dw --> bi[Dashboards]

Three variables did most of that work. The heavy hitters: primaryColor (node fill), primaryBorderColor, primaryTextColor, lineColor (edges), fontFamily, plus secondary/tertiary sets for subgraphs and second-class nodes. Mermaid derives sensible values for everything you do not set.

Real world

A platform team put their company's exact brand hex codes into one shared frontmatter snippet and pasted it atop every architecture diagram in their docs. Design stopped asking them to "redo the diagrams in brand colors" - the diagrams simply WERE brand-colored, forever, for free.

Self-studythemeVariables worth memorizing2 min read▶
VariableControlsStart here
primaryColormain node fillyour lightest brand tint
primaryBorderColormain node borderyour strongest brand color
primaryTextColortext inside nodesnear-black for contrast
lineColoredges and arrowheadsa mid-tone of the border
fontFamilyevery labelyour docs font
clusterBkg / clusterBordersubgraph boxesa whisper-faint tint
pie1...pie12pie slice colorsbrand ramp, darkest first

Contrast check your choices: light fill + dark border + near-black text survives projectors, printers, and colorblind readers. Diagram-specific variables (sequence actors, gantt bars) are listed per diagram in the theming docs.

Part 2 · covers "Architecture" + "C4" diagram types

Architecture-grade diagrams 7 min live

Flowcharts describe flow; sometimes you need to describe DEPLOYMENT - what runs where, grouped how. Mermaid v11 added architecture-beta for cloud-style layouts with icons, and ships an experimental C4 grammar for context diagrams.

Livearchitecture-beta: Nova's cloud layout4 min▶

The grammar has four words: group (a labeled container), service (a box with an icon), junction (an invisible split point), and edges that name which SIDE they leave and enter: ing:R --> L:dw means "from ingestion's right side into the warehouse's left side". You place things; mermaid routes.

architecture-beta
  group nova(cloud)[Nova platform]
  service gw(internet)[Event gateway]
  service ing(server)[Ingestion] in nova
  service dw(database)[Warehouse] in nova
  service bi(server)[Dashboards] in nova
  service ml(disk)[Feature store] in nova
  junction fan in nova

  gw:R --> L:ing
  ing:R --> L:dw
  dw:R -- L:fan
  fan:T -- B:bi
  fan:B -- T:ml
  • Icons: five ship built in - cloud, database, disk, internet, server. Thousands more via iconify packs when you control the renderer.
  • Sides are the layout tool: L R T B on each edge end is how you sculpt the arrangement - there is no direction flag like a flowchart's LR.
  • Beta means beta: the keyword is literally architecture-beta. Keep labels plain (letters, numbers, spaces) and expect the syntax to evolve.
LiveC4 context: Nova and its neighbors3 min▶

C4 is a documentation METHOD (Context, Container, Component, Code) with its own boxy visual convention. Mermaid implements it - C4Context and friends - but flags it experimental: the docs say syntax and properties can change in future releases. Use it when your org already speaks C4; keep examples small.

C4Context
  title Nova in context
  Person(analyst, "Analyst", "Reads dashboards daily")
  System(nova, "Nova platform", "Events to warehouse to insight")
  System_Ext(crm, "CRM", "Nightly export source")
  Rel(analyst, nova, "Uses")
  Rel(crm, nova, "Sends data")
Which one when Subgraphed flowchart = logical flow (Session 2, still your default). architecture-beta = deployment view with icons. C4Context = stakeholder-facing context when C4 is the house style. All three can describe Nova; they answer different questions.
Part 3 · covers mermaid-cli + usage/embedding + accessibility

Shipping - CLI, CI, and everywhere 7 min live

Rendering in editors is table stakes. The pro layer renders diagrams in PIPELINES: batch-export with the CLI, regenerate in CI on every push, embed live in any web page - and make every diagram readable to screen readers while you are at it.

nova.mmdcommitted in git 1 · Host renders itGitHub, Notion, docs sites - zero setup 2 · Your page + mermaid.jsthis course site - ten lines of JS 3 · mmdc pre-rendersCI job - SVG, PNG, PDF artifacts Readers see diagramssource stays the single truth Pick per destination: hosts for docs, embed for sites you own, pre-render for slides and PDFs.
🔍 Click to zoom - one committed source, three delivery routes. All three can coexist.
Livemermaid-cli: mmdc in one minute2 min▶

mmdc is the official command-line renderer. It spins up headless Chromium via puppeteer, renders exactly what the browser would, and writes the file format you asked for - the extension picks it.

The whole workflownpm install -g @mermaid-js/mermaid-cli mmdc -i nova.mmd -o nova.svg # crisp, infinite zoom mmdc -i nova.mmd -o nova.png # for slides and chats mmdc -i nova.mmd -o nova.pdf # for the print crowd

No npm on the machine? The maintained docker image skips the install entirely: docker run --rm -v $(pwd):/data minlag/mermaid-cli -i nova.mmd -o nova.svg. Because puppeteer downloads a browser, the first install is heavy - normal, not broken.

LiveCI: render on push, never by hand2 min▶

The pattern is one job: when a .mmd file changes, run mmdc over it and publish the output. Two flavors:

  • Commit artifacts back - the job renders docs/*.mmd to docs/img/*.svg and commits them, so even non-mermaid surfaces (wikis, emails, slides) get current images.
  • Attach to the docs build - MkDocs or Docusaurus renders fences at build time; mmdc covers only the exports slides need.
Real world

A data platform team wired mmdc into their docs pipeline: every merge re-exported twelve architecture diagrams to SVG for their internal portal. The diagrams stopped drifting from reality because updating them was no longer a task anyone could forget - it was a side effect of merging.

LiveEmbedding: the ten lines behind this site2 min▶

Everything this course does - live rendering, pink theme, all of it - starts with one ES module import and one initialize call. Here is the skeleton, ready to steal:

Minimal live-mermaid page - adapt freely<script type="module"> import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs"; mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: { primaryColor: "#FFEFF5", primaryBorderColor: "#D6246E", lineColor: "#C05585" } }); await mermaid.run({ querySelector: ".mermaid" }); </script>

securityLevel matters: strict (the default) sanitizes labels and disables click interactions - right for pages that render other people's diagrams. loose enables clicks and HTML labels - only for sources you fully trust. This page runs strict.

LiveAccessibility: accTitle and accDescr1 min▶

An SVG diagram is invisible to a screen reader unless you say what it means. Two lines fix that in ANY diagram type, right after the type keyword:

flowchart LR
  accTitle: Nova high level flow
  accDescr: App events flow through ingestion into the warehouse which feeds dashboards
  src[App events] --> ing[Ingestion]
  ing --> dw[(Warehouse)]
  dw --> bi[Dashboards]

Multi-line descriptions use accDescr { ... } with no colon. Rule of thumb: the description should let someone who cannot see the diagram repeat its point in a meeting.

Self-studyGitHub's renderer vs pre-rendered SVG2 min read▶

When a host renders your fence, the HOST picks the mermaid version and config - GitHub ignores your custom themes and strips click interactions, and its mermaid version may lag features like architecture-beta. So:

  • Fence it when the diagram lives next to code and freshness beats styling - READMEs, PRs, issues.
  • Pre-render to SVG (mmdc in CI) when brand theming, exact appearance, or clickable links matter - slides, portals, published docs.
  • Docs sites are the sweet spot - MkDocs and Docusaurus let you configure the mermaid version AND theme, so fences render branded.
Demo 1 of 3

Brand-theme a Nova diagram ★ 8 min · follow along

Take Nova's 30,000-foot map from Session 1 and dress it in YOUR company's colors - one frontmatter block, no design tools.

Grab three brand hex codes: a light tint, a strong accent, a mid-tone. No brand guide handy? Use your company homepage and a color picker.

In mermaid.live, paste the Nova map, then add frontmatter above it: theme: base plus themeVariables with primaryColor set to the tint.

Add primaryBorderColor (the accent) and lineColor (the mid-tone). Quote every hex code - YAML treats a bare # as a comment.

Squint test: text readable on the tint? If not, set primaryTextColor to near-black. Set fontFamily to your docs font as a bonus.

Save the snippet somewhere shared - the frontmatter block IS your team's diagram brand kit now. Paste it atop any diagram, forever.

Demo 2 of 3

Export Nova with mmdc ★ 6 min · build your own

From browser tool to build tool: install the CLI and turn the Nova map into files you can drop into slides and PDFs.

Install: npm install -g @mermaid-js/mermaid-cli. Expect a puppeteer browser download - it is large and normal.

Save your themed Demo 1 source (frontmatter included) as nova.mmd in an empty folder.

Run mmdc -i nova.mmd -o nova.svg, then mmdc -i nova.mmd -o nova.png. Two files, one source.

Open both. Zoom the SVG to 800% - still crisp. That is why SVG is the default and PNG is for hosts that refuse vectors.

Drop the PNG into a slide. You have now shipped a mermaid diagram to the one place fences cannot reach.

Demo 3 of 3

Make every Nova diagram accessible ★ 4 min · build your own

Sweep your Nova collection from Sessions 1-5 and give each diagram a voice. This is the cheapest professionalism upgrade in the whole course.

Open each Nova diagram you have built (map, sequence, ERD, gantt - whatever you kept).

Add accTitle: naming the diagram, right under the type keyword.

Add accDescr: stating the takeaway in one sentence - what should a listener LEARN, not what shapes exist.

Re-render each to confirm nothing broke; the lines are invisible in the output by design.

Homework

Try it yourself - this week ◐ 30-45 min total

Source material

Official docs covered

This session teaches the working content of these sections of the official docs at mermaid.js.org (mermaid 11.x) plus the mermaid-cli repo.

✓ThemingPart 1 - five themes, base + themeVariables, the pink reveal
✓Configuration + directivesPart 1 - frontmatter config vs init directive
✓Architecture (architecture-beta)Part 2 - groups, services, junctions, side-anchored edges
◐C4 diagramsPart 2 - context level only; experimental, syntax may change
✓mermaid-cli (mmdc)Part 3 + Demo 2 - SVG/PNG/PDF exports, docker, CI pattern
✓Usage: embedding in web pagesPart 3 - the ESM import + initialize + run skeleton
✓AccessibilityPart 3 + Demo 3 - accTitle, accDescr, multi-line form
◐ELK layout enginenamed only - Deep dive 6.3 covers layout tuning
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · You set themeVariables but the diagram ignores them completely. Most likely cause?

The four fixed themes ignore your variables by design. Set theme: base first, then customize - and quote your hex codes in YAML.

2 · Frontmatter block vs %%{init}%% directive - which statement is true?

Frontmatter sits between --- fences at the very top; init is the older JSON-in-a-comment form. Both still work in v11.

3 · What does mmdc -i nova.mmd -o nova.png actually do?

mmdc is a real browser in a trench coat: puppeteer renders exactly what you would see, and the output extension (svg/png/pdf) picks the format.

Session 6 cheat sheet · pin this

Five themesdefault · neutral (print) · dark · forest · base. Only base is customizable - the rest are fixed palettes.
Brand kittheme: base + themeVariables: primaryColor (fill), primaryBorderColor, primaryTextColor, lineColor, fontFamily.
Frontmatter--- config: theme: ... --- above the type line. Real YAML: two-space indents, quote '#hex' colors.
Init directive%%{init: {'theme':'base'}}%% - the legacy JSON form. Still valid; prefer frontmatter for new work.
architecture-betagroup id(icon)[Label] · service id(icon)[Label] in group · junction id · edges anchor sides: a:R --> L:b.
C4ContextPerson / System / System_Ext / Rel(a, b, "verb"). Experimental - keep small, expect change.
mmdcnpm i -g @mermaid-js/mermaid-cli · mmdc -i in.mmd -o out.svg|png|pdf · puppeteer inside · docker image if npm is unwelcome.
Access + trustaccTitle: / accDescr: right after the type line, every diagram · securityLevel strict for others' sources, loose only for your own.