Skip to content
All projects
Web

Guesstrap

An Arabic online party word game for 3–6 friends: call words, set traps and work out everyone's secret rule

Year
2026
Status
Shipped
Role
Solo — game design, rules engine, backend and web app
Stack
Next.js · React · TypeScript · Tailwind CSS · Motion · Supabase · PostgreSQL · Deno · Zod · Zustand · Turborepo · Vitest · pgTAP · Web Audio
Guesstrap cover
Players
3–6
Words
969
Secret rules
36
Database tests
37

Problem

I wanted a party game in Egyptian Arabic that a group of friends can play together, each on their own phone. It is a bluffing game, and a bluffing game falls apart the moment someone can peek: any secret that reaches the browser can be read there. So nobody, not even a player watching the network traffic, may see another player's secret before the reveal.

Approach

Each of 3 to 6 players holds a secret rule (for example "words starting with م"). Every round shows a fresh grid of words, and within a few seconds each player calls one word and sets a trap on another. A call that lands on a trap costs points and pays the trapper. A call that fits your own rule pays extra, but the extra goes to a hidden score, so the visible points never give your rule away. The final reveal flips every rule, adds the hidden scores, and the ranking can turn over. Gold rounds, sudden death and power cards change the stakes, and bots can fill an empty seat.

Next.js web appArabic, RTL · UI onlyGame clientstore · server clockEdge FunctionsDeno · Zod-checkedRules enginepure TypeScriptPostgresRLS · Realtime
  • The server is the only referee. The UI never computes a score. Moves go to Supabase Edge Functions, a round is resolved in one database transaction, and row-level security on all 13 tables keeps each player's rule, call and trap unreadable by the others until the reveal. 37 pgTAP tests prove the secrets stay secret and open up when the game ends.
  • One rules engine, two runtimes. The engine is pure TypeScript with no dependencies; the clock and the random seed are inputs. The same code is tested with Vitest and runs on Deno inside the Edge Functions.
  • Layers the linter enforces. A pnpm and Turborepo monorepo: the web app talks to the game client, the game client to the engine and the shared Zod protocol. The imports each layer may use are an ESLint rule with its own test.
  • Content as data. 969 words and 36 rules, each rule matching at least 50 words, checked by a validator; Arabic spelling variants are normalized so they match. Every tunable number lives in a config table, and an admin portal edits words, rules and settings on the live game.
  • Game feel. A countdown synced to the server clock, a staged reveal, sounds synthesized with Web Audio (no audio files), haptics, and an installable PWA you join with a room code or a link.

Result

Live and playable at guesstrap.vercel.app. It was built in 12 phases, each with its own acceptance tests, and then revamped: a security hardening pass, a new toy-like design system and the admin portal. CI runs lint, type checks, tests and the production build across the whole monorepo.

1 of 2
How to play, steps 1 and 2: every player holds a secret rule, such as “words starting with م”; each round you call one word and set a trap on another
How to play, steps 1 and 2: every player holds a secret rule, such as “words starting with م”; each round you call one word and set a trap on another