"Day 04 — Forging the Codex: SQLite as the Memory Seal" date: 2026-01-20 series: "Gammoridin Dev Log" tags: [tauri, rust, react, typescript, sqlite, local-first, schema]
A Chronicle without memory is just smoke—so we sealed ours in SQLite.
What we set out to build
Problem: A launcher UI can look organized while the underlying truth rots: duplicate game entries, unstable identifiers, “phantom installs,” and metadata that can’t survive rescans. If the Sanctum forgets, the player pays the price.
Promise: Keep Gammoridin local-first and deterministic. The Codex must be a real source of truth: scans become upserts, launches become sessions, and enrichment becomes cached knowledge—without relying on cloud state or fragile frontend storage.
ARCH-NOTES
Today was about naming the memory vault clearly: what we store, why we store it, and how we keep it stable as the app evolves.
DB-SCHEMA
What shipped today
✅ Codified the “four-table core” of Gammoridin’s local database:games, game_igdb_metadata, play_sessions, settings.
This is the minimal spine that supports a launcher, a Codex, and the Chronicle—without bloat.
✅ Locked in what makes a game record “real” in the Codex:
Display + normalized naming, launcher identity (including Steam AppID when available), executable + install fields, and the user-facing state (backlog_status, cached art paths).
✅ Confirmed board-grade ordering support via sort_index to persist within-column ordering for the Backlog Board (and keep drag/drop from being a “temporary illusion”).
✅ Aligned the “data lives here” story end-to-end: SQLite sits behind the Rust ward, stored in the app data directory, and surfaced through Tauri commands—not directly mutated by the UI.
Behind the curtain
The choice — SQLite over “just state”
SQLite isn’t here because it’s trendy—it’s here because it’s boring in the best way.
Scanning needs idempotence. A scan should update what changed, not duplicate what exists. That means the backend needs a persistent catalog that can be upserted safely and queried quickly.
Play sessions are historical truth. The Chronicle needs start/end/duration records that don’t evaporate when the UI reloads or the user restarts.
Metadata is expensive and should be cached. IGDB enrichment is valuable, but it’s also network-bound and not guaranteed. Caching game_igdb_metadata keeps the Codex readable even when the outside world is quiet.
Local-first means ownership. The player’s library, statuses, and history live on their machine—full stop.
In short: the Sanctum must remember, even when the UI is asleep.
The cut — not over-normalizing (yet)
We could have broken everything into many tiny tables: genres, platforms, developers, publishers, tags, board ordering tables, and more.
We didn’t—on purpose.
The current schema stores some IGDB arrays as
