Watchr: TV Time Shut Down, So I Built My Own

TV Time shut down, so I took my GDPR export and built Watchr, a self-hosted replacement, in two days with AI: TypeScript, Nuxt, PostgreSQL, Zero, and Capacitor.

6 min read

TV Time has known every episode of television I’ve watched for years, and then it shut down. I didn’t rage-quit over ads or a redesign. The app I’d fed my entire watch history to simply announced it was going away, and took its roadmap with it.

The one mercy: they provided a GDPR data export on the way out. So I took my history and built Watchr, my own replacement that runs on my homelab, works better than the original ever did for me, and took two days to build. This is the writeup.

#When your tracking app dies, your history goes with it

If you never used it, TV Time was a TV show and movie tracking app. You check in episodes as you watch them, it keeps your progress per show, and it gives you a calendar of upcoming episodes. That core loop is genuinely great, and it’s why I used it for years.

A shutdown is the failure mode nobody plans for with these apps. It’s not that a feature got worse or a subscription got pricier, it’s that the whole thing, including years of my data, had an end date. The GDPR export was the difference between starting over from memory and carrying my history forward, and it’s the reason this post has a happy ending.

Lesson learned either way: any app that accumulates years of your data needs an exit plan, and you want it before the shutdown email arrives.

#Everything I actually used fits on one screen

Before writing any code I made an honest list of what I used in TV Time versus what existed in TV Time. The gap was embarrassing.

What I kept:

  • Episode check-ins, the whole point, one tap per episode
  • Per-show progress, which season, which episode, how many left
  • An upcoming calendar, so I know when the next episode of something airs
  • A watchlist for shows and movies I haven’t started

What I cut:

  • The social feed, comments, and reactions
  • Badges, streaks, and whatever gamification was left
  • Every notification except “a show you watch aired today”

I did keep one indulgence, a small stats page with totals and a “hours of my life spent on this show” counter. It serves no purpose, but it’s my app and nobody can stop me.

#The stack: TypeScript front to back, with Zero doing the magic

Watchr is TypeScript everywhere: a Nuxt app on the front, PostgreSQL holding the data, and Zero in between.

Zero is the piece worth calling out. It’s a sync engine that keeps a local replica of my data on the device, so every screen reads and writes locally first and syncs to Postgres in the background. In practice that means check-ins are instant, navigation never shows a spinner, and the app still works when my phone has one bar in a basement. TV Time round-tripped to a server for everything; Watchr feels faster because most of the time it isn’t talking to a server at all.

The whole thing ships as a Docker image on my homelab, and Capacitor wraps the same Nuxt app into a real mobile app for my phone. One codebase, one language, and the couch check-in experience I actually wanted, minus the full-screen ad afterwards.

#One day to build, one day to polish, all with AI

I’ve written before about my “endless personal software” philosophy, the idea that AI coding agents have made it practical to build custom software for an audience of one. Watchr is that idea in practice, and it’s the fastest proof of it I’ve produced yet.

Day one: I described the data model and the screens I wanted, and by that evening the core loop worked, check-ins, progress, calendar, watchlist. Day two was polish, the stats page, the rough edges, the Capacitor build for my phone. Two days, total, with the agent doing the bulk of the typing while I steered, reviewed, and occasionally vetoed.

That timeline is the entire argument. A self-hosted, local-first, mobile-wrapped app to replace a product a whole company used to run is now a two-day project. Watchr doesn’t exist because I’m fast; it exists because the cost of building it collapsed below the cost of living without it.

#Importing years of history from the GDPR export

The one genuinely fiddly part was the migration. The GDPR export gives you your check-ins with show and episode names, but no useful stable IDs, so I had an import script match every show against TMDB, which is where Watchr gets all its show and episode metadata (the API is free for personal projects). A nightly job pulls air dates for the shows I’m actively watching, which feeds the upcoming calendar.

Exact title matches covered most of the import. The rest was the usual mess, shows with reboots sharing a name, year mismatches, a few titles renamed since I watched them. I ended up with a short manual review list and fixed those by hand. Tedious, but it was a one-time cost, and now the history lives in my Postgres database instead of a company’s farewell email.

If you’re doing something similar, log every fuzzy match your import script makes instead of trusting it. The confident wrong matches are the ones that will haunt your stats page.

#What software with a userbase of one feels like

This is the part that’s hard to convey until you’ve used an app built for exactly one person. There’s no onboarding, no settings for preferences I don’t have, no feature I have to route around. Every screen exists because I wanted it, and when something annoys me it’s usually fixed the same evening.

There are real tradeoffs. Nobody else is finding my bugs, there’s no community keeping metadata tidy, and if the nightly TMDB sync breaks, the only on-call engineer is me. I’m fine with that deal. And unlike TV Time, Watchr cannot shut down on me. I’d have to shut down on it.

#Takeaways

  • Most of the value in a tracking app is a tiny core loop. Rebuild that, skip the rest, and you’re 90% done.
  • Local-first is a superpower for personal apps. Zero made Watchr faster than the product it replaced, essentially for free.
  • Export your data before you need it. A GDPR request is the difference between losing years of history and migrating it in an afternoon.

If an app you rely on ever announces a shutdown, file the data request the same day, list the three features you actually use, and hand the boring parts to an agent. It took me two days to end up with something better than what I lost.

↑↓ navigate↵ openesc to close