← Back to projects
Live

Nostalgia Lab

A free, non-profit retro console preservation platform: a quarter-million-ROM archive you can play with friends.

  • 238KROMs auto-matched
  • 104Kgame releases
  • 887Kmedia assets
  • 20+console systems
Screenshot 1 The library at play.nostalgialab.org, navigated like a console: a controller-driven system picker with box art and release details.
Screenshot 2 A release page: box art, ratings, regional release dates, and enriched metadata for Secret of Mana.
Screenshot 3 The public GraphQL API at api.nostalgialab.org: an annotated schema and a live query returning the full release record.

Nostalgia Lab is the project I point to when someone asks whether a sales engineer can still build. It is a non-profit retro-console platform I architected, wrote, and operate: a quarter-million-ROM archive that identifies itself, plays in the browser, and lets people play together. Seven services, one identity, real infrastructure.

The catalog: teaching a database to recognize a quarter-million ROMs

The hard part of a game archive is not storage, it is knowing what each file actually is. Nostalgia Lab ingests DAT files from Redump and No-Intro into a 374,000-row lookup table of CRC32, MD5, and SHA1 signatures. An autonomous linker daemon then works through unidentified ROMs in a four-tier cascade: an exact MD5 hit first, then CRC32 scoped to the system, then filename, and finally a fuzzy PostgreSQL trigram match at 92% similarity for the dumps that DAT files miss. Region scoring prefers USA, World, and Europe variants, and every regional dump collapses onto a single canonical release. The result is 238,376 ROMs resolved to 103,926 releases, reconciled continuously rather than in a one-off import.

Enrichment: filling in a hundred thousand games without a human

A raw catalog is just names. A four-tier enrichment pipeline gives each release a genre, description, developer, publisher, and cover art by trying Wikipedia, then web search, then a language-model fallback that writes structured metadata and a long-form description. It runs several workers in parallel against a Postgres-backed token-bucket rate limiter that coordinates quota across instances, backs off on failure, and respects daily third-party API limits. Roughly 83% of releases now carry a rich description, with vector embeddings staged for semantic search.

Play, and cloud saves that stay legal

Games run entirely in the browser on libretro cores compiled to WebAssembly, covering 20-plus classic consoles. Nostalgia Lab never hosts copyrighted ROMs: you point it at your own files through the browser's File System Access API, and they never leave your device. What syncs to the cloud is your progress. Save states and SRAM are encrypted with a per-user AES-256-GCM key, wrapped by a master key held in Secret Manager, and stored in your own Google Drive or OneDrive. Your games stay yours; only your saves travel.

Playing with friends

Multiplayer is the feature everyone wants and almost no browser emulator gets right. Nostalgia Lab uses a host-authoritative design: only the host runs the emulator, streaming video and audio over WebRTC while guests send controller input back over a data channel. That sidesteps the desync problems of rollback netcode on non-deterministic WASM. A signaling service holds room state, presence, and rosters in Redis and routes WebRTC offers across auto-scaled Cloud Run instances with pub/sub, so there are no sticky sessions. Friends connect with a nine-character friend code you can type on a controller, see each other in real time, and drop into an open seat directly. A disconnect holds your seat for a grace window instead of dropping you to a lobby, and the client re-opens its socket before Cloud Run's 60-minute request timeout can interrupt a session.

Media and search at scale

887,000 media assets, box art, screenshots, marquees, and clips, are transcoded to WebP and WebM and served from S3-compatible object storage through a Cloudflare CDN, with presigned URLs minted by the GraphQL API. Search runs two live strategies at once, trigram similarity for typos and full-text search with English stemming for descriptions, with pgvector semantic matching staged on top. A hybrid executor merges the results by relevance and flags a confident direct hit, so a query like "best SNES RPGs from the 90s" lands somewhere useful.

The platform underneath

All seven services share one sign-on. The login service mints HS256 JWTs that every service verifies locally, with a Redis denylist that makes logout revoke instantly. Cloudflare Workers stamp every origin request with a shared secret and the services fail closed if it is missing, so the GCP origins cannot be reached around the edge. The whole platform is provisioned as code: Cloud Run services, a private VPC whose database and Redis VMs have no public IP and are reached only through an IAP tunnel, secrets in Secret Manager, and Cloudflare DNS and Workers. GitHub Actions deploys through Workload Identity Federation with no long-lived keys, promoting dev to stage to prod on separate workflows so application and infrastructure changes never race.

Stack

  • SvelteKit
  • Vue 3
  • Express
  • GraphQL Yoga
  • PostgreSQL
  • pgvector
  • Redis
  • WebRTC
  • WebAssembly
  • GCP Cloud Run
  • Cloudflare Workers