2 Choosing Taliesin
What adopting Taliesin costs and what it is good at: how much of your source is portable, what the speed numbers are in absolute terms, and what happens if you leave.
Every other chapter tells you how to use the tool. This one helps you decide whether to adopt it: what you are committing to, what you get, and what leaving costs.
2.1 Source portability
The first worry about a single-author tool is lock-in: that a year of writing ends up in a dialect only this program understands.
Taliesin’s own corpus is 80 .tmd documents and 7,099 lines of real writing, the largest
sample that exists. Of those lines, 453 (6.4%) carry any construct beyond plain
CommonMark. The other 93.6% is Markdown, and any Markdown tool reads it.
| Construct | Lines | Share |
|---|---|---|
Executable fence (```{python}) | 103 | 1.5% |
Attribute block ({#sec-id}, {.unnumbered}) | 96 | 1.4% |
Citation / cross-reference ([@key], @fig-x) | 90 | 1.3% |
Fenced div (::: {.callout-note}) | 76 | 1.1% |
Cell option (#| label: fig-x) | 66 | 0.9% |
Shortcode ({{< include … >}}) | 22 | 0.3% |
(Measured 2026-09-25 over corpus/**/*.tmd; a line using two constructs is counted once
in the total and once per family, so the family rows sum to more than the total.
Reproduce it with python3 tools/portability-census.py, which is where these numbers
come from and which spells out each family’s definition. The script is committed because
this table was first published in July as “measured rather than asserted” while the
script that measured it was not, and by August its document and line counts no longer
reproduced.)
None of those six constructs originated in Taliesin. Each is Pandoc or Quarto vocabulary
that predates it, so the 6.4% is syntax another Pandoc-family tool already parses. .tmd
is a file extension, not a format. A project arriving from Quarto likewise brings its
sentences, fenced cells, #| options, ::: divs, math, citations and cross-references
across unchanged. Taliesin reads only .tmd pages and does not read _quarto.yml, so
rename each .qmd to .tmd and add a _site.yml (see the
configuration reference). Then
taliesin build . --check-only names the short list of vocabulary that differs, with a
file and a line for each.
The check cannot flag an unknown cross-reference prefix. Only @fig-, @tbl-, @sec-,
@eq- and @lst- are references here; anything else (@thm-, @def-) stays literal
text, because @rust-lang in a sentence is indistinguishable from a typo. Grep your
source for those prefixes before you migrate.
2.2 Speed measurements
Speed is the reason this tool exists. These are absolute numbers on one machine, and they measure Taliesin’s work only. A batch document compiler doing a cold Pandoc pass with execution is doing different work, so a ratio between its times and these would be misleading.
| Measurement | Value | What it covers |
|---|---|---|
Whole-project build, docs/internals (6 pages) | 0.16 s | Parse, render, highlight, math, search index, assets |
| Whole-project build, this guide (16 pages) | 0.21 s | Including executed cells replayed from _freeze/ |
Whole-project build, corpus/tech-blog (17 pages) | 0.35 s | 20.7 ms/page, the heaviest project in the tree |
preview time-to-ready, single document | ≈40 ms | Process spawn to the first HTTP 200; ≈0.3 s for a highlight-dense document |
preview time-to-ready, 16-page book | ≈110 ms | Discovery, nav, cross-reference registry, first render |
| Warm edit: diff only | 0.45 ms | The block diff for one keystroke-sized edit |
| Warm edit: re-render + diff | 2.9 ms | One document, against a 107 ms cold render of it |
| Warm-edit payload | 3.2 KB | Versus a 288 KB full page a reload would refetch |
Save to the open tab, corpus/tech-blog (17 pages) | ≈35 ms | End to end: the watcher, the cross-reference refresh, re-render, diff, websocket |
| Cross-reference refresh, this guide (16 pages) | 3.0 ms | Added to every save in a site preview |
(Every figure re-measured 2026-09-24, the 16-page time-to-ready 2026-09-25, release build,
on a 16-core machine with no other build running. Each build figure is the duration the
build prints for itself, best of three with a warm _freeze/ cache, and each page count
is the one it reports
(find … -name '*.html' is not the page count, since a project may ship its own
404.html and _-prefixed files are never pages). The ready rows are the median of five
runs: wall time from spawning taliesin preview <target> <port> to the first HTTP 200
from its socket, polled every 2 ms, for a small document (corpus/native-tmd.tmd); the
≈0.3 s companion figure is corpus/highlight.tmd, written to be highlight-dense. The
warm-edit and cross-reference rows come from tools/live-edit-bench, run as
cargo run --release -p live-edit-bench; its committed RESULTS.md labels them
indicative (the numbers vary by machine). The structural rows it also records, the op
counts and payload bytes, are deterministic and gated by a regression test. The save row
is measured by crates/server/tests/save_to_open_tab.rs, run as cargo test --release -p taliesin-server --test save_to_open_tab -- --nocapture: from writing the same post the
warm-edit rows measure to its open tab receiving the change, median of nine saves in
place and nine renamed over the old file, 35 to 44 ms over three runs. The watcher’s wait
for a save’s events to stop, 15 ms of quiet, is inside it.)
Because the warm edit is a diff, its cost tracks what you changed rather than how large the document is. See the block model for the operation breakdown behind that payload figure.
The last row is an exception to that scaling. In a multi-page project a save also
re-derives the cross-reference registry before the diff, and its harvest renders every
page, without typesetting math or highlighting code, to recover the cross-page figure and
equation numbers. That pass scales with the size of the project while the diff scales
with the size of the edit, so it is still O(pages) on every save: 3.0 ms in this guide,
and 24 ms for the synthetic 500-page book in tools/live-edit-bench (55 ms when the save
moves an anchor, which also rebuilds the search index). Those figures are wall clock
across every core the machine offers, so a two-core laptop pays more.
2.3 What Taliesin claims, and who asked for it
Each of these is a thing users of comparable tools have asked for in public. They are listed with their sources so you can check that the need is real and was not retrofitted.
- Edit in your own editor, see output alongside.
(marimo #3114) The
.tmdfile is the only editing surface and the browser is a read-only view. Click-to-source, the only path from the page back to the editor, never writes to your source. - A format a human can read and
git diff. (marimo #1379).tmdis Markdown. See the table above for exactly how much of it is not. - Reload on disk change, without losing state. (marimo #2675) A save re-renders and patches in place; scroll position and live canvases survive.
- Stop restarting the kernel. (Quarto #4201) The kernel is warm for the life of the server, so an edit costs one cell, not one boot.
- Re-render only what changed; freeze a single cell. (Quarto #3674, #10429) Both are the same mechanism here: a per-cell cumulative content hash.
Cached-output systems in this space carry a standing complaint that the cache can serve a
stale result: an output produced by code that has since changed. Taliesin’s cache key is
the cumulative hash of a cell’s own code plus every upstream cell in its language plus the
interpreter’s identity, so editing anything upstream invalidates that cell and everything
downstream. For the axes the key can see (cell code, its upstream, the interpreter), a
stale hit cannot happen, and no comparable tool makes that claim. By design, the key does
not cover what a cell reads: a data file, an environment variable, a fetched URL, the
clock, a library upgraded in place. Mark such a cell #| cache: false and it re-runs
every time, along with everything downstream. See
Executable content and the cache notes in
Troubleshooting.
2.4 Continuity: what you are relying on
Taliesin has one maintainer, and the scope is closed. Version 1.0 does not change that: it means the feature set is final for this tool’s one use case, not that a team stands behind it. In practice there is no support contract or release cadence you can plan around, and nobody but the maintainer knows the codebase. The project continues only while the maintainer works on it.
What you keep if the maintainer stops:
- Your source is Markdown, 93.6% of it plain CommonMark, all of it in your repository.
- Pages you already built keep working: they are static HTML with no runtime dependency on the tool that made them.
- The code is AGPL-3.0, so a fork is always available to anyone who wants one.
So the realistic downside is migrating to another Pandoc-family tool and redoing a small fraction of the syntax, with your writing intact. The table in Source portability bounds that fraction.
The project offers no guarantee of continuity. Its mitigation is that everything the
author writes goes through this tool. Both books of this manual, the public website and
the regression corpus are .tmd rendered by Taliesin: 112 tracked .tmd files, 12,904
lines, of which the 81-document corpus is re-rendered by every cargo test run. A defect
that breaks a page breaks the documentation for that page in the same commit.