Everything else in this pipeline runs by itself. This is the one part that needs me: looking at the day’s new files and choosing which ones are actually my daughter, worth keeping in her archive.

For that I built a small browser gallery. It shows the files waiting on the cutting board, I tap the keepers, and press a button. That’s the whole job. But a few small choices made it pleasant enough to actually use every day.

What It Looks Like

Open it in a browser and you get a grid of thumbnails from the working folder:

  • Photos show as thumbnails.
  • Videos show a still frame with a play button — tap to preview in a small player, because you often can’t tell a good video from a frozen first frame.
  • Checkboxes to select the keepers, plus “select all” and “clear.”
  • Pages of 50–60 at a time, so it stays fast even with a big pile.

When I’m done, I press a button and the selected files move on to the next stage. Simple.

The Small Things That Made It Usable

The first version worked but annoyed me daily. Fixing those small frictions is most of what “personal software” is:

  • Video previews. A frozen first frame is often black or blurry. Being able to tap and actually watch a few seconds is the difference between guessing and knowing.
  • A badge for which phone. Each file shows a small tag for where it came from — my phone or my wife’s. That comes straight from the record the pipeline keeps, and it helps when the same moment was shot on both.
  • Keep going after “done.” Early on, once I’d selected some files it would say “nothing left to process” and stop. But there were always unselected files I still wanted to look at. Now skipping a file doesn’t remove it — the gallery just keeps showing the remaining files until I press “done.” (That fix came out of the same big rethink as the cutting board.)

Built With Almost Nothing

The gallery is a single Python file. No web framework, no build step, no npm. It uses Python’s built-in web server, generates the thumbnails with Pillow, and pulls a still frame from each video with ffmpeg. Thumbnails are cached to disk so they’re only made once.

I’m not saying that’s the “right” architecture. I’m saying it’s small enough that I understand every line, which — for software only I maintain — matters more than being fashionable. When something breaks, there’s no framework between me and the bug.

Where It Lives

This is the tool at its own address — the one that does the whole flow: pull new files onto the cutting board, let me pick, and move the keepers on toward the archive. (There’s also an older, separate gallery tool I built earlier that copies photos straight into the archive by hand; the automatic pipeline in this series runs on this one.) It’s gated so it’s not open to the world — like the rest of my apps, a new device has to enter a password and re-enter it periodically. Personal software: reachable by me, closed to everyone else.

There’s one honest bug worth mentioning, because the cause surprised me. On the phone, a grid of videos would show only one thumbnail while the desktop showed them all. It wasn’t the browser. It was my little NAS.

Each video thumbnail is a frame pulled by ffmpeg, and a grid of 50 asks for 50 of them at once. On a two-drive home NAS, launching that many ffmpeg jobs together just overwhelms the CPU — they fight for it, most time out, and their thumbnails never get saved. On desktop the timing happened to work out; on the slower mobile load it didn’t. The fix was to stop being greedy: generate the video thumbnails one at a time, and reuse the cached image the moment it exists. Serialized and cached, the grid fills in reliably on both. A good reminder that “works on my machine” can literally mean “works on my faster machine.”

The Human in the Loop

I could try to remove this step and let something auto-select my daughter. I tried. It didn’t work, for reasons that get their own post next. But honestly, I’m glad. Choosing which moments to keep is not a chore I want automated away — it’s a minute a day of looking at my daughter’s life and deciding what’s worth remembering.

The machine does the copying, de-duplicating, shrinking, and sorting. I do the choosing. That split feels right.