
Catalogie
Keep track of everything you watch, play and read, with movies, TV, games and books all in one place, running on a PERN stack that we host ourselves.
- Role
- Team
- 3 people, collaborative
- Type
- Stack
- Status
- Live & ongoing since Jun 2026
- Version
- v1.2.0 - 6 releases shipped
01Overview
Catalogie is a media tracker that brings movies, TV series, games and books together in one catalog. Each type of media is tracked in the way that actually makes sense for it, so you log TV by the episode, movies by the watch, games by the hours you’ve played and books by the page.
It’s a real product with real people using it. The three of us built it and run it ourselves on our own hardware, with an API written in strict TypeScript, and we’re still adding to it. We’ve shipped six versions since launching in June 2026, and each one came with a public dev diary. This page covers both parts of the project: the app itself at app.catalogie.com and the marketing site at catalogie.com.
Product problem
We needed to track four kinds of media that measure progress in completely different ways, all in one library, without any of them feeling like an afterthought stuck onto a TV app.
Data problem
There’s no single catalog that covers all four. Each one comes from a different provider with its own login method, usage limits and licence terms, and none of those keys could ever be allowed to reach the browser.
Platform problem
People only trust a tracker if their history is safe. That meant real accounts, a real database, backups and infrastructure we control, rather than just saving things in the browser.
Team problem
Three of us work on the same codebase, and there’s also a native app in a separate repository. So the API had to be a properly documented contract that everyone could rely on, not just an internal detail.
02Key Features
One library, four media
Each type of media has statuses that use the right words, like watching, playing, reading, wish and TBR, along with favourites and custom filters.
Progress at the natural unit
Episodes are grouped inside seasons, pages inside books and hours inside a playthrough. You can mark a whole season at once or log a session with the date it happened.
Ratings on your scale
You can choose five stars with half stars, or a ten-point scale, separately for each type of media. You can also rate individual episodes, and see outside scores alongside an anonymous average from the community.
What’s next
Your watchlist, backlog and to-be-read pile all live in one queue. There’s also a release calendar, and you can turn on push notifications for new seasons and launches if you want them.
Stats & Yearly Wrap
See how much time you spend on each type of media, your favourite genres, a heatmap of your activity with streaks, more than 35 badges with different tiers, and a yearly wrap-up for any year you choose.
Social layer
Follow other people, control exactly what’s visible on your profile down to individual titles, and leave threaded comments with reactions and images.
Importers
Bring across years of watch history from other services. Your data is read, matched against our catalog and shown to you for review before anything is added.
Reader-contributed books
If a book is missing, you can describe it once, and after a quick moderation check it becomes a shared entry that everyone can track.
03Screenshots
Screens taken from the real product. Tap any of them to see it full size.















04Architecture
Catalogie is a modular monolith on the PERN stack, which means one Express process with fourteen feature modules and background jobs running inside it. It’s hosted on an Oracle Ampere A1 virtual machine (4 OCPUs, 24 GB of memory, arm64) behind Caddy. Caddy serves the app at app.catalogie.com and forwards API calls to api.catalogie.com, which keeps the login cookies first-party.
The progress model
A library_entries row stores the details that every type of media shares, like status, favourite, rating and notes, with one row per user per title. Everything that’s specific to a type of media goes into event tables that are only ever added to: episode_watches, title_watches, play_sessions and reading_logs. That way, rewatching a show or rereading a book adds a new row instead of overwriting the old one.
One activity view
All four event tables are combined into one SQL view called activity_events. That view powers the streak counter, the heatmap and the yearly wrap-up, so finishing a book and beating a game both count towards the same streak.
Federated metadata
Data about films and TV, games, books, ratings and release dates is fetched through typed clients that only run on the server. The API keys live only in environment variables, requests can only go to an approved list of hosts, each one times out after 10 seconds with a single retry, and results are cached in memory and in Postgres so we stay within the shared usage limits.
Layered API
Routers read the request, services make the decisions and repositories run the queries. Zod checks the data at every boundary, ownership always comes from the logged-in session, and the API is documented with OpenAPI so both the web and native apps can use it.
Auth for two clients
Login uses better-auth with email and password or Google, and sessions are stored in the database. The website uses first-party SameSite=Lax cookies, while the native app uses the bearer token plugin, because it doesn’t run in a browser.
Jobs in Postgres
pg-boss runs scheduled jobs inside the database itself: syncing episodes, updating release dates, refreshing ratings within the usage budget, cleaning up uploads, sending emails from an outbox and delivering push notifications. Every job is safe to run more than once and gets retried if it fails, and there’s no need for Redis.
05Tech Stack
Client
API
Data & jobs
Infra & quality
Marketing site
06A Collaborative Build
Catalogie started as my idea, and now the three of us design, build and look after it together. Work moves from personal branches to a reviewed dev branch and then to main. Along the way, CI lints, type-checks, tests and builds both the app and the site, and also runs npm audit and a gitleaks scan over the full history.
Ruchira Edirisinghe
I came up with the concept and look after the product direction and UI design. I also built the React client and the TypeScript backend, all the way from the database schema to deployment.
Nimna Niwarthana
Nimna works on design and engineering across the client, the API and the infrastructure, and also built the admin panel.
Thaanu Perera
Thaanu builds the native iOS and Android apps on top of the same API, which is the reason we designed everything API-first from the very start.
07Release History
It isn’t finished, and it isn’t meant to be. Every version comes with a dev diary written in plain English, including the bugs we got wrong.
v1.0.0 · 13 Jun 2026
The first launch, with movies, TV, games and books in one library, progress tracked by episode, page or hours played, a stats dashboard, and accounts that are private by default.
v1.1.0 · 14 Jun 2026
Added following and public profiles, comments and reactions, optional push notifications and Founding Member badges.
v1.1.1 · 15 Jun 2026
Fixed a sign-up bug that could lock people out of their accounts, resent verification emails automatically and added a new date picker for when you watched something.
v1.1.2 · 16 Jun 2026
Made sign-in clearer with links to the Terms and Privacy pages, switched to self-hosted fonts so the layout stopped jumping around, and added the Dev Diaries page.
v1.1.3 · 17 Jul 2026
Cut the size of the library data in half, made posters load only when needed, kept counts live across all your devices, and finally showed movie watch dates.
v1.2.0 · 25 Jul 2026
Added books contributed by readers, separate rating scales for each type of media with community averages, ratings for individual episodes, more than 35 badges and completely rebuilt Yearly Wraps.
08Engineering Challenges
09Results & Learnings
- A live tracker that we host ourselves, with real accounts. It covers four types of media with four ways of tracking progress, lets you rate on your own scale, and includes a social layer, stats, importers, a release calendar and push notifications.
- Most tests run against a real Postgres database, plus a permissions matrix that checks user A can never touch user B’s entries, comments or uploads.
- Encrypted backups are copied off the server every night and kept for 30 days, and we practise restoring from them once a month.
- It’s free forever, private by default and you can export your data for free. The first 1,000 accounts become Founding Members, and catalogie.com shows a live count straight from the production API.
- Next up: the native iOS and Android apps on the same API, more importers, and a second server region behind a CDN.
What I learned
- Shared usage limits on outside services are part of your production setup. They need to be treated as carefully as a database, not like something to play around with in tests.
- You can rebuild a product while it’s live, as long as the new system grows next to the old one and every commit could be shipped.
- Measure before you optimise. The bottleneck turned out to be the CPU, not the database that everyone suspected.
- Keeping a log of our decisions and writing a dev diary for every release keeps the three of us on the same page, and it’ll help us later on too.