Image overlay editor
An editor for putting things on top of a picture. You drop an image or a PDF in as the background, then place boxes over it and drag them where they belong: boxes of text, boxes that are a circle or a rectangle, boxes that hold another image. What comes out is a YAML file.
I wrote it for D&D character sheets and that is what it runs — it has been holding the sheets of every campaign I DM since April 2026 — but nothing inside it knows what a character sheet is. A scanned form with boxes where the fields go is the same problem. So is a generator of custom cards: one file with the frame and the layout, one short file per card. So is putting a face on top of a photo.
The reason it is a YAML file and not a drawing is inheritance. A file can
extend other files, one or several, and what it inherits is both the layout
and the values. So the boxes and their positions are written once, on a base
file; the repeated content — in D&D, classes, races, backgrounds — is written
once each; and the final thing is a short file that lists what it extends and
fills in a handful of values. Change where a box sits on the base and every file
that extends it moves too.
Any value can be an expression in braces, evaluated with every other field of
the file in scope: {10 + Perception} for passive perception, or a nest of
ternaries that turns level into proficiency bonus. Fields are resolved in
passes, so an expression can depend on a field that is itself an expression, and
overriding one in a child gives you base to refer to what the parent said.
That is the whole point of the thing — I stopped recomputing modifiers by hand
at the table. The one part that does know about D&D is a mod filter, which
prints a number as +3 or -1.
There is no build step and no framework: one HTML file, one CSS file, one JS
file, and four libraries checked into the repo. Files are served by their path —
/campaign/character is not a file, it is nginx noticing the YAML exists and
handing you the editor, which reads the path back off the URL and loads it.