Home/Work/WatchWise

Consumer product & ranking systems

WatchWise

A time-boxed recommendation engine: tell it how long you have and what you're in the mood for, and get three ranked picks with the reasoning attached.

Type
Consumer product
Stack
FastAPI · React · SQLite
Scoring
9 components
Monetisation
Tier system, dormant

The situation

You have ninety minutes and four subscriptions. You spend twenty of them scrolling.

This is a genuinely interesting product problem hiding inside a trivial complaint. The streaming services optimise for engagement with their catalogue; none of them knows what else you pay for, none knows you have ninety minutes rather than three hours, and none will ever recommend the thing you already own over the thing they're promoting.

The real constraint isn't taste. It's time, cost and availability — three things every existing recommender treats as an afterthought.

What was built

A time-boxed recommendation engine. You say how long you have and what you're in the mood for; it returns three ranked picks.

The scoring model combines nine components: time fit, intent match, taste similarity, availability, cost advantage, recency, diversity, a subtracted fatigue penalty, and an ownership boost. Time fit and intent carry the most weight; skipping something teaches it within the session; what you already own wins ties against what you'd pay for again.

  • Tonight — three picks with a match percentage, a “why this” in under twenty-five words, and service, price and runtime chips.
  • Personal TV Station — a generated seven-day schedule with a genre-diversity rule preventing two consecutive days from sharing a genre pair. Slots suit the day: weekday evenings, Friday nights, weekend afternoons.
  • Insights — genre breakdown, content-type split, viewing timeline, and skip-reason analysis. The skip reasons are the interesting chart; they tell you things about your own taste you'd deny out loud.
  • Region and language scoping across nine regions and ten languages, with local pricing and deduplicated sources — because “available on Amazon” means something different in Hyderabad than in Chicago.

Stack: Python, FastAPI, SQLAlchemy, SQLite in WAL mode; React, Vite, Tailwind. Scheduled jobs on IST for daily snapshots and weekly schedule generation. Optional catalogue integrations. Test suite. Ships pre-seeded so it works with no API keys at all.

The weights are yours

Where this system can be wrong

Two mechanisms, and they're related.

The weights are published and yours to change. Every scoring coefficient is in the documentation and adjustable by slider in Settings. A recommender that won't tell you what it optimises for is asking you to trust that its interests match yours — and in every commercial streaming recommender, they don't. Exposing the weights means a user who disagrees with the model can correct it rather than abandon it.

Every recommendation shows its opportunity cost. The gap between this pick and the best available one, displayed on the card. It's an unusual thing to show. It amounts to the product saying this is my second choice and here's how much worse it is — which no engagement-optimised system would ever volunteer.

There's a third, smaller instance of the same instinct: the acceptance criteria are written down and tested. Five of them, each with a test. Stating what “working” means before claiming it is the cheapest honesty mechanism there is, and most side projects skip it.

What happened

WatchWise runs end to end: registration, authentication with rate-limited login, multi-profile support, live catalogue expansion via user-supplied API keys, daily database snapshots with one-click restore, and a scheduled weekly regeneration.

The commercial infrastructure is built and deliberately dormant. Every user carries a tier — beta, free, or pro. Beta users get full access at no cost. The Settings page shows the current plan, a comparison, and a wired upgrade button with no payment provider attached. Gating a feature later is a single check on the relevant endpoint; no schema change, no frontend work.

That's the part worth showing a client. The interesting engineering decision wasn't the scoring algorithm — it was building monetisation as a dormant capability, so the decision to charge is a business decision rather than a rebuild.

What made it repeatable

The architecture separates the scoring engine from the schedule service from the API clients, so the model can be tuned without touching delivery. Snapshot and restore mean a bad catalogue refresh is recoverable.

Most transferably: the pattern of user-provided API keys. Rather than a shared server key that rate-limits everyone at once, each user brings their own — stored per profile, removable in one click. It removes a whole category of scaling cost and support burden.

The engagement shape

For a client with a recommendation, ranking or prioritisation problem:

  1. Name the components. What actually determines a good answer here? Usually five to ten factors, most of which nobody has written down.
  2. Make them explicit and weighted. A legible model beats an accurate black box wherever a human has to defend the output.
  3. Build the loop — capture the correction and feed it back.
  4. Show the cost of the recommendation, not just the recommendation.

What's still open

Named, not hidden. A case study that admits open items is worth more than one that doesn't.

  • Catalogue enrichment is imperfect and the product says so. One provider returns complete metadata for roughly 60–70% of requested titles; another does better. The documentation states this plainly rather than letting a user conclude the app is broken.
  • Some series have no runtime. Handled gracefully, but time-fit scoring is weaker for those titles. A known gap, not a hidden one.
  • Local pricing uses a fixed conversion. Fine for comparison, wrong for precision.
  • No payment provider connected. By choice — but it means the tier system is untested against real transactions.

Next case study

AdCraftAI →