2.9 KiB
AGENTS.md — Game Grid
Stack
- SvelteKit 2 with Svelte 5 (runes mode:
$state,$derived,$props) - TypeScript (strict), Tailwind CSS 3
- SQLite via
better-sqlite3(native module — needs Python/make/g++) - bcrypt (also native), archiver for on-the-fly .app zipping
- Docker for deployment with multi-stage build and bind-mounted game volumes
Commands
npm run dev # dev server (vite dev)
npm run build # production build (vite build)
npm run check # typecheck: runs svelte-kit sync then svelte-check
npm run preview # preview production build
No test, lint, or format scripts exist. No CI.
Architecture
Two-tier library: GAMES_PATH/public/ (no auth) and GAMES_PATH/private/ (login required).
Scanner runs on every layout load (src/routes/+layout.server.ts:6). On first request the scanner walks the file tree, detecting games, series, platforms, cover art, and screenshots — populating the SQLite DB. Database is auto-created and auto-migrated on first access (src/lib/server/db.ts).
Auth: single shared password (APP_PASSWORD env var), bcrypt-hashed at first use, session cookie is HMAC-signed with SESSION_SECRET.
CSRF checkOrigin is disabled globally in svelte.config.js — intentional for local network access.
Native modules (better-sqlite3, bcrypt) require Python 3, make, and g++ for npm install. Docker build stage installs these explicitly.
Important files
| File | Purpose |
|---|---|
src/lib/server/db.ts |
DB singleton, schema + migration |
src/lib/server/scanner.ts |
Filesystem scanner, game/series detection |
src/lib/server/auth.ts |
Session signing, password verification |
src/lib/platform.ts |
Platform detection from file extensions |
src/routes/+layout.server.ts |
Runs scanner & auth check on every request |
src/routes/games/[slug]/+page.server.ts |
Game detail, meta editing, tag actions |
src/routes/api/download/[fileId]/+server.ts |
File download, on-the-fly .app zipping |
svelte.config.js |
adapter-node, CSRF disabled |
docker-compose.yml |
Volume mounts, env vars, port mapping |
Gotchas
- Scanner is slow on first load — it walks every file in both libraries. Plan for this: refreshing while a scan is running will queue another scan.
- No hot reload for
$env/dynamic/private— env var changes require a dev server restart. .svelte-kit/tsconfig.jsonis generated bysvelte-kit syncand needed for TypeScript to resolve$libetc. Thecheckcommand runs sync first, but in an IDE you may need to runnpm run devonce to generate it.- Game files are served directly off disk — paths come from the DB and map to real filesystem paths under
GAMES_PATH. If bind mounts change, re-scan (hit the app orPOST /api/scan) to update the DB. .appbundles (macOS) are zipped on-the-fly for download — this is CPU-intensive for large bundles.