MovieTQ
A real-time multiplayer movie game. Four live modes, five play languages, and one profile that carries across all of them.


Bomb-It · demo
Game modes
Trailer Quiz
A trailer clip plays for everyone in the room at the same moment. First to type the correct title takes the round.
Bomb-It
A timed survival mode: name a movie that fits the prompt before your timer runs out. Run out of time and you lose a life.
Daily
One hidden film a day, the same one for every player in the world. Each guess is scored column by column until someone lands it.
Pet Feast
A snake arena played with your pet: grow by feeding, hold your line, and outlast everyone else on the board.
More modes
More ways to play are on the roadmap, including a voting-based mode. Pet Battle, the pet card duel, is being reworked and reads as coming soon in the meantime.
Features
Rooms & access
- Public lobbies
- Private, password-protected rooms
- Genre and difficulty (1–10) filters
- Five play languages
- One-click guest sessions
Social
- Friends gallery with presence
- Direct messages
- Lobby chat and emotes
- Global leaderboard and Walk of Fame
Progression
- XP, levels, and achievements
- Popcorn in-game currency
- Wardrobe — avatars, titles, backgrounds, emotes, effects
- A pet that follows you into every mode
- A daily gift calendar
Accounts & membership
- Email, Discord, or Google sign-in
- Memberships in three tiers
- Popcorn packs and gifting
- No scoring advantage, ever
Leaderboard & profiles
Recreated from the in-game leaderboard — real cards, live ranking and stats. Click the card to open the profile.






