← All sites

Design Lab / project

Opus's Diecast Emporium

My dad has a wall. Pegboard, floor to ceiling, carded Hot Wheels and Matchbox, boxes underneath, a few thousand pieces and no list of any of it. He wanted a real record, a place to show the good ones, and a way to sell the doubles. So the site is the small part. The interesting part is what feeds it.

Opus's Diecast Emporium home page, the collector ambulance
The front. A '59 ambulance named Opus, a red ticker, a cream card on dark pegboard. Direction B of two. The other one was a blister card.
The public vault: a searchable grid of catalogued cars
The vault. Search, filter, sort, detail view with a photo gallery and a spec table. Every card here was cut out of a video.

The shape of it

One database, two doors.

The public site holds no data of its own. It asks the API for cars at load, and the API only ever answers with rows he has flagged public, and only the safe fields. What he paid, where a car lives, what he wrote in the notes, none of that has a route out. The filtering happens inside the app, not in the UI, so poking the API directly gets you the same answer the page gets.

The private door is the same API behind Authentik. Caddy authenticates, then the app checks the group itself instead of trusting the proxy. If the vhost is ever misconfigured, the app still says no. That door has the full catalogue, the edit form, a deliberately loud publish toggle, CSV in and out.

opusdiecastmi.com          Cloudflare Pages
api.opusdiecastmi.com      worker2, Caddy, systemd

visitor --> index.html
            /vault/ --------> GET /api/public/cars
                              no auth
                              only is_public = 1
                              safe fields only

Opus ------> login.opusdiecastmi.com
            (Authentik) ----> /api/vault/*
                              group re-checked in app
                              every field, every row
                              PATCH is_public = publish

photos      /api/public/photo/<id>
              404 unless that car is public
            /api/vault/photo/<id>
              anything, gated

How cars get in

Film the shelf. That's the data entry.

Typing a few thousand cards into a form was never going to happen. So the input is a phone video: a slow pan across a shelf, two lights from the sides so the blister doesn't glare, one column every couple of seconds. He emails the clips. The rest is a pipeline.

01
Frames

Each clip gets sampled to stills. The clearest frame per card wins, which is often not the first one it appears in.

02
Read the card

Brand, series, casting, colour, collector number, card condition. Every row carries a confidence. Unreadable means "unknown," never a guess.

03
Crop the photo

The product photo is cut straight out of the best frame, trimmed, and attached to the row. No separate photo shoot.

04
Import, then he decides

A CSV lands in the vault as drafts. Low-confidence rows are flagged Needs ID. Nothing goes public until he flips it.

First real run: three clips, about 75 seconds of footage, 134 draft rows with photos. The same shoot also produces a month of vertical video for his page, which is the point. Catalogue it once or catalogue it twice.

Front

Plain HTML on Cloudflare Pages. No build step. Fetches the public API at load and self-hosts his one Facebook video, no embed script.

Back

Python, stdlib only, no pip on prod. SQLite in WAL mode with a verified backup script, audit table, custom key/value fields so the schema never blocks him.

Gate

Authentik with its own brand and login flow, his collection wall as the login background. Caddy forward_auth, group re-checked in the app. 17 auth tests, all green.

Hot Wheels and Matchbox are trademarks of Mattel, Inc. This is a private collector's catalogue and is not affiliated with either.

Got a collection, a shop, a thing that needs a real record?

This is the kind of build Quick IT does. Free 30-minute consult.

Start a project