Rankle
A daily tier-list game: one topic, rank it, submit, then see how everyone else ranked it too.
One topic a day. Rank it, then see who agrees.
Rank
Every day, one topic and a fixed set of items. Place each one into a tier — S, A, B, C, F, or N/A if you haven't tried it.
Rank the shapes — select one, then choose a tier.
Submit
Submitting locks the ranking. One official ranking per player per game, enforced by a database constraint below the one server action that can write it — not a disabled button.
Compare
See the community's tier distribution, the consensus, the controversial items, and where your own ranking disagreed.
Share
Send a link. It's spoiler-protected: whoever opens it has to submit their own ranking before they can see yours.
Return tomorrow
A new topic releases on its own schedule. No account required to play any of it.
Rankle only shows you the argument after you've taken a side.
- No signup required to play — an opinion shouldn't have a login wall. Guest identity is a signed cookie, not an account.
- Results stay locked until you submit your own ranking, checked twice, server-side, independent of whatever the page shows.
- Sign up later and your guest history follows you in — nothing about the original ranking is rewritten to do it.
Three decisions the database actually enforces
A simple architecture: the browser, then Next.js, then Supabase.
Browser
Next.js / React UI
Next.js
Server Actions · Route Handlers · Server Components
Supabase
PostgreSQL · Auth · Storage · Row Level Security
Constraint
Play had to work with no signup, without resorting to device fingerprinting.
Decision
Guest identity is a random UUID in a signed, httpOnly cookie — HMAC-SHA256, verified in constant time, never readable or forgeable by the browser.
Why it mattered
Sign in later and Rankle claims that guest's submissions into the new account without ever mutating the original, immutable row.
Constraint
Community results had to stay invisible to anyone who hasn't played — not just hidden in the UI.
Decision
Two independent server checks stand between a visitor and results: a cheap boolean redirect for UX, and a SECURITY DEFINER Postgres function that's the actual authority.
Why it mattered
Even a raw call straight to the database can't see results early — tested at the RLS, integration, and end-to-end layers.
Constraint
One official ranking per player per game had to actually hold, not just look like it holds.
Decision
Enforced by a unique database constraint, not a disabled submit button or client-side state — the server action reads identity from a trusted cookie, never the request body.
Why it mattered
A duplicate or retried request can't double-count community statistics; it just reports back the already-submitted state.
Real repository. Real deployment.
Every change to Rankle passes through the same five required checks before it reaches production — built and shipped solo.
- 15version-controlled database migrations
- 36Vitest unit & integration test files
- 12Playwright end-to-end specs
- 5required, parallel CI checks per change
- 10tables enforcing the product's own rules