Other Components
Other Components
Three more things that aren't text: diagrams, icons, and embedded Vue
components.
Mermaid diagrams
A fenced code block tagged mermaid is rendered as a diagram instead of
highlighted code:
## How a request flows
```mermaid
flowchart LR
A[Editor] --> B[Parser]
B --> C[SlideDeck IR]
C --> D[Renderer]
```Mermaid runs client-side and offline — the library is bundled, nothing is
fetched. Every Mermaid diagram type works: flowcharts, sequence diagrams, state
diagrams, class diagrams, Gantt charts, pie charts, ER diagrams.
The diagram is sized by auto-fit like any other
block: if it's too tall for the slide it is scaled down rather than clipped. A
diagram with twenty nodes will fit — and be unreadable. Split it across slides,
or reveal it in pieces.
Diagrams are code, so they diff
The reason to write a diagram in text rather than paste a screenshot: it lives
in the .tac, it survives a theme change, it stays sharp in the PDF, and agit diff shows exactly what you changed.
Icons: /icon[…]
Tachyonn ships the Symbols Nerd Font (MIT). Go to
nerdfonts.com/cheat-sheet, copy the
glyph itself, and paste it between the brackets:
## /icon[] Deploy
Built with /icon[] and shipped to /icon[].You paste the character, not a name — there is no icon registry to look up and
no way to typo a name. Because the font travels inside the app, this works
offline, on any machine, in the PDF export and in the network viewer; you do not
need a patched font installed.
Icons work anywhere text goes: slide and section titles, the cover, callout
title bars, list items, table cells, footer slots. By default the glyph
inherits the colour of wherever it sits — orange in a heading, white on a
callout bar. Override with two frontmatter keys:
| Key | CSS variable | Default |
|---|---|---|
iconSize | --tac-icon-size | 1em (relative to the surrounding text) |
iconColor | --tac-icon-color | (inherits) |
In the PDF the font is subsetted — only the glyphs you actually used — so
four icons cost a few KB, not a megabyte.
Vue components: /component[…]
For anything genuinely interactive or generated, /component[…] embeds a real
Vue component. Props are key=value, comma-separated; numbers andtrue/false are converted to their real types.
/component[QrCode, url=https://example.org/lecture?class=2026, label=Slides, size=320]Registered components
| Component | Props | Use |
|---|---|---|
QrCode | url (required), size (px, 260), label, ecl (L/M/Q/H, default M), margin (modules, 2), color (#000000), background (#ffffff), showUrl (false) | A QR code for a link |
Counter | initial (0), step (1) | A click counter — the demo component |
The QR code is drawn as vector SVG, so it stays sharp and weightless in the
PDF, and it is generated on the client — nothing is fetched. A url too long to
encode shows a message on the slide instead of breaking the deck; if a dense
code is hard to scan from the back of the room, raise size and lower ecl.
Adding your own
Components are registered intachyonn-render/app/slides/custom-components.ts. Add an entry there, rebuild,
and the name is available to /component[…].
No raw HTML
.tac deliberately has no raw-HTML escape hatch. Custom content goes through/component[…], which keeps structure separate from presentation and means
nothing written in a .tac file can inject markup into the app.