164 lines
6.8 KiB
Markdown
164 lines
6.8 KiB
Markdown
# Shadowdark Character Sheet Manager — Design Spec
|
|
|
|
## Overview
|
|
|
|
A web app for managing Shadowdark RPG character sheets in real-time. Players in a campaign can view and edit characters simultaneously, with changes syncing live across all connected clients. Hosted locally and exposed via ngrok for group access.
|
|
|
|
## Tech Stack
|
|
|
|
- **Frontend:** React + Vite (TypeScript)
|
|
- **Backend:** Node.js + Express + Socket.IO
|
|
- **Database:** SQLite (single file, zero config)
|
|
- **Project location:** `/Users/aaron.wood/workspace/shadowdark/`
|
|
- **Structure:** `client/` and `server/` directories
|
|
|
|
## Data Model
|
|
|
|
### campaigns
|
|
|
|
| Column | Type | Notes |
|
|
| ---------- | ------- | -------------------------- |
|
|
| id | INTEGER | Primary key, autoincrement |
|
|
| name | TEXT | Campaign name |
|
|
| created_by | TEXT | For future auth |
|
|
| created_at | TEXT | ISO timestamp |
|
|
|
|
### characters
|
|
|
|
| Column | Type | Notes |
|
|
| ----------- | ------- | -------------------------------------------------- |
|
|
| id | INTEGER | Primary key, autoincrement |
|
|
| campaign_id | INTEGER | FK to campaigns |
|
|
| created_by | TEXT | For future auth |
|
|
| name | TEXT | Character name |
|
|
| class | TEXT | Fighter / Priest / Thief / Wizard |
|
|
| ancestry | TEXT | Human / Elf / Dwarf / Halfling / Goblin / Half-Orc |
|
|
| level | INTEGER | Default 1 |
|
|
| xp | INTEGER | Default 0 |
|
|
| hp_current | INTEGER | |
|
|
| hp_max | INTEGER | |
|
|
| ac | INTEGER | |
|
|
| alignment | TEXT | Lawful / Neutral / Chaotic |
|
|
| title | TEXT | Optional, e.g. "the Brave" |
|
|
| notes | TEXT | Freeform notes |
|
|
|
|
### character_stats
|
|
|
|
| Column | Type | Notes |
|
|
| ------------ | ------- | --------------------------------- |
|
|
| character_id | INTEGER | FK to characters |
|
|
| stat_name | TEXT | STR / DEX / CON / INT / WIS / CHA |
|
|
| value | INTEGER | Raw score (3-18 typically) |
|
|
|
|
One row per stat per character. Ability modifiers are derived, not stored:
|
|
|
|
| Score | Modifier |
|
|
| ----- | -------- |
|
|
| 1-3 | -4 |
|
|
| 4-5 | -3 |
|
|
| 6-7 | -2 |
|
|
| 8-9 | -1 |
|
|
| 10-11 | +0 |
|
|
| 12-13 | +1 |
|
|
| 14-15 | +2 |
|
|
| 16-17 | +3 |
|
|
| 18 | +4 |
|
|
|
|
### character_gear
|
|
|
|
| Column | Type | Notes |
|
|
| ------------ | ------- | ----------------------------------------------------- |
|
|
| id | INTEGER | Primary key, autoincrement |
|
|
| character_id | INTEGER | FK to characters |
|
|
| name | TEXT | Item name |
|
|
| type | TEXT | weapon / armor / gear / spell |
|
|
| slot_count | INTEGER | Gear slots used (Shadowdark inventory system) |
|
|
| properties | TEXT | JSON — e.g. `{"damage":"1d6","melee":true,"bonus":1}` |
|
|
|
|
Spells are stored as gear entries with `type: "spell"` and a `tier` property in the JSON.
|
|
|
|
### character_talents
|
|
|
|
| Column | Type | Notes |
|
|
| ------------ | ------- | ----------------------------------------- |
|
|
| id | INTEGER | Primary key, autoincrement |
|
|
| character_id | INTEGER | FK to characters |
|
|
| name | TEXT | Talent name |
|
|
| description | TEXT | Flavor/rules text |
|
|
| effect | TEXT | JSON — mechanical bonuses for dice roller |
|
|
|
|
## UI Layout
|
|
|
|
### Campaign List (home page)
|
|
|
|
- Grid/list of existing campaigns
|
|
- "+ New Campaign" button
|
|
- Click a campaign to enter it
|
|
|
|
### Campaign View (main screen)
|
|
|
|
- Campaign name header
|
|
- Responsive character card grid:
|
|
- Desktop: 4 cards across
|
|
- Tablet: 2 cards across
|
|
- Mobile: 1 card, stacked
|
|
- Cards flow naturally — 6 characters = 4 + 2 rows on desktop, just scroll
|
|
- "+ Add Character" button
|
|
- Future: dice log panel (right side on desktop, bottom drawer on mobile)
|
|
|
|
### Character Card (in the grid)
|
|
|
|
- Name, class, ancestry, level header
|
|
- HP bar with +/- buttons (current / max)
|
|
- AC display
|
|
- Six stats in compact 3x2 layout: score, modifier, +/- buttons
|
|
- Gear summary (slots used / total)
|
|
- Click to expand into full detail view
|
|
|
|
### Character Detail (expanded / modal)
|
|
|
|
- Full stat editing with +/- buttons
|
|
- Gear/inventory management: add/remove items with type and properties
|
|
- Talents list: add/remove with name, description, effect
|
|
- Spell list (for Priests/Wizards — gear items with type "spell")
|
|
- Notes freeform text field
|
|
- Future: dice roll buttons next to weapons/spells
|
|
|
|
## Real-time Sync
|
|
|
|
- Client joins a Socket.IO room per campaign (room ID = campaign ID)
|
|
- Mutation flow: client -> server API -> save to SQLite -> broadcast to room
|
|
- Other clients receive update and patch local state (no full reload)
|
|
- Optimistic UI: editing client updates immediately, server confirms
|
|
- On reconnect, client fetches latest full state from server
|
|
|
|
## Auth (v1: none, future-ready)
|
|
|
|
- v1 is open free-for-all: anyone with the link can create/edit anything
|
|
- `created_by` fields exist in the schema for future use
|
|
- Migration path to light auth (name/pin per character) or GM controls requires adding middleware, not restructuring
|
|
|
|
## Future: Dice Rolling (not in v1)
|
|
|
|
Design accommodations for future dice rolling:
|
|
|
|
- **Shared dice log panel** — layout reserves space for it
|
|
- **Inline roll buttons** — next to weapons/spells and stats
|
|
- **Server-side rolls** — server calculates d20 + ability modifier + gear/talent bonuses, broadcasts result
|
|
- **Log entries** — show who rolled, what for, full breakdown (e.g. "Kira attacks with Longsword +1: d20(14) + STR(+2) + weapon(+1) = 17"), and timestamp
|
|
- **Data model supports it** — `character_gear.properties` and `character_talents.effect` JSON fields carry the mechanical data the roller needs
|
|
|
|
## Deployment
|
|
|
|
- Run `server/` on localhost with a configured port
|
|
- `client/` built and served by Express (or Vite dev server during development)
|
|
- Expose via ngrok for friends to access
|
|
- SQLite file lives in `server/data/shadowdark.db`
|
|
|
|
## Out of Scope for v1
|
|
|
|
- Authentication / permissions
|
|
- Dice rolling
|
|
- Character import/export
|
|
- Multiple themes / dark mode
|
|
- Mobile native app
|