← All projects

Case study

grainyday

a personal film journal and recommendation app

Visit live site
Screenshot of the grainyday film journal app interface

Why it exists

I built grainyday because I kept searching “films like ___ reddit” too often. It lets you rate movies, write journal entries about what you loved (or hated), and learns your taste over time.

Design decisions

  • The movies find you. No searching, no endless catalogs. Once a day, Gemini sample your journal entries and movie ratings, analyzes likes and dislikes, filters out anything already on your watchlist, and deals three movies with reasoning.
  • No advertising. Streaming recommendations optimize for engagement inside one catalog — they’ll show you what keeps you subscribed, from their library. Our prompt works from what you actually wrote about what you loved and hated, with the reasoning shown, so a pick can come from anywhere and you can see why.
  • Three picks, pick on the fly. The ticket is deliberately short. Three films, readable in seconds, instead of an infinite scroll of options. The most recent picks stay stored until you generate new ones, so you can come back anytime.

Under the hood

  • TMDB behind a server route. Film data — posters via image.tmdb.org, synopses, directors, and release years — goes through our own API routes, so keys never reach the browser and responses are shaped before the client sees them.
  • Tiptap, not a textarea. Entries support real formatting — quotes, emphasis, structure — because writing a film journal on grainyday should feel as personal as writing on your own notebook, and not just some online textbox.
  • Free-tier end to end. Next.js + Tailwind on Vercel, email/password Auth + Firestore on Firebase. A handful of users so far, unpromoted, effectively zero cost.

Build notes

  • Spec before code. OpenCode plan mode first: specs, design choices, and the data model captured in guidelines, then the Gemini prompt itself designed by the model. It wrote the tests too; secrets stayed secret, and everything shipped after manual testing plus AI-run suites — with human eyes on every trust-boundary diff.
  • Built in layers. Scaffolded the whole UI on dummy data so every screen could be visualized ahead of time. Completed journal and watchlist pages first, made editing feel more personal through Tiptap, then refined the recommendations page look and feel. Only then connected Firestore, with Gemini and TMDB wired up together at the end.