Inspiration

My staple is anime. Classic film is the gap — the thing I keep meaning to get back into and never do.

So I asked a worse question than "what should I watch." I asked: what if I never had to tell it what I like? Every recommendation engine opens with a form. Pick three genres. Rate these ten titles. Tell us about yourself.

I wanted to know what happens if you refuse to answer.

The detective framing came second and fixed everything. Forgotten films are cold cases. The agent isn't recommending, it's making an argument. Once it was a case file instead of a feed, the whole interface wrote itself.

What it does

You sign in with an alias. No email, no password, no OAuth — type a name, land in your own case file.

Gemini opens a case on a forgotten or classic film and delivers a cold pitch, roughly 90 seconds: title, year, director, logline, stills, and the actual argument for why you might like this one. Not a synopsis. A case.

You render a verdict — Watch or Skip — with an optional reason. That's the only signal it ever gets.

Then the next pitch adapts, visibly. One skip into testing, the app surfaced a line I never wrote into the UI copy: "The next case will steer away from Comedy and Mystery." It wasn't repeating a preference I'd given it. It was reporting a conclusion it had drawn.

Watch a film and the case unlocks a second layer: a YouTube description draft, title-card copy, and a thumbnail prompt, all built from the same case file. The app isn't a companion to a show. It's the production pipeline for one.

How we built it

Gemini (gemini-3.1-pro-preview) is the only model. Pitch writing, adaptation copy, taste summaries, review assets — one vendor, no exceptions. Parallel Search runs live at api.parallel.ai/v1/search via the official parallel-web SDK, called before every single pitch. Not cached, not mocked. When it can't reach live data the UI labels the result as fallback rather than quietly lying about it. ClickHouse Cloud takes the event stream over the native HTTP interface — pitch, verdict, signal, review-draft events appended to cold_case_cinema_events, fire-and-forget so a slow write never blocks a pitch. Postgres via Drizzle is the authoritative store. Splitting it this way means fast operational reads and a durable event history without making one database do both jobs badly. pnpm monorepo, React + Vite frontend, Express API.

Every piece of this was built on a free tier or a hackathon credit. The constraint was the design brief.

Challenges we ran into

The cold start nearly shipped broken, and code review caught it before the demo did.

Review flagged that every new user's first pitch would be identical — a tie in the selection pool with nothing to break it, because a brand-new alias has zero signals by definition. That's not a bug you can see alone on one device, because your own account already has history.

So I tested it on two phones. Two fresh aliases, side by side. Both drew The Thin Man.

Fixed it by shuffling the tie-break pool, then re-ran the same two-phone test until fresh aliases diverged on the opening pitch. Hypothesis, live test, fix, verification.

The two phones weren't a demo rig. They were the debugger.

The honesty problem. Live research fails sometimes. The easy move is to serve sample data and say nothing. Instead every result carries researchStatus, so a fallback is visibly a fallback. It looks worse in a screenshot and it's the right call.

Accomplishments that we're proud of

OMG it works. I still find it a little absurd that you can describe a thing to an agent and get back something better than what you pictured.

But the one that actually got me: I showed it to my boyfriend. It pitched him Amadeus. He'd never seen it. He wants to watch it now.

That's the whole thesis surviving contact with a human who isn't me. The agent didn't know him, didn't ask him anything, and still made a case that landed.

What we learned

Two things, and they don't sit together neatly.

The build one: an agent that can't remember is a demo, and an agent that remembers is a product. The distance between them is one event stream and about a hundred decisions about what's worth writing down. Also — you cannot test a cold start from a warm account. Get a second device.

The other one: sometimes you have to be human. Step away from the screen and build something with your hands. I did that in the middle of this and came back with the case-file framing, which is the only reason the interface makes sense.

What's next for Cold Case Cinema: The Pitch

Actually running it. Using it to pick what I watch, and turning the two-post cycle — Gemini's pitch, then my reaction — into the YouTube series it was always built to feed.

After that: multi-user taste profiles so the archive holds more than one operative, auto-posting through the existing pipeline, a weekly digest of open cases, and crossover detection between film taste and anime taste — the question that started this in the first place.

None of it got opened during the build. That was the point.

Built With

Share this project:

Updates

Submission history