Case study
Horrorometer
A horror-focused discovery and rating platform where fans track, rate, and surface scary movies, TV shows, and books. It scores titles on three genre-specific axes — Creepy, Gory, and Jumpy — instead of a single star rating, so fans can find what actually matches their taste.

- My role
- Sole engineer, end-to-end: product design, frontend build, backend/API architecture, database design, authentication, rate limiting and resilience patterns, Cloudflare Workers deployment, and observability setup.
- Year / status
- 2025 · Live product
01 — The challenge
One number can't describe a scare.
General-purpose rating sites flatten horror into one number. A slow-burn atmospheric film and a gorefest score the same 3.5 stars, so fans can't find what actually matches their taste. Horrorometer gives each title a multi-axis profile and lets users build watchlists and favorites around the kind of scare they want.
02 — The approach
Architecture, resilience, then interface.
Architecture first: defined the API surface before UI — file-based Next.js routes for primary resources, dedicated proxy routes with circuit breakers for TMDB and Open Library, and a legacy catch-all that redirects to the new routes. Resilience by default: external calls run through a circuit breaker (5 failures / 60s → 30s open, 2 successes to close) with 3-attempt exponential backoff, plus a graceful-degradation layer that returns cached/empty data when upstreams fail so the UI never hard-errors on a TMDB outage. Security hardening through two formal audits (2026-05-28 and 2026-06-27) drove 31 audit cards to done: CSRF on ~18 admin mutation routes, Zod enum validation on role escalation paths, fail-open rate limiting so a DB outage can't block all traffic, and PII-scrubbed Sentry breadcrumbs. Auth uses Firebase client-side with JWT verification in API routes, generic error messages to prevent info leakage, CSRF tokens with cleanup, and a 60s password-reset cooldown to prevent email enumeration. Edge-native deploy on Cloudflare Workers via @opennextjs/cloudflare, with three post-build patch scripts to make Next.js 16 run on the Workers runtime. Testing covers Jest unit coverage (migrating to Vitest), Playwright E2E with dedicated auth-flow suites, and 20 state-machine tests for OAuth device-flow race conditions.
03 — The outcome
A resilient, audited, live product.
Shipped to production on Cloudflare Workers with real users. 31 audit cards closed across two security/architecture audits covering rate limiting, CSRF, info-leakage, circuit breakers, and observability. RFC 8628 OAuth device flow implemented end-to-end (code issuance, authorize, token, polling, revocation) with compare-and-swap state transitions and full race-condition test coverage. External watchlist API with Bearer-token watchlist scope, plus read-only monitor-scope admin endpoints for external agents. Two cron routes (hourly prune, nightly inactivity sweep) with optional CRON_SECRET gating. Observability in place: Sentry with PII scrubbing, 10% production perf sampling, plus liveness and readiness health endpoints.
More work
Keep exploring.

Live product 2025
SENDadvisor
A national directory that brings days out, specialist services, schools, Local Offer information, and plain-English EHCP guidance into one calmer, more searchable experience for families navigating SEND across England.

Early access 2024
Kanaboards
A planning workspace where developers and coding agents work from the same board — the board is the shared surface, not the sync target.

Release candidate 2026
Stay With Me: Deep Sea
A real-time interactive horror story told through a damaged comms link. Help Mara survive 412 metres beneath the surface through messages, recovered footage, and choices that matter.