Architecture
Repository layout
Where each piece lives — the app, the API, and the data plane.
Three codebases carry the system, one per architectural role:
| Repo | Role | Stack |
|---|---|---|
repos/ollin-study | This app. The user-facing study product; also hosts these docs at /docs. | Next.js App Router, React, TypeScript, Tailwind v4, shadcn-style UI, Vitest. pnpm 10.28.1. |
repos/ollin-study-api | Serving API. Stateless read-only pack server. | Fastify + TypeScript (tsx), Vitest, Docker/Cloud Run. pnpm 10.28.1. |
solver-lab/ | Data plane + verification workspace. Extraction ETLs, backbone ops, gate runs, specs. | Python (ETLs), operating docs. |
ollin-study (this repo)
src/
app/
(product)/ # the product shell (topbar + main)
study/ # preflop tree → /study
study/library/ # family index → /study/library
study/[spotId]/ # family view + [boardId] strategy browser
methodology/ practice/ analyze/
docs/ # Fumadocs layout + catch-all page (this site)
api/search/ # docs search route (Orama)
components/
preflop/ study/ # screen components
shell/ # topbar, demo ribbon
docs/ # MDX registry, Mermaid
lib/
api/ # fetch layer, wire contracts (mirrored), view models, mock/
poker/ # boards, cards, 169 classes, combo query
content/docs/ # these pages (MDX)The wire contracts under src/lib/api/contract.ts and
src/lib/api/preflop-contract.ts are mirrors of the API's schema files —
see Data flow.
ollin-study-api
schema/ # THE frozen contracts: node-document.v1.ts, preflop.v1.ts
# + JSON Schema mirrors (*.schema.json)
src/
routes/v1.ts # families / boards / node-slot endpoints
routes/preflop.ts # preflop catalog / depth / node / boundaries
serving/ # catalog, grid169 aggregation, cache headers, card utils
store/ # local + GCS pack sources, sha256 LRU, v0 pack adapter
scripts/agpl-check.sh # the CI deny-gate
fixtures/ # fabricated packs (tests, offline dev)
fixtures-real/ # trimmed copies of real producer packssolver-lab (read-only from here)
data_plane/
extract_roots_v0.py # backbone roots → v0-roots serving packs
extract_preflop_v0.py # HRC exports → preflop-v0 serving packs
specs/extraction_spec_v1.md # Tier-A full-tree extraction (draft)
fleet/ # campaign ops, BOARDS_184_SPEC, cost notes
verification/ signoffs/ # gate runs over inherited artifacts
STATUS.md # live workspace statusThe data plane is upstream of everything: the app and API only ever consume
what its ETLs publish to gs://ollin-solver-data. Nothing in the
serving plane writes.