About NextFilm
NextFilm is a taste-based film recommender. Instead of filtering by genre, it learns from your tier-list ratings what you actually like, then finds films that fit the mood you're in. I designed, built, and run the whole thing myself.
Queried from the running database 2 hours ago, not typed into the page.
The stack
I picked boring, proven tools on purpose, so the time went into the product rather than the tooling.
| Backend | Go, with the chi router |
| Frontend | Server-rendered HTML with templ and HTMX, styled with µCSS. No JavaScript framework and no front-end build step. |
| Database | PostgreSQL, with pgvector for similarity search |
How it works
- Data ingestion
- Every day, a Go batch worker streams TMDB's full movie export and decides what belongs in the catalog. Real-world movie data is messy, so it filters out shorts, obscure entries and incomplete records, enriches what's left, and writes it to Postgres.
- Taste embeddings
- Genre tags are a blunt tool: two "thrillers" can feel nothing alike. So each film is described by its themes, tone and pacing, and that description is turned into a vector. Recommendations then match the feel of a film rather than its label.
- Handling diverse tastes
- Human taste isn't one-dimensional. If you love both slow-burn indie dramas and high-octane action movies, averaging the two gets you something you don't want. NextFilm groups your ratings into separate taste profiles and scores each film against the one it's closest to, so your love of horror doesn't bleed into your love of rom-coms.
The same idea powers Tonight: answer a few questions about your mood, and NextFilm turns your answers into a vector and finds three films that fit, whether you're watching alone or with a room of friends.
Performance and real-world use
Sorting the whole catalog of 13,476 films against your taste takes 172 ms — measured live by this server, not typed into the page.
A great recommendation is useless if you can't watch it, so NextFilm also tracks availability across 272 streaming services in three regions. You can hide anything you can't actually stream, and every film shows where to watch it.
Scaling the monolith
Right now NextFilm is a single Go web app plus one batch-worker binary, built from the same image and sharing one database. That was a deliberate choice: one deployable meant shipping quickly with almost no DevOps overhead while the product took shape.
It's built along domain boundaries, though. The heavy batch work — ingestion, embedding, clustering — already runs outside the web process. Browse, which handles the vector sorting and recommendations, is by far the most read-heavy part of the system, and it's structured so it can be split out into its own service as traffic grows. That lets the recommendation engine scale independently of the write-heavy ingestion and user-rating services.
Questions? [email protected]