Counting on hostile ground
Instagram and YouTube are SPAs that rewrite URLs without navigation events. Polling the location, fingerprinting transitions, and separating swipe-up from back-swipe took real care to keep counts honest.
Case study · 2026 · Live at brainrot.quicklabs.pro
An extension + web platform that counts every Reel and Short you watch — and roasts you into stopping. Compete with friends for the cleanest brain.

BrainRot portal — stats, history, and the friends leaderboard
Overview
Everyone knows they watch too many Reels; nobody knows how many. BrainRot Counter answers that with a floating brain bubble that counts every Instagram Reel and YouTube Short you watch — and visibly rots as you blow past your daily target.
It's a full product: a Manifest V3 extension doing the counting, an Express/PostgreSQL backend syncing events, and a Next.js portal with stats, history charts, settings, and a friends leaderboard where the lowest count wears the crown.
3
Apps — extension, API, portal
24h
Rolling count window
4
Stages of brain rot
0
Video IDs stored — ever
Screen-time dashboards are easy to ignore because they arrive after the fact, in a settings menu you never open. The feedback has to live where the scrolling happens — on the video, in the moment, slightly judgmental.
And it had to be private by design: counting what you watch must not mean recording what you watch.
Three coordinated pieces around one loop — count, sync, shame, repeat:
Reels + Shorts detection from SPA URLs, swipe-vs-back disambiguation, rolling 24h window
A 4-stage rotting brain icon, progressive screen fade, milestone roast popups, optional hard-block wall
Offline outbox, idempotent batched uploads, server reconciliation for new devices
Friends leaderboard with invite codes, history charts, settings that sync to the extension
Video IDs are used in memory only to tell a new Short from a back-swipe — what leaves the device is {platform, timestamp, random event id}. There is nothing to leak.
Events queue in an outbox and upload in batches with client-generated IDs; the server dedupes on (user, event id), so retries, offline stretches, and reinstalls can't double-count.
Short-lived access tokens with one-use rotating refresh tokens — reuse is treated as theft and kills the session family. The portal hands tokens to the extension via postMessage.
Past your limit, a capture-phase event wall swallows scrolling input on the feed — polite enough to disable in settings, annoying enough to work.
Instagram and YouTube are SPAs that rewrite URLs without navigation events. Polling the location, fingerprinting transitions, and separating swipe-up from back-swipe took real care to keep counts honest.
The count lives on the badge, the bubble, and the portal simultaneously. A reconcile step rebuilds local state from the server's recent events, so a fresh install agrees with your history.
One person shipping an extension, an 81-file TypeScript API, and a Next.js portal means brutal prioritisation — the roast messages were, obviously, non-negotiable scope.
BrainRot Counter is live — the portal at brainrot.quicklabs.pro onboards you with Google, the extension counts and roasts, and friends compete for the crown. The Chrome Web Store release is packaged and pending listing assets.
It's my favourite kind of project: a meme on the surface, and underneath it, the most careful auth and sync engineering I've shipped.
What's next