TinyVolt

Nova

Turn your markdown into an interactive canvas. Write on Github, preview on Nova.

What is Nova?

Nova is a markdown editor and a platform.

Editor: A VS Code-style editor where one can write and preview content locally.

Platform: The invisible scaffold that handles publishing, hosting and serving. The same article lives in two places:


The authoring format

Top-level fence code becomes hidden setup. with group("name"): collects a run of commands, and {label}(ref:name) reveals it from your prose as one click. Inline spans like {label}(scale = gm.scalar(1)) are the escape hatch for one-off commands. Everything else is plain markdown, KaTeX math included.

# Drawing a walk

```pygeomatic
origin = gm.p0
a = gm.point(3, 0)
walk = gm.line(origin, a)
gm.hide(walk)

with group("walk-x"):
    gm.highlight(walk)
    gm.show(walk)
```

Reach the point by {moving a distance}(ref:walk-x) of $3$ units.
Or reset it inline: {set scale to 1}(scale = gm.scalar(1)).

Binding LaTeX to live nodes

Give a formula an id (a %id: line inside the $$…$$ block), reach it with gm.tex("id"), then attach a store node. Whatever drives the node reflows the formula. Two modes:

bind — show a node's value in a slot

  • A number inside the formula tracks a node (integral limit, fraction numerator).
  • Address the slot as tex.family.slot (e.g. int.upper, frac.num) and call .bind(node).
$$
%id:energy
\int_{a}^{b} x^2 \, dx
$$

```pygeomatic
b = gm.scalar(3, out="b")
energy = gm.tex("energy")    # matches %id:energy
energy.int.upper.bind(b)   # upper limit now shows b
```

Change it: {b = 5}(b = gm.scalar(5))

highlight — paint matrix cells by position

  • Paint a row, column, diagonal, or region of a matrix.
  • Build a selector over each cell's grid position; it moves as its node changes.
$$
%id:M
\begin{pmatrix} a & b & c \\ d & e & f \\ g & h & i \end{pmatrix}
$$

```pygeomatic
r = gm.scalar(0, out="r")
M = gm.tex("M")
M.highlight(M.rows() == r, color="pink")   # row r
M.triu().highlight(color="blue")         # upper triangle
```

Move it: {row 1}(r = gm.scalar(1)) · {row 2}(r = gm.scalar(2))
  • Boxes: M[3:, 4:]. Regions: M.diag() / M.triu() / M.tril().
  • Arithmetic cols - rows > 0, combine with & / |, gate with .scale(node).