Skip to content

pleiad/gql-detective

Repository files navigation

GQL Detective

A noir detective game that teaches the ISO-GQL graph query language. You are the detective: read the evidence, build the case graph by pinning suspects and drawing red-string cords between them (each cord is a graph INSERT), then write GQL at the records terminal to interrogate what you built and name the culprit.

Powered by frogql-wasm — an in-browser, in-RAM ISO-GQL engine (Rust → WebAssembly).

The loop

Each case runs model → query → accuse:

  1. Model. Click highlighted names/places inside the evidence to pin them as nodes (INSERT (m:Person {...})). Drag a cord from one card to another to add an edge (INSERT (m)-[:KNOWS]->(v)). Every action shows the GQL it ran.
  2. Query. Write MATCH / WHERE / RETURN against the graph you assembled to close each lead.
  3. Accuse. Pick the culprit from the lineup.

Cases are progressive: The Vanishing Violinist (nodes, MATCH/WHERE/AND) → The Broken Alibi (edges, directed traversal, comma multi-patterns, EXISTS/NOT EXISTS).

Run it

npm install
npm run dev        # http://localhost:5173
npm run build      # production build (bundles the ~300 kB gzip wasm, no plugin)
npm run preview

Stack

  • React + Vite + TypeScript, Tailwind as a layout utility under a hand-built noir theme (CSS vars, grain/scanline/vignette).
  • CodeMirror 6 terminal with a custom GQL highlighter.
  • framer-motion scene transitions; Web Audio synth SFX (no asset files).
  • zustand + localStorage for progress; react-i18next + inline {en,es} case content (fully bilingual EN/ES).

Architecture

src/
  engine/    frogql.ts — the ONLY module touching frogql-wasm (init + GqlConnection)
  graph/     builder.ts — the assembled graph + INSERT codegen, re-opened per change
  content/   types.ts (Case schema) + cases/<id>/index.ts  ← add a case = add a folder
  verify/    order-insensitive model + query + accusation checks
  game/      scenes/ (boot · office · desk · accusation · caseClosed) + zustand store
  components/desk/ (Evidence · Pinboard · Terminal · Printout · Leads · InsertLog · …)

Adding a case

Create src/content/cases/<id>/index.ts exporting a Case, then register it in src/content/registry.ts. No engine or UI code changes. A case bundles bilingual story, evidence cards (clickable entities + cord edges), ordered leads with declarative verification, and the suspect lineup.

Engine notes

frogql-wasm supports MATCH, label logic (& | !), directed/reverse/undirected edges, comma multi-patterns, WHERE (= != < <= > >=, AND/OR/NOT, IS NULL, IS INT), RETURN ... AS, DISTINCT, EXISTS {}/NOT EXISTS {}, OPTIONAL MATCH, variable-length paths, and DML (INSERT/SET/REMOVE/DELETE).

It does not support ORDER BY, GROUP BY, LIMIT, UNION, or aggregation — and silently ignores them rather than erroring. All puzzle verification is therefore order-insensitive, and the terminal warns when a query uses an unsupported clause.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages