Here’s a concrete, **handoff-ready plan** you can give to another AI to implement a first version (v1) of a **Spelljammer Ship Tracker** with **multi-ship CRUD, constrained editing, SQLite persistence, and <1s live updates**. --- ## 0) Product goal (v1) A small phone-friendly web app where your group can: * Create/select/delete ships (delete requires confirm modal) * View & edit **core ship stats** + **current weapons on the ship** * See changes propagate to all connected clients within ~1s * Persist “real data” server-side in **SQLite** (ship data + weapons + optional reference content) * Show a **read-only Rules/Reference** screen for battle lookups No authentication. Anyone can edit anything. --- ## 1) Recommended stack (simple + robust) **Option A (recommended): Node.js + Fastify + Socket.IO + SQLite (better-sqlite3) + React (Vite)** * Fast to implement, great websocket support, easy Docker build. * Socket.IO simplifies reconnects & room-based updates (per ship). * better-sqlite3 is reliable and fast for low-concurrency apps. **Option B:** Node.js + Express + ws + SQLite (also fine, but more manual reconnection & rooms logic) Either way: **single Docker Compose** with one container; SQLite is a mounted file. --- ## 2) Architecture ### Backend * REST API for CRUD and initial state fetch. * WebSocket (Socket.IO) for real-time updates: * Clients join a “ship room” when viewing a ship. * When any field changes, server: 1. validates & persists to SQLite 2. broadcasts an update event to that room ### Frontend Phone-first layout, 3–4 screens: 1. **Ship List** (create/select/delete) 2. **Ship Dashboard** (core stats + weapons list) 3. **Edit Weapon** (or inline editing) 4. **Rules/Reference** (read-only) Use constrained controls: * numeric steppers/sliders for numbers * dropdowns for enums (size category, maneuverability class, etc.) * toggles for booleans * “Add weapon” form with select + numeric inputs --- ## 3) Data model (SQLite) Implement migrations on startup. ### Tables **ships** * `id` TEXT (uuid, PK) * `name` TEXT (unique-ish, not required but recommended) * Core stats (examples; adjust to your desired fields): * `hull_current` INTEGER NOT NULL * `hull_max` INTEGER NOT NULL * `armor_current` INTEGER NOT NULL * `armor_max` INTEGER NOT NULL * `ac` INTEGER NOT NULL * `con_save` INTEGER NULL (or `con_score`) * `speed` INTEGER NULL * `maneuver_class` TEXT NULL (enum: A/B/C/D/E/F/S per your rules) * `size_category` TEXT NULL * `notes` TEXT NULL * `updated_at` INTEGER (unix ms) **weapons** * `id` TEXT (uuid, PK) * `ship_id` TEXT (FK -> ships.id, indexed) * `name` TEXT NOT NULL * `type` TEXT NULL (optional enum: siege/arcane/etc.) * `attack_mod` INTEGER NULL * `damage` TEXT NULL (freeform like “3d10”) * `range` TEXT NULL * `ammo_current` INTEGER NULL * `ammo_max` INTEGER NULL * `status` TEXT NULL (enum: ok/damaged/disabled) * `notes` TEXT NULL * `sort_order` INTEGER NOT NULL default 0 * `updated_at` INTEGER **rules_pages** (optional; for read-only reference) * `id` TEXT PK (e.g., “battle”, “ship-stats”) * `title` TEXT * `content_markdown` TEXT * `updated_at` INTEGER > Keep rules content as markdown stored in DB **or** ship it as static markdown files in the frontend. For v1, static markdown is simplest. --- ## 4) API design (REST) ### Ships * `GET /api/ships` → list ships `{id, name, updated_at}` * `POST /api/ships` → create `{name, initialStats...}` → returns full ship * `GET /api/ships/:id` → full ship + weapons * `PATCH /api/ships/:id` → update core stats (validated + constrained) * `DELETE /api/ships/:id` → delete ship + weapons ### Weapons * `POST /api/ships/:id/weapons` → add weapon * `PATCH /api/weapons/:weaponId` → update weapon fields * `DELETE /api/weapons/:weaponId` → delete weapon Validation rules (server-enforced): * current values must be `0 <= current <= max` * max values must be `>= 0` * enums must be in allowed set * name length limits --- ## 5) WebSocket events (Socket.IO) ### Client → Server * `ship:join` `{shipId}` * `ship:leave` `{shipId}` * `ship:update` `{shipId, patch}` // core stats patch * `weapon:create` `{shipId, weapon}` * `weapon:update` `{weaponId, patch}` * `weapon:delete` `{weaponId}` ### Server → Client (broadcast to ship room) * `ship:state` `{ship, weapons}` // on join, or after major changes * `ship:patched` `{shipId, patch, updated_at}` * `weapon:created` `{shipId, weapon}` * `weapon:patched` `{shipId, weaponId, patch, updated_at}` * `weapon:deleted` `{shipId, weaponId}` Implementation approach: * On any mutation, server writes to DB then emits event. * On join, server emits current `ship:state`. * Clients apply patches locally; on reconnect, re-join and refresh state. Conflict model: * **Last write wins** is fine (your requirement). Keep it simple. --- ## 6) Frontend UI details (phone-first) ### Screen 1: Ship List * List cards: name + “last updated” * Buttons: * “Create ship” (modal with name + optional initial stats) * Tap card to open * Delete icon → confirm modal (“Delete ship X?”) ### Screen 2: Ship Dashboard Sections: 1. **Vitals** * Hull: current/max (stepper) * Armor: current/max * AC (stepper) 2. **Mobility** * Speed (stepper) * Maneuver class (dropdown) * Size category (dropdown) 3. **Weapons** * List weapons with quick fields (ammo, status) * Tap weapon to open “Weapon details” * “Add weapon” button 4. **Notes** * Multi-line text Include a top bar: * Ship name * “Rules” link/button * “Back to ships” ### Screen 3: Weapon Details (or modal) Constrained inputs for ammo/status/attack_mod. Freeform for damage/range/notes. ### Screen 4: Rules/Reference * Static markdown viewer with headings + quick links * Optional “search within rules” (client-side filter) --- ## 7) Persistence + backups * SQLite file at `/data/spelljammer.sqlite` * Docker volume mount that path. * Optional: periodic backup script/cron outside app (copy DB file nightly). --- ## 8) Docker Compose (single service) * Build a single image that serves both: * backend API + websockets * frontend static files * Expose one port (e.g., 3000) to Caddy reverse proxy. Example structure (for the implementing AI): * `/server` Fastify app * `/web` React app build output served by server (or Caddy, but keep simple) --- ## 9) Implementation steps (what the AI should do in order) 1. Create repo scaffold with `/server` and `/web` 2. Implement SQLite schema + migrations 3. Implement REST endpoints + validation 4. Add Socket.IO with rooms: * join/leave * mutation events that persist + broadcast 5. Build React UI: * routing for screens * state store (zustand or simple context) * socket connection + reconnection handling 6. Wire CRUD flows: * list → select → join room → render state * edit fields → emit update → optimistic UI 7. Add delete confirmation modal 8. Add rules markdown page (static) 9. Dockerize + compose + test behind Caddy --- ## 10) Acceptance criteria checklist * ✅ Create ship, appears in list, persists after restart * ✅ Select ship, see dashboard with core stats + weapons * ✅ Delete ship requires confirm, removes weapons too * ✅ All edits propagate to another browser within <1s * ✅ App is usable on phone (single column layout, large touch targets) * ✅ SQLite file persists via mounted volume * ✅ WebSocket reconnect works (refresh state on reconnect) * ✅ No auth, no user accounts --- ## 11) “Reference guide” integration (v1) Since you want read-only rules “for during battle”: Start with a **curated markdown** page that copies only the snippets you frequently need (e.g., maneuverability classes, hull/armor notes, weapon usage, combat steps). You can refine later. (If you want, I can extract a concise “Battle Reference” page from your PDF and format it as markdown for the AI to drop into `/web/src/rules/battle.md`.) --- ## 12) v1 Implementation Status **Status: v1 COMPLETE** (implemented 2026-02-19) All 14 commits have been implemented: 1. ✅ Project scaffold (Fastify + Vite + TypeScript) 2. ✅ SQLite connection + migration system 3. ✅ Ship REST API with Zod validation 4. ✅ Weapon REST API with validation 5. ✅ Socket.IO with rooms + real-time events 6. ✅ React routing + layout (mobile-first dark theme) 7. ✅ Zustand stores + Socket.IO client 8. ✅ Ship List page with create modal 9. ✅ Ship Dashboard (vitals + mobility) 10. ✅ Weapons section (add/edit/detail modals + notes) 11. ✅ Delete confirmation polish 12. ✅ Rules/Reference page (collapsible battle reference) 13. ✅ Dockerfile + docker-compose 14. ✅ README with testing + deployment docs See `README.md` for full setup, testing, and deployment instructions.