A poster that lays itself out
Type one item per line on the left, watch the price list rebuild on the right, then hit “Save as image” and print it or post it. The whole app really does only one thing — typesetting: it measures how tall every block will be before drawing anything, and only then decides how tall the paper is and whether it needs two columns. Even the row of dots between a name and its price is arithmetic — leftover space divided by the width of one dot. Nothing is uploaded; saving the image happens on your machine. Your menu is kept for next time.
The part of this worth stealing is measure first, draw second. Drawing as you go is the natural way to write it, but then the height of the paper has to be decided up front — a few items too many and they run off the page, a few too few and the bottom half is blank. So the code makes two passes: measure() draws nothing and just collects how tall each block will be; draw() works from that table. Once the table exists, “how tall is the paper”, “does this need two columns” and “where do I cut so both columns come out even” are all just addition.
Splitting has two old typesetting rules behind it, both versions of never separate a heading from its items: a column may not end on a heading (its items would all be in the next column, so the group reads as empty), and a group split across columns repeats its heading with “(cont.)” (otherwise column two opens with orphans). The second rule was missing from the first version — the code ran, every check passed, and it took zooming into the rendered image to notice two items stranded at the top of column two with nothing above them.