docs: add comprehensive README with testing and deployment instructions
Includes development setup, Docker deployment, API reference, WebSocket events, troubleshooting guide, and curl-based test script. Updates App plan.md with implementation completion status. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
183
README.md
183
README.md
@@ -4,19 +4,190 @@ A phone-friendly web app for tracking Spelljammer ships during D&D sessions. Sup
|
||||
|
||||
See `App plan.md` for the full product spec.
|
||||
|
||||
## Quick Start (Development)
|
||||
## Tech Stack
|
||||
|
||||
- **Backend:** Node.js + Fastify + Socket.IO + better-sqlite3 + Zod
|
||||
- **Frontend:** React 19 + Vite + react-router-dom + zustand + socket.io-client
|
||||
- **Language:** TypeScript everywhere
|
||||
- **Database:** SQLite (file-based, zero config)
|
||||
- **Deployment:** Docker + Docker Compose
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Node.js** >= 18 (tested with v18.20.8)
|
||||
- **npm** >= 8
|
||||
- **Docker + Docker Compose** (for production deployment only)
|
||||
|
||||
## Development Setup
|
||||
|
||||
```bash
|
||||
npm run install:all
|
||||
npm run dev
|
||||
# Open http://localhost:5173
|
||||
# Install dependencies for both server and web
|
||||
cd server && npm install
|
||||
cd ../web && npm install
|
||||
cd ..
|
||||
|
||||
# Or use the convenience script:
|
||||
npm install # installs root deps (concurrently)
|
||||
npm run install:all # installs server + web deps
|
||||
```
|
||||
|
||||
## Quick Start (Docker)
|
||||
### Running in Development
|
||||
|
||||
**Option A: Two terminals**
|
||||
|
||||
```bash
|
||||
# Terminal 1 — Backend (port 3000)
|
||||
cd server && npm run dev
|
||||
|
||||
# Terminal 2 — Frontend (port 5173, proxies API to 3000)
|
||||
cd web && npm run dev
|
||||
```
|
||||
|
||||
**Option B: Single command**
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Then open **http://localhost:5173** in your browser.
|
||||
|
||||
The Vite dev server proxies `/api` and `/socket.io` requests to the Fastify server, so everything works from a single URL.
|
||||
|
||||
## Production Deployment (Docker)
|
||||
|
||||
```bash
|
||||
# Build and start
|
||||
docker compose up -d --build
|
||||
|
||||
# Open http://localhost:3000
|
||||
```
|
||||
|
||||
*Full setup, testing, and deployment docs will be added once implementation is complete.*
|
||||
The Docker image:
|
||||
- Multi-stage build (web build → server build → production)
|
||||
- Serves both API and frontend from a single container on port 3000
|
||||
- SQLite database stored in a Docker volume at `/data/spelljammer.sqlite`
|
||||
|
||||
### Stopping
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
### Database Backup
|
||||
|
||||
```bash
|
||||
# Copy the SQLite file out of the container
|
||||
docker cp spelljammer-ships:/data/spelljammer.sqlite ./backup-$(date +%F).sqlite
|
||||
```
|
||||
|
||||
### Reverse Proxy (Optional)
|
||||
|
||||
If you want HTTPS, put Caddy or nginx in front:
|
||||
|
||||
```
|
||||
# Example Caddyfile
|
||||
spelljammer.yourdomain.com {
|
||||
reverse_proxy localhost:3000
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### API Tests
|
||||
|
||||
Start the server, then run the test script:
|
||||
|
||||
```bash
|
||||
cd server && npm run dev
|
||||
# In another terminal:
|
||||
bash server/test-api.sh
|
||||
```
|
||||
|
||||
This runs through the full CRUD lifecycle: create ship → update stats → add weapons → fire (reduce ammo) → delete.
|
||||
|
||||
### Real-Time Sync Test
|
||||
|
||||
1. Open the app in two browser tabs
|
||||
2. Create a ship in one tab — it should appear in the other when you refresh the list
|
||||
3. Open the same ship in both tabs
|
||||
4. Change hull points in one — the other should update within ~1 second
|
||||
5. Add/edit/delete weapons — verify sync
|
||||
|
||||
### Mobile Test
|
||||
|
||||
- Use Chrome DevTools (F12 → device toggle) to simulate a phone
|
||||
- Or open the URL from your phone on the same network
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
├── server/ # Fastify backend
|
||||
│ ├── src/
|
||||
│ │ ├── index.ts # Entry point (Fastify + Socket.IO bootstrap)
|
||||
│ │ ├── config.ts # Environment config
|
||||
│ │ ├── db/ # SQLite connection + migrations
|
||||
│ │ ├── routes/ # REST API endpoints
|
||||
│ │ ├── services/ # Database query logic
|
||||
│ │ ├── socket/ # Socket.IO event handlers
|
||||
│ │ └── validation/ # Zod schemas
|
||||
│ └── test-api.sh # curl-based API test script
|
||||
├── web/ # React frontend
|
||||
│ ├── src/
|
||||
│ │ ├── App.tsx # Router setup
|
||||
│ │ ├── socket.ts # Socket.IO client
|
||||
│ │ ├── store/ # Zustand state stores
|
||||
│ │ ├── pages/ # Route pages
|
||||
│ │ ├── components/ # UI components
|
||||
│ │ ├── rules/ # Battle reference content
|
||||
│ │ └── types/ # TypeScript interfaces
|
||||
│ └── vite.config.ts # Dev proxy config
|
||||
├── Dockerfile # Multi-stage production build
|
||||
├── docker-compose.yml # Single-service compose
|
||||
└── App plan.md # Full product specification
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Ships
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| -------- | ----------------- | ------------------------ |
|
||||
| `GET` | `/api/ships` | List all ships |
|
||||
| `POST` | `/api/ships` | Create a new ship |
|
||||
| `GET` | `/api/ships/:id` | Get ship with weapons |
|
||||
| `PATCH` | `/api/ships/:id` | Update ship fields |
|
||||
| `DELETE` | `/api/ships/:id` | Delete ship + weapons |
|
||||
|
||||
### Weapons
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
| -------- | --------------------------- | ----------------- |
|
||||
| `POST` | `/api/ships/:id/weapons` | Add weapon to ship|
|
||||
| `PATCH` | `/api/weapons/:weaponId` | Update weapon |
|
||||
| `DELETE` | `/api/weapons/:weaponId` | Delete weapon |
|
||||
|
||||
### WebSocket Events
|
||||
|
||||
| Direction | Event | Purpose |
|
||||
| ---------------- | ----------------- | ---------------------------------- |
|
||||
| Client → Server | `ship:join` | Join a ship's room |
|
||||
| Client → Server | `ship:leave` | Leave a ship's room |
|
||||
| Client → Server | `ship:update` | Update ship stats |
|
||||
| Client → Server | `weapon:create` | Add a weapon |
|
||||
| Client → Server | `weapon:update` | Update a weapon |
|
||||
| Client → Server | `weapon:delete` | Delete a weapon |
|
||||
| Server → Client | `ship:state` | Full ship+weapons state (on join) |
|
||||
| Server → Client | `ship:patched` | Ship field(s) updated |
|
||||
| Server → Client | `weapon:created` | New weapon added |
|
||||
| Server → Client | `weapon:patched` | Weapon field(s) updated |
|
||||
| Server → Client | `weapon:deleted` | Weapon removed |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Server won't start:** Check that port 3000 is free (`lsof -i :3000` or `netstat -an | grep 3000`).
|
||||
|
||||
**WebSocket not connecting:** In development, make sure Vite proxy is configured (check `web/vite.config.ts`). The proxy forwards `/socket.io` to port 3000.
|
||||
|
||||
**Database locked:** If the server crashes without clean shutdown, the SQLite WAL/journal files may remain. Delete `data/spelljammer.sqlite-wal` and `data/spelljammer.sqlite-shm`, then restart.
|
||||
|
||||
**Docker build fails on better-sqlite3:** The `node:18-alpine` image includes prebuilt binaries. If issues persist, switch to `node:18-slim` in the Dockerfile.
|
||||
|
||||
Reference in New Issue
Block a user