Back to Projects

Cue

Personal Movie Tracker · React + TypeScript PWA

Offline-First Streaming Availability Recommendations Connection Graph

A private, personal build behind Cloudflare Access. This page is a case study rather than a link to a live demo.

Why I Built It

I wanted a single place to track what I've watched, what I want to watch, and where to find it, without ads, tracking, or a feed designed to keep me scrolling. Cue is a personal watch log first: watched history, a watchlist, ratings, and a running event log of what I've seen and when.

It started as a small local tool and grew into something more capable over time: an offline-first library seeded with nearly 20,000 movies, streaming availability by region and service, a recommender I built myself from weighted keywords, cast, directors, and genres, and a graph of co-star connections that computes Bacon and Cage numbers across roughly 150,000 edges. It's private behind Cloudflare Access because it's built for me and my household, not as a public product.

Highlights

Cue movie library grid showing watched and watchlist titles with posters and ratings

Offline-first library

The library holds nearly 20,000 movies in IndexedDB, so browsing, searching, and adding titles all work offline. Prefix and fuzzy search make it fast to find a title even with a typo, and each entry shows where it's currently streaming by region and service.

Cue movie detail screen showing a title's info alongside its Bacon number and Cage number

Tracking and detail

Every title tracks watched status, watchlist membership, and a rating, feeding a chronological watch-event log of what I've seen and when. Detail pages go deeper: full cast and crew, streaming providers, and a title's Bacon number and Cage number.

Cue's Cage Quest page with Nicolas Cage filmography progress at 31 of 112, stats, and a random unwatched picker

Cage Quest

The Cage Ascent

Cage Quest tracks progress toward watching Nicolas Cage's entire filmography, currently sitting at 31 of 112. A random unwatched picker helps close the gap, and a climb visualization called the Cage Ascent charts how far there is to go. Both the Bacon number and Cage number shown throughout the app come from a homegrown co-star connection graph that runs a breadth-first search across roughly 150,000 edges.

31 of 112 watched 27.7%

Current expedition status. Yes, this is a real metric I track.

Rounding out the app: a Hidden Gems finder with tunable sliders for how obscure or well-rated a suggestion should be, Lookback viewing analytics, and household sync across devices through a minimal Cloudflare Worker and KV.

Notable Decisions

Offline-first The library lives in IndexedDB and imports via streaming NDJSON, so the app works without a network connection once the seed is loaded.
Sync Started as a purely local app and evolved into a minimal Cloudflare Worker with KV, so my household's watch data syncs across devices without a full backend.
Recommender & graph Both the recommendation engine and the co-star connection graph are homegrown rather than third-party services, run entirely on the client against the local library.

Technology

Frontend React, TypeScript, PWA
Backend Cloudflare Worker
Storage IndexedDB (client), Cloudflare KV (household sync)
Seed data Weekly refresh from Cloudflare R2
Access Private, behind Cloudflare Access

Questions about how this was built, or want to talk about a similar project? LinkedIn Email