A self-hosted tracker for TV, film, books, podcasts and music. Check off episodes as you watch, and record whether you watched them alone or with someone. Built to replace TV Time's core loop, on a server you control, with an invite list instead of a signup page.
Every tracker knows you finished the season. None of them knows who was on the sofa. That second fact turns out to be the one worth having years later, so MediaPassport treats it as a first-class column rather than a note you might have left.
A watch event with no companion rows is a solo watch. Recording absence rather than
writing a sentinel keeps "alone" and "with three people" the same shape of query,
and it makes tagging a past watch an INSERT instead of a migration.
The interface leans on it: red means solo, purple means co-watched, so scanning down a season tells you at a glance who you watched each episode with. Companions are named people, not accounts. No invites, no permissions, no second login for somebody who just sat there.
TheTVDB and TMDB are not equivalent, and the app uses both. Each supplies something the other omits entirely.
MetadataProvider, and nothing outside src/lib/providers/ imports either one directly. Adding a third source is one new file.remoteIds carry the TMDB id and it is stored at ingest. A show with no cross-reference simply gets no panel, never a lookup with the wrong provider's id.JustWatch has no public API. It is enterprise data-partnership only, and the unofficial scrapers that exist violate their terms. But TMDB licenses this exact data from JustWatch and exposes it on an endpoint the app already has a key for, so it arrives legitimately with no scraping and no second integration.
Two conditions come attached, and both are enforced in the component rather than left to good intentions: JustWatch is credited as the source, and the panel links out to TMDB's page rather than inventing per-service deep links, which the API deliberately withholds. TMDB revokes access for non-compliance, so this is a correctness requirement, not a courtesy.
Results cache for twelve hours, and the panel is omitted entirely when the provider has nothing for your region. A provider outage degrades to a missing section rather than a broken page.
MediaPassport is the furthest along of the Locke Werks house apps: it is deployed and in daily use on our own infrastructure. Next.js 16, React 19, TypeScript, Drizzle and PostgreSQL, running as its own service user behind our own reverse proxy.
The source is private. For access or a conversation about running your own, write to archon@lockewerks.com.