One mechanic each, one shared arcade layer, and one engine written three times over so no copy of the rules is ever trusted on its own.
Match the target — overlapping sheets add their light.
The lineup
Each game is one mechanic taken as far as it goes. They share the progression, the coin economy, the daily challenge and the leaderboards — which is the only reason one studio can keep three of them running at once, and why the fourth costs a fraction of the first.
Stack the light until it matches.
Drag translucent sheets across the board. Where they cross, their colours add and get brighter — gels stacked in front of a stage light. Every cell you see was composited by the engine, not blended by the GPU, because the win check is literally does it render the same.
The same five hues, composited live.
One move. Every world.
Every world moves at once, and each one reads your input its own way — as given, mirrored, transposed. A wall stops one explorer while the others carry on, and that desync is the only tool you get. The puzzle beside this is generated fresh and solved by breadth-first search, so the par is real.
Fold it. Punch it. Prove it.
Crease the sheet, punch through every layer at once, then unfold and read what you actually made. One hole becomes many, every crease is a mirror line, and the puzzle runs backwards — you are given the pattern and have to work out the folds.
Target
The sheet
That is deliberate, and it is the single most important thing to understand before changing any of it. Each port has a different job, none of them is trusted alone, and they are pinned to each other by frozen test vectors rather than by good intentions.
Port 01 · the reference
src/engine/
The authority on what a level is. Generates every pack offline; only its frozen output ever reaches a player.
Port 02 · the judge
server/internal/engine/
Replays a submitted move log and awards only what the replay proves. One run costs 32 microseconds.
Port 03 · the player
packages/raa_engine/
Runs the game on the phone and scores it locally, so the result screen is instant and works with no signal at all.
The client tells the server what it did, never what it earned.
Levels are deterministic from their pack and the engine is pure, so the server replays the move log and computes the outcome itself. Coins, stars, trophies and board positions are all decided on that side; prices are constants in the API, never values in a request body. Continues and clue purchases are brokered through our own records rather than believed — any scoring field in a submission would be a hole.
Every figure here is produced by a command in the repository, and the command is printed underneath it. Re-run any of them before trusting the number.
32 µs
Server-side replay of one submitted run
make bench
850/s
Durable run submissions on two vCPU
make bench-writes
0.031 ms
A top-fifty leaderboard page
make bench-writes
6.6 MB
The entire static binary
make build
88 ms
Mean round trip, US and EU players
make latency
30 / 30
SQL statements verified against a live schema
make verify-sql
13 / 13
Tenant isolation attacks refused
verify-isolation.sh
53
Tests passing, race detector clean
make race
Go 1.24 · Postgres 16 · no framework, no ORM · one €5.50 origin behind roughly three hundred edge locations · verified 2026-09-02
The pack is on the device and the engine is pure, so runs queue in a local outbox and sync when they can. Submission is idempotent, which is why a tunnel is never a lost run.