Adam Burich Open to work

← Portfolio

2026 · Solo · Static web app

The Reinhardt Family Recipe Box

July 2026 · One HTML file, a JSON manifest, and a Python build script

My grandmother has a recipe box our family has cooked out of for decades. There's only one of it, so I scanned every card and put the whole thing online, built to look and open like the box itself.

The brief

The goal was simple: everyone in the family should be able to find a recipe from their phone, and the site should never need looking after. So there's no server, no database, and no dependencies — a single HTML file reads a JSON manifest and two folders of images.

Just as important, it should feel like her box, not a recipe database. The front page is the box: a wooden case with its lid open and a manila divider for every category. Click a tab to pull that category, or search across all of it.

A scanned typewritten card for chocolate chip cookies, with handwritten quantity edits in the left margin.
Every card is presented as scanned — including the handwritten margin edits, which are the part nobody would want transcribed away.
The recipe box rendered in 3D with its lid open, divider tabs labelled by category standing in staggered rows, and an embossed plate reading Reinhardt Family Recipes.
701
Recipes
926
Card scans, 215 recipes spanning more than one card
22
Categories, one divider tab each
1
HTML file — the entire application
0
Servers, databases, or dependencies to keep alive

01A box made of divs

The box is plain HTML and CSS 3D transforms — no canvas, no WebGL, no images for the wood. A scene with perspective holds the box tilted back and to the side; every wall, the floor, and the lid are ordinary elements placed in 3D space with translateZ and rotateY, and the wood grain is layered gradients. The front carries a thumb notch and an embossed name plate whose screw heads are pseudo-elements.

The lid is a hollow tray hinged at the back: an outer shell, rim walls, and four inner walls, each darkened to a slightly different brightness to fake the way light falls into it. Its depth and wall thickness are CSS variables, which made it quick to tune by eye.

The dividers are generated from the manifest — one per category, spaced evenly through the depth of the box, alternating between two manila shades, with tabs cycling through staggered positions the way real dividers do. The last tab position is computed so it sits exactly flush with the card's edge.

02Making the tabs feel right

Hovering a divider lifts it out of the box. The catch is that a lifted tab moves out from under the cursor, which fires mouseleave, which drops it back down — an infinite flicker. The fix tracks the pointer instead: a lifted tab stays up until the pointer leaves its rectangle plus a margin, with a deeper margin below to cover the path the tab just travelled. The whole lifted divider is clickable, so the target is generous, and clicking the open tab again closes it.

On phones and other devices without hover, the box becomes a scaled-down illustration and a grid of manila category buttons with recipe counts takes over the navigation.

03Browsing and search

Opening a category deals its cards into a masonry gallery. Cards are dealt round-robin across the columns so each visual row still reads left to right, and the layout rebuilds only when the column count actually changes on resize. Thumbnails load lazily, multi-card recipes are labelled "page 1 of 2," and clicking one opens every page stacked at full size.

Search is deliberately simple: the manifest is flattened into one list on load, and titles are matched as you type. Each result carries a small badge tinted from its category's divider color, so results still feel like they came out of the box.

04The build script

A Python script with Pillow turns a folder of original scans into the site. Categories are subfolders; titles, page order, and multi-card recipes all come from the filenames:

Recipes/Cookies/Cookies - Capt. Tweedie Cookies (1).jpeg
Recipes/Cookies/Cookies - Capt. Tweedie Cookies (2).jpeg
                          └──────── title ────────┘ └ page

05Deployment

The output is one static folder with relative paths, so it can live anywhere. It's served from /recipe-box/ on this site, with a handful of friendlier short links (/recipes, /cookbook) redirecting to it.

Stack

HTML · CSS 3D transforms · vanilla JavaScript · Python · Pillow