**TL;DR:** I built **[Scriba](https://scriba.judge.zone)** — a free, open-source (MIT) renderer that turns a LaTeX editorial (math, prose, tables, code, **and step-by-step algorithm animations**) into one self-contained, sanitized HTML file. Animations are driven by real code, not hand-drawn frames. To see it on real problems right now: **[50 CSES problems](https://app.judge.zone/problems?tags=cses) where every editorial is explained with an animation** — open any of them and press play. Or write your own in the [playground](https://scriba.judge.zone/playground), no signup.↵
↵
## Hello, Codeforces!↵
↵
If you've ever written an editorial — for a school contest, a gym, or just a↵
detailed solution comment — you know the drill. The prose and the math are the↵
easy part. Then you hit *"and now the DP table fills up like this"*, and↵
you're hand-drawing cells in `Excalidraw`, screenshotting each state into↵
`step1.png`, `step2.png`, … Then you find an off-by-one in your own↵
explanation, and all nine screenshots are garbage. Re-draw, re-shoot,↵
re-upload.↵
↵
I did this one too many times while building the editorial corpus for my judge,↵
and got tired of it. So I built something.↵
↵
## The friction with hand-made diagrams↵
↵
- Screenshots go stale the moment the algorithm logic changes — fix a bug,↵
redraw every frame.↵
- A GIF can't be paused mid-step, and readers can't step backwards.↵
- The diagram lives in a different tool than the statement, so they drift↵
apart silently.↵
- KaTeX/MathJax solve the *math* beautifully, but an editorial is math + prose↵
+ tables + code + "watch what happens at step 4".↵
- Sharing source with a co-setter means "here's the .tex, and also this↵
Excalidraw link, and these PNGs".↵
↵
## What Scriba does↵
↵
- **Full statements, not just math:** math, prose, tables, and code↵
highlighting in one document, rendered server-side (the math inside goes↵
through KaTeX — credit where due).↵
- **21 animation primitives:** array, DP table, matrix/heatmap, graph, tree,↵
stack, queue, deque, linked list, hash map, number line, code panel,↵
variable watch… most editorial diagrams map 1-1 to a shape you already↵
think in.↵
- **Frames driven by real code:** a sandboxed [Starlark](https://github.com/bazelbuild/starlark)↵
block (`\compute` / `\foreach`) runs your actual loop and fills frames from↵
its output — fix the logic once, every frame updates.↵
- **Self-contained & sanitized:** math, styles, and the player script all↵
inline in one HTML file — drop it into any page, no toolchain. Untrusted↵
setters' statements can't script-inject your site.↵
- **Free, MIT** — live [playground](https://scriba.judge.zone/playground) with↵
shareable snippets, or `pip install scriba-tex`.↵
↵
*(Honest scope: Scriba renders a LaTeX **subset** — body content plus its own↵
animation syntax — not full LaTeX.)*↵
↵
## What the source looks like↵
↵
A minimal 3-step animation:↵
↵
```↵
\begin{animation}[id="hello", label="Hello Scriba"]↵
\shape{a}{Array}{size=5, data=[3,1,4,1,5], label="my array"}↵
↵
\step↵
\narrate{A simple array with 5 elements.}↵
↵
\step↵
\recolor{a.cell[2]}{state=current}↵
\narrate{Highlight the middle element.}↵
↵
\step↵
\recolor{a.cell[2]}{state=done}↵
\narrate{Mark it as done.}↵
\end{animation}↵
```↵
↵
That renders as an inline player with play / pause / step controls.↵
↵
↵
↵
The interesting part is when frames come from real logic. This is an actual↵
example from the guide — the matrix-chain DP table, computed by the real↵
nested loops inside a `\compute` block, then poured into the table:↵
↵
```↵
\begin{animation}[id="matrix-chain", label="Matrix-chain DP table"]↵
\shape{dp}{DPTable}{rows=5, cols=5, label="dp[i][j]"}↵
\compute{↵
n = 5↵
p = [30, 35, 15, 5, 10, 20]↵
dp_vals = [[0 for _ in range(n)] for _ in range(n)]↵
for length in range(2, n + 1):↵
for i in range(n - length + 1):↵
j = i + length - 1↵
dp_vals[i][j] = 10**9↵
for k in range(i, j):↵
cost = dp_vals[i][k] + dp_vals[k+1][j] + p[i] * p[k+1] * p[j+1]↵
if cost < dp_vals[i][j]:↵
dp_vals[i][j] = cost↵
}↵
↵
\step↵
\foreach{i}{0..4}↵
\foreach{j}{0..4}↵
\apply{dp.cell[${i}][${j}]}{value=${dp_vals[i][j]}}↵
\endforeach↵
\endforeach↵
\narrate{Minimum matrix-chain multiplication cost table, built with nested for loops.}↵
\end{animation}↵
```↵
↵
If I later realize the cost formula was wrong, I fix the loop — not nine↵
screenshots. And unlike VisuAlgo's fixed canonical examples, this runs *your*↵
problem's data and *your* transition.↵
↵
## Don't take my word for it — 770 real problems use this↵
↵
Every editorial on my judge ([app.judge.zone](https://app.judge.zone)) is↵
rendered with Scriba, in **8 languages** (including RTL Arabic). If you only↵
click one link in this post, make it the first one:↵
↵
- **[50 CSES problems](https://app.judge.zone/problems?tags=cses)** — intro to↵
advanced, where **every editorial explains the algorithm with a step-by-step↵
animation**: watch the DP table fill or the tree get re-rooted, instead of↵
parsing three paragraphs of index notation. Open any editorial and press↵
play — that's the whole pitch.↵
- **[720 USACO problems](https://app.judge.zone/problems?tags=usaco)** — 65↵
contests, 2011–2026. The volume test: one pipeline, no per-page hand-tuning.↵
↵
(And even if you never write editorials, the playground doubles as a free↵
scratchpad for stepping through your own DP while upsolving.)↵
↵
## Try it↵
↵
Open **[scriba.judge.zone](https://scriba.judge.zone)** — no signup. The↵
[LaTeX guide](https://scriba.judge.zone/guide/latex) and↵
[animation guide](https://scriba.judge.zone/guide/animation) cover every↵
command with runnable examples. To render locally or self-host:↵
`pip install scriba-tex` (v0.39.0), source on↵
[GitHub](https://github.com/Danchuong/scriba) (MIT).↵
↵
## Feedback / bug reports / feature requests↵
↵
1. Next primitive: **Trie**, **DSU forest**, or **Fenwick/BIT** — which one↵
would you actually use first?↵
2. Which LaTeX command do you miss most inside statements?↵
↵
Bug reports and PRs welcome on [GitHub](https://github.com/Danchuong/scriba/issues),↵
or come argue about animation timing in the Discord:↵
**[discord.gg/pg52FspEns](https://discord.gg/pg52FspEns)**.↵
↵
## Thanks↵
↵
Scriba stands on [KaTeX](https://katex.org) — all math inside statements is↵
rendered through it server-side, and it's an absurdly good piece of software.↵
Thanks also to every editorialist on CF whose hand-drawn DP tables and graph↵
doodles over the years quietly defined the list of 21 primitives — this tool↵
is basically those whiteboard drawings, made reproducible.↵
↵
Happy animating.↵
↵
## Hello, Codeforces!↵
↵
If you've ever written an editorial — for a school contest, a gym, or just a↵
detailed solution comment — you know the drill. The prose and the math are the↵
easy part. Then you hit *"and now the DP table fills up like this"*, and↵
you're hand-drawing cells in `Excalidraw`, screenshotting each state into↵
`step1.png`, `step2.png`, … Then you find an off-by-one in your own↵
explanation, and all nine screenshots are garbage. Re-draw, re-shoot,↵
re-upload.↵
↵
I did this one too many times while building the editorial corpus for my judge,↵
and got tired of it. So I built something.↵
↵
## The friction with hand-made diagrams↵
↵
- Screenshots go stale the moment the algorithm logic changes — fix a bug,↵
redraw every frame.↵
- A GIF can't be paused mid-step, and readers can't step backwards.↵
- The diagram lives in a different tool than the statement, so they drift↵
apart silently.↵
- KaTeX/MathJax solve the *math* beautifully, but an editorial is math + prose↵
+ tables + code + "watch what happens at step 4".↵
- Sharing source with a co-setter means "here's the .tex, and also this↵
Excalidraw link, and these PNGs".↵
↵
## What Scriba does↵
↵
- **Full statements, not just math:** math, prose, tables, and code↵
highlighting in one document, rendered server-side (the math inside goes↵
through KaTeX — credit where due).↵
- **21 animation primitives:** array, DP table, matrix/heatmap, graph, tree,↵
stack, queue, deque, linked list, hash map, number line, code panel,↵
variable watch… most editorial diagrams map 1-1 to a shape you already↵
think in.↵
- **Frames driven by real code:** a sandboxed [Starlark](https://github.com/bazelbuild/starlark)↵
block (`\compute` / `\foreach`) runs your actual loop and fills frames from↵
its output — fix the logic once, every frame updates.↵
- **Self-contained & sanitized:** math, styles, and the player script all↵
inline in one HTML file — drop it into any page, no toolchain. Untrusted↵
setters' statements can't script-inject your site.↵
- **Free, MIT** — live [playground](https://scriba.judge.zone/playground) with↵
shareable snippets, or `pip install scriba-tex`.↵
↵
*(Honest scope: Scriba renders a LaTeX **subset** — body content plus its own↵
animation syntax — not full LaTeX.)*↵
↵
## What the source looks like↵
↵
A minimal 3-step animation:↵
↵
```↵
\begin{animation}[id="hello", label="Hello Scriba"]↵
\shape{a}{Array}{size=5, data=[3,1,4,1,5], label="my array"}↵
↵
\step↵
\narrate{A simple array with 5 elements.}↵
↵
\step↵
\recolor{a.cell[2]}{state=current}↵
\narrate{Highlight the middle element.}↵
↵
\step↵
\recolor{a.cell[2]}{state=done}↵
\narrate{Mark it as done.}↵
\end{animation}↵
```↵
↵
That renders as an inline player with play / pause / step controls.↵
↵
↵
↵
The interesting part is when frames come from real logic. This is an actual↵
example from the guide — the matrix-chain DP table, computed by the real↵
nested loops inside a `\compute` block, then poured into the table:↵
↵
```↵
\begin{animation}[id="matrix-chain", label="Matrix-chain DP table"]↵
\shape{dp}{DPTable}{rows=5, cols=5, label="dp[i][j]"}↵
\compute{↵
n = 5↵
p = [30, 35, 15, 5, 10, 20]↵
dp_vals = [[0 for _ in range(n)] for _ in range(n)]↵
for length in range(2, n + 1):↵
for i in range(n - length + 1):↵
j = i + length - 1↵
dp_vals[i][j] = 10**9↵
for k in range(i, j):↵
cost = dp_vals[i][k] + dp_vals[k+1][j] + p[i] * p[k+1] * p[j+1]↵
if cost < dp_vals[i][j]:↵
dp_vals[i][j] = cost↵
}↵
↵
\step↵
\foreach{i}{0..4}↵
\foreach{j}{0..4}↵
\apply{dp.cell[${i}][${j}]}{value=${dp_vals[i][j]}}↵
\endforeach↵
\endforeach↵
\narrate{Minimum matrix-chain multiplication cost table, built with nested for loops.}↵
\end{animation}↵
```↵
↵
If I later realize the cost formula was wrong, I fix the loop — not nine↵
screenshots. And unlike VisuAlgo's fixed canonical examples, this runs *your*↵
problem's data and *your* transition.↵
↵
## Don't take my word for it — 770 real problems use this↵
↵
Every editorial on my judge ([app.judge.zone](https://app.judge.zone)) is↵
rendered with Scriba, in **8 languages** (including RTL Arabic). If you only↵
click one link in this post, make it the first one:↵
↵
- **[50 CSES problems](https://app.judge.zone/problems?tags=cses)** — intro to↵
advanced, where **every editorial explains the algorithm with a step-by-step↵
animation**: watch the DP table fill or the tree get re-rooted, instead of↵
parsing three paragraphs of index notation. Open any editorial and press↵
play — that's the whole pitch.↵
- **[720 USACO problems](https://app.judge.zone/problems?tags=usaco)** — 65↵
contests, 2011–2026. The volume test: one pipeline, no per-page hand-tuning.↵
↵
(And even if you never write editorials, the playground doubles as a free↵
scratchpad for stepping through your own DP while upsolving.)↵
↵
## Try it↵
↵
Open **[scriba.judge.zone](https://scriba.judge.zone)** — no signup. The↵
[LaTeX guide](https://scriba.judge.zone/guide/latex) and↵
[animation guide](https://scriba.judge.zone/guide/animation) cover every↵
command with runnable examples. To render locally or self-host:↵
`pip install scriba-tex` (v0.39.0), source on↵
[GitHub](https://github.com/Danchuong/scriba) (MIT).↵
↵
## Feedback / bug reports / feature requests↵
↵
1. Next primitive: **Trie**, **DSU forest**, or **Fenwick/BIT** — which one↵
would you actually use first?↵
2. Which LaTeX command do you miss most inside statements?↵
↵
Bug reports and PRs welcome on [GitHub](https://github.com/Danchuong/scriba/issues),↵
or come argue about animation timing in the Discord:↵
**[discord.gg/pg52FspEns](https://discord.gg/pg52FspEns)**.↵
↵
## Thanks↵
↵
Scriba stands on [KaTeX](https://katex.org) — all math inside statements is↵
rendered through it server-side, and it's an absurdly good piece of software.↵
Thanks also to every editorialist on CF whose hand-drawn DP tables and graph↵
doodles over the years quietly defined the list of 21 primitives — this tool↵
is basically those whiteboard drawings, made reproducible.↵
↵
Happy animating.↵




