id: cbe709faa5a34fa3a8fc913794bdf36a
parent_id: cd48a4b0ae154eef886e4219e403a0a5
item_type: 1
item_id: 980c3eb587294e4383474b94988f2f88
item_updated_time: 1785664023744
title_diff: "[]"
body_diff: "[{\"diffs\":[[0,\"ess.\"],[-1,\" The schema and crate deps are ready; just swap the in-memory adapter for the Redis one when the time comes.\"],[0,\"\\\n\\\n**\"]],\"start1\":2005,\"start2\":2005,\"length1\":116,\"length2\":8},{\"diffs\":[[0,\".\\\n\\\n---\\\n\\\n\"],[1,\"## Art Direction (decided 2026-08-02)\\\n\\\n**Torn-style graphical browser UI.** The game mechanics are text/numbers; the presentation is a fully graphical web application.\\\n\\\n### UI characteristics\\\n- **Location panels**: illustrated backgrounds per district (tavern, market, dungeon entrance, etc.)\\\n- **Item/equipment icons**: sprite-style icons with quality-tier border glow (Common→Legendary)\\\n- **Stat bars & HUD**: graphical HP/energy/PP bars, XP progress bars, skill meters\\\n- **Themed color scheme**: dark fantasy palette, per-district tinting\\\n- **Tab-based navigation**: Torn-style tab bar for core pages (City, Adventures, Combat, Inventory, Guild, etc.)\\\n- **CSS animations**: transitions for page changes, stat updates, combat results\\\n\\\n### Rendering approach\\\n- All rendering via **HTML/CSS/SVG within Vue 3 SPA** — no canvas, no WebGL.\\\n- Keeps it lightweight, accessible, and PWA-compatible.\\\n- Vue component library with dark-fantasy theming.\\\n\\\n### Art pipeline\\\n- **Location art**: digital illustrations — ~11 district panels + dungeon room tiles\\\n- **Item icons**: sprite sheet or SVG icon set\\\n- **UI chrome**: Vue component library (stat bars, progress rings, modals, tooltips, tab bar)\\\n\\\n---\\\n\\\n\"],[0,\"## Multi\"]],\"start1\":2262,\"start2\":2262,\"length1\":16,\"length2\":1210},{\"diffs\":[[0,\"\\\n\\\n```\\\n~/\"],[-1,\"d\"],[1,\"D\"],[0,\"ev\"],[1,\"elopment\"],[0,\"/skara-b\"]],\"start1\":4345,\"start2\":4345,\"length1\":19,\"length2\":27},{\"diffs\":[[0,\"ra-brae/\"],[-1,\"      \"],[0,\"        \"]],\"start1\":4368,\"start2\":4368,\"length1\":22,\"length2\":16},{\"diffs\":[[0,\"tion `~/\"],[-1,\"d\"],[1,\"D\"],[0,\"ev\"],[1,\"elopment\"],[0,\"/<projec\"]],\"start1\":4689,\"start2\":4689,\"length1\":19,\"length2\":27},{\"diffs\":[[0,\"into `~/\"],[-1,\"d\"],[1,\"D\"],[0,\"ev\"],[1,\"elopment\"],[0,\"/skara-b\"]],\"start1\":4886,\"start2\":4886,\"length1\":19,\"length2\":27},{\"diffs\":[[0,\"l`).\"],[-1,\" So `api-types/` becomes a *generated* artifact, not hand-written in two languages.\"],[0,\"\\\n- *\"]],\"start1\":7124,\"start2\":7124,\"length1\":91,\"length2\":8},{\"diffs\":[[0,\"n/`.\"],[-1,\" Commit generated output (or generate in CI).\"],[0,\"\\\n\\\n**\"]],\"start1\":7307,\"start2\":7307,\"length1\":53,\"length2\":8},{\"diffs\":[[0,\"s/`.\"],[-1,\" Only truly cross-language artifacts go in the third repo.\"],[0,\"\\\n2. \"]],\"start1\":7586,\"start2\":7586,\"length1\":66,\"length2\":8},{\"diffs\":[[0,\"oth \"],[-1,\"(`server/common/`, `client/common/`) so `git clone --recurse-submodules` yields a complete tree. Cleaner CI, more day-to-day friction (detached HEAD, two-step updates). For solo work, s\"],[1,\"repos. S\"],[0,\"tart\"]],\"start1\":7688,\"start2\":7688,\"length1\":193,\"length2\":16},{\"diffs\":[[0,\"rt with \"],[-1,\"the **\"],[0,\"sibling \"]],\"start1\":7702,\"start2\":7702,\"length1\":22,\"length2\":16},{\"diffs\":[[0,\"path\"],[-1,\"** layout above\"],[0,\"; sw\"]],\"start1\":7720,\"start2\":7720,\"length1\":23,\"length2\":8},{\"diffs\":[[0,\"t.\\\n\\\n\"],[-1,\"**Synergy:** Because all content lives as structured data, we can **auto-generate a community game wiki** from `skara-brae-common` (Idle Fantasy does exactly this) — client tooltips and docs from one source.\\\n\\\n\"],[0,\"---\\\n\"]],\"start1\":7779,\"start2\":7779,\"length1\":217,\"length2\":8},{\"diffs\":[[0,\"t\\\" }\"],[-1,\"   # cross-language game data + types\"],[0,\"\\\nuto\"]],\"start1\":14250,\"start2\":14250,\"length1\":45,\"length2\":8},{\"diffs\":[[0,\"\\\"] }\"],[-1,\" # OpenAPI for client codegen\"],[0,\"\\\ntra\"]],\"start1\":14305,\"start2\":14305,\"length1\":37,\"length2\":8},{\"diffs\":[[0,\"00,\\\n    \"],[-1,\"mana\"],[1,\"pp  \"],[0,\"        \"]],\"start1\":16156,\"start2\":16156,\"length1\":20,\"length2\":20},{\"diffs\":[[0,\"    max_\"],[-1,\"mana\"],[1,\"pp  \"],[0,\"    BIGI\"]],\"start1\":16204,\"start2\":16204,\"length1\":20,\"length2\":20},{\"diffs\":[[0,\"50,\\\n\"],[-1,\"    -- Base stats (BIGINT — exponential growth, display tiered)\\\n\"],[0,\"    \"]],\"start1\":16244,\"start2\":16244,\"length1\":72,\"length2\":8},{\"diffs\":[[0,\"10,\\\n\"],[-1,\"    -- Location\\\n\"],[0,\"    \"]],\"start1\":16510,\"start2\":16510,\"length1\":24,\"length2\":8},{\"diffs\":[[0,\"on',\"],[-1,\"  -- common, fine, superior, exceptional, masterwork, legendary\"],[0,\"\\\n   \"]],\"start1\":17216,\"start2\":17216,\"length1\":71,\"length2\":8},{\"diffs\":[[0,\"NULL\"],[-1,\"  -- collar, armor, trinket\"],[0,\"\\\n);\\\n\"]],\"start1\":20537,\"start2\":20537,\"length1\":35,\"length2\":8},{\"diffs\":[[0,\"ULL,\"],[-1,\"  -- mercenary, apprentice, gatherer\"],[0,\"\\\n   \"]],\"start1\":21686,\"start2\":21686,\"length1\":44,\"length2\":8},{\"diffs\":[[0,\"ULL,\"],[-1,\"  -- adventure, skill_training, gathering\"],[0,\"\\\n   \"]],\"start1\":22510,\"start2\":22510,\"length1\":49,\"length2\":8},{\"diffs\":[[0,\"AL '\"],[-1,\"1\"],[1,\"4\"],[0,\" hour\"],[1,\"s\"],[0,\"',\\\n \"]],\"start1\":22605,\"start2\":22605,\"length1\":14,\"length2\":15},{\"diffs\":[[0,\"rces\"],[-1,\" — single server can serve thousands of concurrent WebSocket connections.\\\n\\\n2. **Type safety**: Game rules are complex (combat formulas, skill interactions, economy, crit tables). Rust's type system catches bugs\"],[1,\".\\\n2. **Type safety**: Complex game rules caught\"],[0,\" at \"]],\"start1\":22805,\"start2\":22805,\"length1\":218,\"length2\":55},{\"diffs\":[[0,\"le time.\"],[-1,\" The\"],[0,\" `sb-cor\"]],\"start1\":22865,\"start2\":22865,\"length1\":20,\"length2\":16},{\"diffs\":[[0,\"sb-core`\"],[-1,\" crate\"],[0,\" becomes\"]],\"start1\":22875,\"start2\":22875,\"length1\":22,\"length2\":16},{\"diffs\":[[0,\"engine.\\\n\"],[-1,\"\\\n\"],[0,\"3. **Fea\"]],\"start1\":22908,\"start2\":22908,\"length1\":17,\"length2\":16},{\"diffs\":[[0,\"y**:\"],[-1,\" Game tick engine processes timers for thousands of players simultaneously. Offline reward calculation runs alongside active gameplay.\"],[0,\" Tokio +\"],[-1,\" Rust's\"],[0,\" own\"]],\"start1\":22940,\"start2\":22940,\"length1\":157,\"length2\":16},{\"diffs\":[[0,\"makes th\"],[-1,\"is\"],[1,\"e tick engine\"],[0,\" correct\"]],\"start1\":22969,\"start2\":22969,\"length1\":18,\"length2\":29},{\"diffs\":[[0,\"uction.\\\n\"],[-1,\"\\\n\"],[0,\"4. **No \"]],\"start1\":23008,\"start2\":23008,\"length1\":17,\"length2\":16},{\"diffs\":[[0,\"**: \"],[-1,\"Critical for real-time combat. Rust provides deterministic performance.\\\n\\\n5. **Workspace architecture**: Clean separation between game logic (`sb-core`), persistence (`sb-db`), API (`sb-api`), and auth (`sb-auth`). Each crate compiles independently — fast iter\"],[1,\"Deterministic performance for real-time combat.\\\n5. **Workspace architecture**: Clean crate separation — fast independent compil\"],[0,\"ation.\\\n\"],[-1,\"\\\n\"],[0,\"6. *\"]],\"start1\":23033,\"start2\":23033,\"length1\":275,\"length2\":142},{\"diffs\":[[0,\"rde \"],[-1,\"are all\"],[1,\"—\"],[0,\" mat\"]],\"start1\":23210,\"start2\":23210,\"length1\":15,\"length2\":9},{\"diffs\":[[0,\"ade \"],[-1,\"crates \"],[0,\"in 2\"]],\"start1\":23237,\"start2\":23237,\"length1\":15,\"length2\":8},{\"diffs\":[[0,\"n 2026.\\\n\"],[-1,\"\\\n\"],[0,\"7. **Sin\"]],\"start1\":23242,\"start2\":23242,\"length1\":17,\"length2\":16},{\"diffs\":[[0,\"pile\"],[-1,\" for Linux x86_64 on workhorse, deploy the binary to staging/prod. No runtime dependencies, no Docker. Systemd manages the process lifecycle\"],[1,\", deploy, run. No Docker, no runtime deps\"],[0,\".\\\n\\\n-\"]],\"start1\":23288,\"start2\":23288,\"length1\":148,\"length2\":49},{\"diffs\":[[0,\"aps \"],[-1,\"well \"],[0,\"to g\"]],\"start1\":23398,\"start2\":23398,\"length1\":13,\"length2\":8},{\"diffs\":[[0,\"ally\"],[-1,\" (character store, market store, combat store)\"],[0,\"\\\n- *\"]],\"start1\":23514,\"start2\":23514,\"length1\":54,\"length2\":8},{\"diffs\":[[0,\"s** \"],[-1,\"keep\"],[1,\"co-locate\"],[0,\" tem\"]],\"start1\":23544,\"start2\":23544,\"length1\":12,\"length2\":17},{\"diffs\":[[0,\"yles\"],[-1,\" co-located — good for complex game UIs\"],[0,\"\\\n- U\"]],\"start1\":23579,\"start2\":23579,\"length1\":47,\"length2\":8},{\"diffs\":[[0,\"ugin\"],[-1,\" for mobile-like experience without a\"],[1,\"\\\n- **SPA only** — no Nuxt/SSR. Game is behind auth; public pages generated\"],[0,\" sep\"]],\"start1\":23640,\"start2\":23640,\"length1\":45,\"length2\":82},{\"diffs\":[[0,\"separate\"],[-1,\" app\"],[1,\"ly.\"],[0,\"\\\n\\\n---\\\n\\\n#\"]],\"start1\":23719,\"start2\":23719,\"length1\":20,\"length2\":19},{\"diffs\":[[0,\", repo structure\"],[1,\", decisions log\"]],\"start1\":24476,\"start2\":24476,\"length1\":16,\"length2\":31}]"
metadata_diff: {"new":{},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-08-02T09:49:55.816Z
created_time: 2026-08-02T09:49:55.816Z
is_locked: 0
type_: 13