Combine a song's source with prose so the musical decisions and the code can be read together.
Executable documents: markdown prose with live, editable Volta code cells. Design spec: Write music with explanations.
The standalone reader page was deleted 2026-08-21, along with the TypeScript notebook page, its markdown renderer and its headless e2e; see git history. The
.volta.mdformat, the corpus underruntime/public/notebooks/, the pure model (notebook-doc.ts) and the content validator all still ship, but nothing reads a.volta.mdtoday. The workbench's bench notebook is a.voltafile whose top-level--comment runs are markdown — the same prose subset, rendered byui/src/md.rs; see Tell a story with a song. This page documents the.volta.mdformat and the cell contract the validator still enforces.
The format#
A notebook is a plain markdown file named *.volta.md. Three fence kinds:
| Fence | Meaning |
|---|---|
```volta | a live cell — editable in the reader, has ▶ |
```volta norun | a display cell — code styling, never compiled |
any other ``` | ordinary static markdown code |
Prose supports headings #–#### (the Rust renderer reads up to ######), paragraphs, -/1. lists, > quotes, --- rules, `code`, **bold**, *italic*, and [links](…) (http/https/mailto/relative only). Raw HTML is escaped, never rendered.
Cell semantics (the contract)#
- Cumulative concatenation. Cell N compiles as cells 0..N joined (current editor text, blank-line separated) into ONE module. Later cells see every earlier binding.
- One introduction per name. Because of (1), redefining a binding in a later cell is a duplicate-binding compile error. Author each concept as a new name (
pluck, then a templateglow = patch from pluck { … }). - ▶ plays what the cell defines. The tracks/songs bound at column 0 in that cell; a
songwins over tracks; a cell defining neither plays the whole cumulative module. One cell at a time — starting a cell stops the previous one. - Edits are always honored. The cumulative source is reassembled from the live editors on every ▶; editing cell 1 changes what cell 7 plays.
Reader URLs#
Gone with the page (2026-08-21). The reader served an index from /notebooks/index.json, ?nb=<id> (a manifest notebook) and ?src=<path> (any raw .volta.md the dev server could see). Nothing serves /notebooks/ today.
Shipping a notebook#
- Write
runtime/public/notebooks/<id>.volta.md(title = first#line). - Add
{ id, title, description, file }toruntime/public/notebooks/index.json. cd runtime && npm run test:notebooks— every runnable cell must compile cumulatively (this runs inmake testandmake test-fast). The two shipped notebooks:welcome(the language tour) andflume-resample(the bounce workflow, fromdocs/notes/flume.md).
Authoring gotchas (found shipping the first two)#
play p (slow 2 !"…")does not lower (slowtakes the pattern FIRST) — write the corpus idiomplay p (!"…" |> slow 2).- A cell that should show code without compiling (an intentionally incomplete fragment) is
```volta norun— a bare```voltafragment would fail the validator. - Keep shipped notebooks import-free until the validator grows a lib-dir bundle.
Code map#
runtime/src/notebook-doc.ts (pure model — parser/assembly/attribution, unit tests in runtime/src/notebook-doc.test.ts) · validator runtime/scripts/validate-notebooks.mjs (content, in make test-notebooks) · ui/src/md.rs (the shipped Rust renderer for the same prose subset). The reader page, its TypeScript markdown renderer and its headless e2e were all deleted 2026-08-21; see git history.