Inspiration

I wanted to build something for programmers, a game where the skill you're using is a real skill and not a simulated one. SQL felt like the right fit because querying a database already is detective work. You're filtering noise, cross-referencing sources, and looking for the thing that doesn't add up. I looked closely at Knight Lab's SQL Murder Mystery, Return of the Obra Dinn, and The Case of the Golden Idol while designing this. Each one does something brilliantly, whether that's open exploration, evidence-based deduction, or accessible progress feedback, and each one has a weakness I tried to avoid.

What it does

You're an investigator handed access to a small tech startup's internal systems after someone breaks into the server room overnight and wipes a drive. No forced entry, nothing physically stolen. An inside job. You investigate by writing real SQL against a real database: employee records, badge logs, VPN logs, company email, HR notes, financial transactions, and the meeting calendar. Nine tables, six suspects. The core rule is that the game never tells you what matters. Running a query doesn't award you anything. You have to read the results, recognise what's significant, and explicitly flag that row as evidence. Two players running identical queries can get different outcomes depending on whether they noticed what they were looking at. Accusations require proof, not hunches. The case has to actually hold together before it's accepted. And there's a second, hidden ending for players who don't stop at the obvious answer.

How I built it

Everything runs client-side. sql.js (SQLite compiled to WebAssembly) means every query genuinely executes against a real SQLite database in the browser. No backend, no server, no API calls. Open the link and it works. The interface is a Windows XP style desktop with a working window manager: draggable windows, minimise and restore, a taskbar. The framing is that you're investigating from the company's own laptop, so each mechanic gets a natural home. CMD is the query terminal, Schema holds the table reference and SQL cheat sheet, Clue Folder is your evidence, Notes is a freeform scratchpad, Case File is the briefing, and Accuse is where you make your call. I designed the schema and case data by hand first, deciding which mismatches across tables would constitute proof, before writing any interface code. The database includes filler employees and unremarkable records specifically so the real evidence has noise to hide in.

Challenges I ran into

Auto-detecting clues turned out to be a design failure. My first version scanned every query result and awarded any clue it found. Running SELECT * FROM emails instantly handed you the most incriminating message in the game, and the player did nothing to earn it. Replacing that with explicit evidence-flagging was the single biggest improvement to the game. The interface also kept leaking the answer. Accusing the wrong suspect returned their alibi, which was evidence you were supposed to discover yourself. Progress counters showed "0 of 6" for the culprit and "0 of 1" for irrelevant suspects, ranking them before you'd run a single query. Even the styling gave it away, since premature accusations against the real culprit rendered in a different colour. Each of these had to be flattened so the interface confirms nothing you haven't earned. There was also a near-invisible soft-lock. One evidence row carries two separate clues. The flag button hid itself if any matching clue was already collected, so flagging that row early made the second clue permanently unreachable, silently locking the secret ending with no error message. Making it playable without knowing SQL was the last big one. I'm not a strong SQL writer myself and struggled with my own game during testing. That led to the always-available schema, an in-game cheat sheet, and a deliberately trivial tutorial case that teaches every interaction before the real case begins.

What I learned

Query syntax is the tool. Interpretation is the gameplay. Almost every problem I hit came from confusing the two and rewarding retrieval instead of recognition. I also learned how much a detective game leaks through its UI rather than its content. The story was airtight long before the interface stopped giving away the answer. On the technical side, designing a database where the absence of a row is meaningful, where filler is load-bearing, and where evidence only becomes proof through a JOIN, is a genuinely different exercise from designing one for an application.

What's next

More cases using the same engine. The database and interface generalise, so a new case is new schema and new seed data rather than new code. I'd also like to add a proper hint system for players who get stuck on the SQL rather than on the mystery.

Share this project:

Updates

Submission history