One person. The whole stack.
Frontend, backend, database, payments, security, and deployment — all built and shipped solo.
Built with
- React
- TypeScript
- Vite
- Tailwind CSS
- react-youtube
- Node.js
- Express
- WebSocket
- Supabase
- PostgreSQL
- Stripe
- JWT
- bcrypt
- node-cron
- Cloudflare
- Render
Engineering
Server-authoritative rooms
The game’s brain runs on the server, not in your browser. A room advances through its own states on the server and pushes each change out to everyone at once — so nobody can win by tampering with their own screen, and everyone sees the same trailer moment together.
Each room is held in memory and advanced through a LOBBY → STARTING → IN_ROUND → BETWEEN_ROUNDS → FINISHED state machine by a server-side clock, with per-match isolation so one bad room cannot stall the others. Clients are render-only: they reconcile to the broadcast rather than deciding anything, so a tampered client cannot alter the outcome, and the round’s answer is not part of the payload until the reveal.
Pushed, not polled
Your browser doesn’t sit there asking the server whether anything happened. Each player holds one open channel and the server talks down it, so a new round, a rival’s guess, a chat line, or a tomato thrown at you lands the moment it happens. If that channel can’t be opened at all, the game quietly falls back to asking on an interval and play continues.
Live state is delivered by server push over Server-Sent Events — one authenticated streaming GET per client, carrying a full public-state snapshot on every state change, for Trailer Quiz and Bomb-It alike. The stream doubles as the presence heartbeat, so a closed socket ages that player out rather than leaving a ghost in the lobby. Trailer Quiz keeps an interval poll of the same state as an automatic fallback for a browser that cannot hold the stream, and both paths share one serializer so they can never disagree.
Separated middleware pipeline
Every request walks one ordered line of checks before any handler runs, so each concern is isolated and a bad request is rejected at the earliest gate rather than deep inside game logic.
Every request walks a single ordered middleware chain covering transport and cookie handling, cross-origin and CSRF checks, per-route rate limiting, schema validation with prototype-pollution and XSS sanitization, and authentication — all of it before a route handler sees the request. Each concern is isolated and independently testable, the ordering is load-bearing and pinned by tests rather than left to convention, and anything that fails a gate is rejected at that gate.
Preloaded movie catalog
The trailers themselves aren’t stored — what loads into the server’s memory at startup is each movie’s info and its YouTube trailer link. During a round the clip plays straight from a YouTube embed in the player’s browser, so the server never serves video and a round never waits on an outside lookup. Difficulty simply controls how deep into the fame-ranked list the game is allowed to reach.
~58,000 films’ metadata — titles, info, and YouTube trailer ids — are parsed from JSONL into memory at boot and sorted by fame; no video is stored server-side. Genre maps UI labels onto dataset categories; difficulty slices the sorted pool — top 100 at level 1 up to the whole pool at level 10 — before a non-repeating random draw. The trailer plays client-side through a YouTube embed, so no external lookup happens during a match.
Five languages, one catalogue
A room can be played in five languages, and a film is matched by its official title in the language you picked. Rather than hold five copies of the catalogue in memory at once, the game builds the index for a language the first time somebody plays in it. Accents are optional in both directions, so “criança” and “crianca” are the same answer.
Catalogue rows carry an optional map of each film’s official title in the other languages, and a room’s language selects which title set the round is played and matched in. The per-language pools and their exact and alias indexes are built lazily on first use because RAM is the binding constraint — roughly +11 MB for the data and +14 MB per active language. Matching NFD-folds diacritics in both directions, so an accent never decides a correct answer.
A daily challenge with nothing to peek at
Every player in the world gets the same film each day, and it is chosen by the date itself rather than drawn at random — so the day is reproducible and recent answers are skipped. Nothing about the answer reaches the browser before you find it: the colours on each comparison row are worked out on the server from the guess you sent.
The day’s answer is derived from the date itself rather than drawn at random, skipping anything used recently — so every player worldwide gets the same film, and the day is reproducible without storing a schedule anyone could read ahead. The challenge row snapshots the film’s title, year, directors, and genres, so an earlier day still reveals correctly after the pool changes. Comparison rows are re-derived server-side on every read: the client never supplies them, and the answer’s attributes stay out of the payload until the win. Shared counters are atomic database operations, so the solve position a player sees is the value the increment returned rather than a read-modify-write race.
One simulation, three consumers
The snake arena would feel sluggish if every keypress had to cross the network and come back, so it doesn’t. Solo and bot games run entirely in the browser; in a multiplayer room your own snake turns the instant you press a key while the server stays the referee for everyone else. Bot rounds are re-run on the server afterwards from the same code, so a game that feels local is still scored honestly.
One deterministic arena module is stepped by three consumers — the server tick, the client’s own-snake prediction, and the server-side replay of a bot round — so they cannot drift apart. Multiplayer rides a WebSocket authorized once at connection time and carrying no credentials per message, and each tick is serialized once per room rather than once per client. The client predicts its own snake by rolling back and reapplying unacknowledged inputs and interpolates the others; a per-snake input queue whose legality is checked against the queue tail means no keypress is silently dropped. Nothing a client reports is trusted for scoring: a bot round runs locally for feel, then the server re-runs it from the same module before it counts.
Resilient trailers
If a trailer is dead or blocked in someone’s region, the round doesn’t stall. A player report (or a host reroll) swaps in a fresh clip and resets the timer, so nobody loses points to a broken video.
A report or a host reroll is validated against the live round it claims to be about before anything changes, so a swap cannot be driven from outside the round. A replacement is drawn from the in-memory pool, the round swaps to it, the timer resets, and guesses already made are cleared so they cannot carry onto the replacement.
Identity across the proxy chain
The API is fronted by more than one hop, each of which would otherwise present itself as the caller. The requester’s identity is carried across those hops in a form the edge attests to and the application verifies, so it cannot simply be asserted by whoever is calling — limits and bans act on the real requester, and the guarantee holds without the application having to trust a forwarded value at face value.
Server-enforced authorization
The backend is the only gatekeeper, so it treats every request as untrusted: it validates everything, checks where it came from, and can revoke a session instantly. Staff muting, banning, and audit logs sit on top.
Authorization is enforced entirely server-side rather than delegated to the data layer, so every query the application issues is treated as a security boundary and no client-supplied claim about who you are is trusted. Sessions ride in cookies the page’s own scripts cannot read, and each request re-checks that the session is still good — so revoking one takes effect on the very next request instead of whenever it would have expired.
Scheduled upkeep
Quiet background jobs keep the game tidy on their own — for example, clearing out guest sessions once they expire so old data doesn’t pile up.
Scheduled server-side maintenance runs off the request path — expiring guest sessions once their window has passed and keeping in-memory state lean — with no manual intervention and no effect on request latency.
Role-aware admin console
Behind the game is an internal operations console where trusted staff run the live service: watching activity and cost, moderating players, working through player and trailer reports, scheduling background jobs, and flipping site-wide switches when something needs to stop. The console reshapes by role — a moderator gets a focused reports-and-audit view rather than the full set of controls — and every action is logged for accountability.
A role-gated console whose surface is decided server-side from the staff role, so a moderator’s view resolves to a genuine subset rather than admin-only tools sitting hidden in markup a client could read. Global runtime switches let the service be degraded deliberately — closing new signups, pausing match creation, taking a subsystem offline — and are enforced in the request layer rather than only in the interface. Deferred operational actions are queued off the request path, moderation evidence is compiled beside each case so a decision is made in one place, and every operational action is written to an exportable audit log.
Social
MovieTQ is a social game too — identity, friends, rivalry, and live in-room expression. The two panels below are real and interactive — try them.
You
YouProfiles & cosmetics
Every player is a recognizable identity — a portrait, a level, an equipped title, a background and a bio that follow them across every screen.
Friends & DMs
Send and accept requests, see who’s online, and chat one-to-one in lightweight popups — friends become collectible player cards, not address-book rows.
Global leaderboard
Ranked by level with the top three highlighted gold/silver/bronze; your own row stays pinned even when you're off the visible page. Tap a row to open the profile.
Store & inventory
Earn Popcorn from matches and level-ups, then spend it on cosmetics. Rarity drives both price and prestige; equip anything you own straight from the inventory.
Achievements
Proof-of-play with progress bars and rarity badges. Unlocks grant titles, cosmetics and Popcorn — and surface as the trophy strip on your profile.
Safety & staff
Calm, visible safety tools live next to the person they affect, with separate staff controls and an official Mod Team roster so players know who represents the game.
Have a dream project?
Tell me your idea and I’ll send you a quote.
