A small, local computational workbook built around ordinary, self-updating Markdown files. The runner, parser, executor, and document writer are Odin. There is no Python, Jupyter, Node.js, web server, or browser-based execution.
Typst renders LaTeX through the MiTeX package. Typst downloads that package on first use and then reads it from its local cache.
odin build tools/workbook -out:workbook
./workbook example.mdEach Markdown file is updated in place; there is no separate preview file. The
workbook implementation and its tests live under tools/workbook/, separate
from the Markdown documents and the self-contained Odin programs inside them.
Workbook files can use any directory depth beneath the project root. The CLI
targets one .md path at a time and does not assign meaning to directory names,
so directories can act as topics, chapters, or any other organization:
topics/
numerical-methods/
01-forward-euler/
introduction.md
exercises.md
linear-algebra/
vectors.md
Run the CLI from the project root and pass any individual document path, or use
the Zed action from inside that document. Generated SVGs remain shared under
the root .build/generated/ cache, while each inserted Markdown image URL is
made relative to its document. Moving from one level of nesting to many levels
therefore does not break previews. The CLI does not recursively build a whole
directory tree in one invocation.
The runner performs three passes:
- Fenced
latexblocks are rendered to content-addressed SVG files under.build/generated/. Equal LaTeX content reuses the same SVG. Fencedgraphblocks are sampled and rendered directly to content-addressed SVG surfaces by the Odin executable, with no plotting subprocess or library. - Every fenced
odinblock runs independently throughodin run <temporary-file> -file. - The same Markdown file is atomically updated with ordinary Markdown image
references and
outputfences.
Each equation view stacks the untouched fenced LaTeX above its white rendered SVG. The runner inserts only a standard Markdown image reference immediately beneath the fence. On the next run it recognizes and replaces that reference, so edits and reruns do not create duplicates. No HTML is generated.
Write an equation cell as ordinary Markdown:
```latex
\frac{dy}{dt} = -y
```Inline $...$ and $$...$$ text is deliberately left untouched.
Write a static single-variable curve as:
```graph
f(x) = x**4 - 2*x**2
x = [-2, 2]
samples = 64
subticks = [4, 4]
size = [900, 600]
```For curves, the function and its variable bounds are required. samples,
subticks, and size are optional. A scalar subticks value applies to both
axes; [x, f] configures them independently.
Write a static two-variable surface plot as:
```graph
f(x1, x2) = x1**2 - x2**2 + x1**3
x1 = [-2, 2]
x2 = [-2, 2]
samples = 64
subticks = [4, 4, 6]
size = [900, 600]
camera = [45, 30]
```For surfaces, the function and both variable bounds are required. samples,
subticks, size, and camera are optional. subticks = 6 applies six equal
subdivisions to every axis; subticks = [4, 4, 6] configures the two input axes
and function axis independently. Subticks add grid and tick marks, while only
the minimum, midpoint, and maximum are labelled to avoid crowding. Both graph
forms support +, -, *, /, **, ^, parentheses, pi, e, and sin,
cos, tan, sqrt, abs, exp, log, min, and max. The runner keeps
the graph fence
untouched and inserts only an ordinary Markdown reference to a transparent SVG
with white axes and labels.
Compiler diagnostics are inserted into the same Markdown file and the command then exits non-zero. Temporary Odin and Typst source files are deleted.
The runner also exposes row-addressed commands for editor integrations:
./workbook render-latex example.md 10
./workbook render-graph example.md 34
./workbook run-odin example.md 52render-latex renders and replaces only the equation containing that Zed row.
render-graph renders and replaces only the graph containing that Zed row and
does not invoke Typst or execute Odin cells.
run-odin executes and replaces the output for only the Odin cell containing
that row; it does not invoke Typst or touch any equation reference. The plain
./workbook example.md command remains the explicit full-document build.
One-time setup: run zed: install dev extension and select
.zed/extensions/workbook-latex. This small declarative extension gives fenced
latex and graph blocks their row-specific runnable tags.
- Open
example.mdand its Markdown Preview side by side. - Edit or add a fenced
latexblock containing only the LaTeX expression. - Edit or add fenced
graphblocks and self-contained fencedodinblocks. - Use the inline action beside a LaTeX cell, graph cell, or Odin
maincell to process only that cell. - Use Run Workbook from Zed Tasks only when you want the full three-pass document build.
The open Markdown document is refreshed in place, so its existing preview is the preview to keep open.
- LaTeX cheat sheet — copyable notation for equations, arrays, matrices, vectors, derivatives, calculus, symbols, and equation layout.
odin test tools/workbookTests cover fenced-LaTeX parsing, opaque code fences, content-addressed math assets, nested-document artifact paths, Markdown-only round trips, output insertion, and safe output fencing.