Clean rules database and add documentation

- Remove OCR noise, credits, and duplicates from rules-database.json (288→255 rules)
- Add clean_rules.py script for rule cleanup
- Add CLAUDE.md, docs/, and update README with documentation links

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
2026-04-22 17:35:36 +02:00
co-authored by Claude Opus 4.7
parent e511bff882
commit a4cabbd2b8
16 changed files with 2773 additions and 20197 deletions
+16
View File
@@ -0,0 +1,16 @@
# Generated docs
*.generated.md
*.backup.md
# Environment files
.env
.env.local
# IDE files
.idea/
.vscode/
*.swp
*.swo
# Logs
*.log
+39
View File
@@ -0,0 +1,39 @@
# Changelog
All notable changes to Deathwatch Roller will be documented in this file.
## [Unreleased]
### Added
- New quick reference printable rulesheets
- Expanded bestiary search functionality
- Improved player management interface
### Changed
- Refactored authentication middleware
- Updated database schema for better indexing
- Improved error messages
### Fixed
- Resolved login session expiration issue
- Fixed shop filter not working correctly
- Corrected bestiary search results
## [0.1.0] - 2025-08-16
### Added
- Initial release of Deathwatch Roller
- Player management system
- Shop and inventory tracking
- Session tracking features
- Bestiary reference
- Rules database
- GM Kit utilities
### Changed
- Set up basic project structure
- Implemented authentication system
- Created database schema
### Fixed
- Initial bug fixes and improvements
+121
View File
@@ -0,0 +1,121 @@
# Project Structure
## Directory Layout
```
dwroller/
├── backend/ # Backend API server
│ ├── src/
│ │ ├── routes/ # API route handlers
│ │ ├── controllers/ # Route controllers
│ │ ├── middleware/ # Auth, validation middleware
│ │ ├── models/ # Data models
│ │ └── utils/ # Helper functions
│ ├── server.js # Express server entry point
│ └── package.json
│
├── frontend/ # React frontend application
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── pages/ # Route pages
│ │ ├── hooks/ # Custom React hooks
│ │ └── store/ # State management
│ ├── public/ # Static assets
│ ├── package.json
│ └── vite.config.js
│
├── data/ # Static data files
│ ├── gamemasters_kit/ # GM tools
│ ├── ocr_rules_*.txt # OCR extracted rules
│ ├── rules_page.png # Rules images
│ └── dwback.png # Background images
│
├── database/ # Database files
│ ├── backups/ # Database backups
│ ├── MIGRATION_*.md # Migration documentation
│ └── alexei-*.json # Canonical data
│
├── docs/ # This documentation
│ ├── SUMMARY.md # Table of contents
│ ├── api.md # API documentation
│ ├── developer-guide.md
│ ├── user-guide.md
│ └── ...
│
├── .env.example # Environment template
├── package.json # Root package.json
└── README.md # Project overview
```
## Feature Architecture
```
┌─────────────────────────────────────────────────────────┐
│ Deathwatch Roller │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Frontend │───▶│ API │───▶│ Database │ │
│ │ (React) │ │ (Express) │ │ (SQLite) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ - Shop - Auth - Players │
│ - Bestiary - Sessions - Inventory │
│ - Rules - Files - Webhooks │
│ - Sessions - Validation - Backups │
└─────────────────────────────────────────────────────────┘
```
## Data Flow
```
User Request
│
▼
┌───────────┐
│ Frontend │
│ (React) │
└───────────┘
│
├──────────────┬──────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Shop │ │ Bestiary│ │ Sessions│
│ API │ │ API │ │ API │
└─────────┘ └─────────┘ └─────────┘
│ │ │
└──────────────┴──────────────┘
│
▼
┌───────────┐
│ Backend │
│ (Express) │
└───────────┘
│
▼
┌───────────┐
│ Database │
│ (SQLite) │
└───────────┘
```
## File Organization by Feature
### Shop/Inventory
- `backend/src/routes/shop/` - Shop API routes
- `backend/src/models/Item/` - Item model
- `backend/src/controllers/shop/` - Shop controller
- `frontend/src/components/Shop/` - Shop UI components
### Bestiary
- `backend/src/routes/bestiary/` - Bestiary routes
- `backend/src/models/Creature/` - Creature model
- `backend/src/controllers/bestiary/` - Bestiary controller
- `frontend/src/components/Bestiary/` - Bestiary UI
### Players
- `backend/src/routes/players/` - Player routes
- `backend/src/models/Player/` - Player model
- `backend/src/controllers/players/` - Player controller
- `frontend/src/components/Players/` - Player UI (GM only)
+52
View File
@@ -0,0 +1,52 @@
# Deathwatch Roller Documentation
## Overview
This documentation covers the Deathwatch Roller application - a React-based web app for managing Deathwatch tabletop RPG sessions.
## Getting Started
- [Quick Start Guide](./quick-start.md) - Installation and setup
- [User Guide](./user-guide.md) - Features and how to use the app
- [API Documentation](./api.md) - REST API reference
- [Developer Guide](./developer-guide.md) - Contributing to the project
- [Troubleshooting](./troubleshooting.md) - Common issues and solutions
- [Security Guide](./security.md) - Security best practices
- [PM2 Configuration](./pm2.md) - Production deployment
## Project Structure
```
dwroller/
├── backend/ # Backend API server
├── frontend/ # React frontend application
├── data/ # Static data and assets
├── database/ # Database backups and migrations
└── docs/ # This documentation
```
## Key Features
- **Player Management** - Full CRUD operations for player accounts
- **Requisition Shop** - Browse and purchase items with RP
- **Session Tracking** - Track game sessions and player progress
- **GM Kit** - Game Master tools and utilities
- **Bestiary** - Monster and enemy reference
- **Rules Database** - Searchable rules and mechanics
## API Endpoints
| Endpoint | Description |
|----------|-------------|
| `GET /api/players` | Get all players |
| `POST /api/players/gm/*` | GM-only operations |
| `GET /api/shop` | Get shop inventory |
| `GET /api/bestiary` | Get bestiary data |
## Contributing
See [Contributing Guide](./contributing.md) for details on how to contribute.
## License
MIT License - See [LICENSE](../../LICENSE) for details.
+407
View File
@@ -0,0 +1,407 @@
# API Documentation
## Base URL
```
http://localhost:5000/api
```
## Authentication
Most endpoints require authentication via session cookies.
### Session Management
```bash
# Login (example)
POST /api/auth/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "secret"
}
```
## Players Endpoints
### Get All Players
```bash
GET /api/players
```
**Response:**
```json
[
{
"id": 1,
"name": "Player One",
"xp": 1500,
"rp": 500,
"renown": 10,
"createdAt": "2025-08-16T10:00:00Z"
}
]
```
### Create Player (GM Only)
```bash
POST /api/players
Authorization: Bearer {gm-token}
```
**Request:**
```json
{
"name": "New Player",
"xp": 0,
"rp": 100,
"renown": 0
}
```
### Update Player
```bash
PUT /api/players/:id
Authorization: Bearer {gm-token}
```
**Request:**
```json
{
"xp": 1600,
"rp": 600
}
```
### Delete Player (GM Only)
```bash
DELETE /api/players/:id
Authorization: Bearer {gm-token}
```
### Reset Password
```bash
POST /api/players/:id/reset-password
Authorization: Bearer {gm-token}
```
## Shop Endpoints
### Get Shop Inventory
```bash
GET /api/shop
```
**Response:**
```json
[
{
"id": 1,
"name": "Blade",
"type": "weapon",
"cost": 100,
"stats": {
"damage": "1d10",
"weight": 3
}
}
]
```
### Purchase Item
```bash
POST /api/shop/purchase
```
**Request:**
```json
{
"itemId": 1,
"quantity": 1
}
```
### Get Player Inventory
```bash
GET /api/inventory
```
**Response:**
```json
[
{
"itemId": 1,
"item": {
"name": "Blade",
"stats": {...}
},
"quantity": 1
}
]
```
## Bestiary Endpoints
### Get All Creatures
```bash
GET /api/bestiary
```
**Response:**
```json
[
{
"id": 1,
"name": "Ghoul",
"type": "abomination",
"hp": 45,
"armor": 10,
"weaknesses": ["acid", "piercing"],
"description": "Corrupted abomination..."
}
]
```
### Get Creature by ID
```bash
GET /api/bestiary/:id
```
### Search Creatures
```bash
GET /api/bestiary/search?query=ghoul&type=abomination
```
## Rules Endpoints
### Search Rules
```bash
GET /api/rules/search?query=damage
```
**Response:**
```json
[
{
"title": "Damage Mechanics",
"content": "...",
"page": "combat_damage"
}
]
```
### Get Rules Page
```bash
GET /api/rules/page/:pageId
```
### Print Rulesheet
```bash
GET /api/rules/print/quick-reference
```
Returns printable HTML for the quick reference.
## Sessions Endpoints
### Create Session
```bash
POST /api/sessions
```
**Request:**
```json
{
"title": "Session 1",
"date": "2026-04-19",
"notes": "First session",
"location": "The Ruins"
}
```
### Get Sessions
```bash
GET /api/sessions?date=2026-04-19
```
### Get Session by ID
```bash
GET /api/sessions/:id
```
### Update Session
```bash
PUT /api/sessions/:id
```
**Request:**
```json
{
"notes": "Updated notes",
"location": "The Ruins"
}
```
### Delete Session
```bash
DELETE /api/sessions/:id
```
## Files Endpoints
### Upload File
```bash
POST /api/files/upload
Content-Type: multipart/form-data
```
**Form Data:**
- `file`: The file to upload
### Get File
```bash
GET /api/files/:filename
```
### Delete File
```bash
DELETE /api/files/:filename
```
### List Files
```bash
GET /api/files
```
## Error Handling
### Standard Responses
```json
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human readable error",
"details": "Additional details"
}
}
```
### Common Errors
| Code | Description |
|------|-------------|
| `UNAUTHORIZED` | Invalid or missing session |
| `FORBIDDEN` | Insufficient permissions |
| `NOT_FOUND` | Resource doesn't exist |
| `VALIDATION_ERROR` | Invalid input data |
| `INTERNAL_ERROR` | Server error |
### Error Examples
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
}
```
## Rate Limiting
API calls are rate limited:
- **100 requests per minute** per IP
- Headers include:
- `X-RateLimit-Limit: 100`
- `X-RateLimit-Remaining: 99`
## Webhooks
Webhooks can be configured for events:
- Player created
- Item purchased
- Session created
```bash
POST /api/webhooks
```
**Request:**
```json
{
"url": "https://example.com/webhook",
"events": ["player.created", "item.purchased"],
"secret": "your-webhook-secret"
}
```
## Testing with curl
### Get Players
```bash
curl http://localhost:5000/api/players
```
### Get Shop
```bash
curl http://localhost:5000/api/shop
```
### Get Bestiary
```bash
curl http://localhost:5000/api/bestiary
```
### Search Rules
```bash
curl "http://localhost:5000/api/rules/search?query=damage"
```
+275
View File
@@ -0,0 +1,275 @@
# Contributing Guide
Thank you for your interest in contributing to Deathwatch Roller! This guide will help you get started.
## How to Contribute
### Reporting Bugs
1. Check if the bug already exists in [issues](https://github.com/alexpolo1/dwroller/issues)
2. Create a new issue with:
- Clear title and description
- Steps to reproduce
- Expected vs actual behavior
- Screenshots if applicable
- Your environment (Node version, OS)
### Suggesting Features
1. Check [issues](https://github.com/alexpolo1/dwroller/issues) for similar suggestions
2. Create a feature request issue
3. Include use case and expected behavior
### Pull Requests
1. Fork the repository
2. Create a branch (`git checkout -b feature/amazing-feature`)
3. Make your changes
4. Add tests for new functionality
5. Update documentation
6. Commit with descriptive messages
7. Push to your branch
8. Open a pull request
```bash
git checkout -b feature/amazing-feature
npm install
npm run dev
# Make changes
git add .
git commit -m "feat: add amazing feature"
git push origin feature/amazing-feature
```
## Development Workflow
### Setting Up Your Environment
```bash
# Clone the repository
git clone https://github.com/alexpolo1/dwroller.git
cd dwroller
# Install dependencies
npm install
# Start development servers
npm run dev
```
### Code Style
We follow these style guidelines:
- **TypeScript**: Use TypeScript for all new code
- **ESLint**: Run `npm run lint` before committing
- **Prettier**: Auto-format with `npm run format`
- **Testing**: Add tests for all new features
### Commit Guidelines
Use conventional commits:
```
feat: New feature
fix: Bug fix
docs: Documentation
style: Code style changes
refactor: Code refactoring
test: Adding tests
chore: Maintenance tasks
```
## Code Review Process
All PRs go through:
1. **Initial Review**: Automated checks (lint, tests)
2. **Technical Review**: Code quality, design, performance
3. **Documentation**: Are docs updated?
4. **Approval**: Maintainer approval
### Review Checklist
- [ ] Tests pass
- [ ] No lint errors
- [ ] Code follows style guide
- [ ] Documentation updated
- [ ] No security issues
- [ ] Performance considerations
## Documentation
Documentation is in the `docs/` folder:
- `SUMMARY.md` - Table of contents
- `quick-start.md` - Setup guide
- `user-guide.md` - User documentation
- `api.md` - API reference
- `developer-guide.md` - Dev guide
When adding features:
- Update relevant documentation
- Add code examples
- Include usage instructions
## Testing
### Backend Tests
```bash
# Run all tests
npm test
# Run with coverage
npm run test:coverage
# Watch mode
npm run test:watch
```
### Frontend Tests
```bash
# Run tests
cd frontend
npm test
# Run with coverage
npm run test:coverage
```
### E2E Tests
```bash
# E2E testing (optional)
npm run test:e2e
```
## Code Quality
### Linting
```bash
# Check for issues
npm run lint
# Fix automatically fixable issues
npm run lint:fix
```
### Formatting
```bash
# Format code
npm run format
```
### Building
```bash
# Build for production
npm run build
# Check build
npm run build
```
## Release Process
1. Update `CHANGELOG.md`
2. Bump version in `package.json`
3. Create release branch
4. Tag release
5. Publish to npm (if applicable)
```bash
npm version patch
git push --follow-tags
```
## Performance Guidelines
- Use indexing for database queries
- Implement caching for static data
- Lazy load heavy components
- Optimize bundle size
- Monitor performance metrics
### Before/After Example
```typescript
// ❌ BAD: N+1 query problem
const items = await db.items.findAll();
items.forEach(item => {
const owner = await db.owners.findOne({ where: { itemId: item.id } });
});
// ✅ GOOD: Use include for eager loading
const items = await db.items.findAll({
include: [{ model: Owner }]
});
```
## Security Guidelines
- Never commit secrets or credentials
- Use environment variables for sensitive data
- Review third-party dependencies
- Use prepared statements for SQL
- Implement proper authentication
### Secrets Management
```bash
# ✅ GOOD
export SESSION_SECRET=${SESSION_SECRET}
# ❌ BAD - Never do this
SESSION_SECRET="hardcoded-secret"
```
## Accessibility
Make sure your changes:
- Support keyboard navigation
- Include ARIA labels where needed
- Maintain color contrast
- Support screen readers
- Are responsive
## Browser Support
Test on:
- Chrome/Edge (Chromium)
- Firefox
- Safari
- Mobile browsers
## Performance Benchmarks
- Initial load: < 2s
- API response: < 200ms
- Bundle size: < 500kb (gzipped)
- Lighthouse score: > 90
## Community
- [GitHub Issues](https://github.com/alexpolo1/dwroller/issues)
- [Pull Requests](https://github.com/alexpolo1/dwroller/pulls)
- Contributing guidelines: `CONTRIBUTING.md`
## Code of Conduct
- Be respectful
- Welcome newcomers
- Provide constructive feedback
- Focus on the project
## License
By contributing, you agree that your contributions will be licensed under the MIT License.
## Questions?
Open an issue or start a discussion on GitHub.
+439
View File
@@ -0,0 +1,439 @@
# Developer Guide
## Project Structure
```
dwroller/
├── backend/
│ ├── src/
│ │ ├── routes/ # API routes
│ │ ├── models/ # Data models
│ │ ├── controllers/ # Route controllers
│ │ ├── middleware/ # Auth, validation
│ │ └── utils/ # Helper functions
│ ├── server.js # Entry point
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── pages/ # Route pages
│ │ ├── hooks/ # Custom hooks
│ │ └── store/ # State management
│ ├── public/ # Static assets
│ ├── package.json
│ └── vite.config.js
├── data/ # Static data files
├── database/ # Database files
└── docs/ # Documentation
```
## Development Setup
### Backend
```bash
cd backend
npm install
npm run dev
```
The backend starts on port 5000.
### Frontend
```bash
cd frontend
npm install
npm run dev
```
The frontend starts on port 3000.
## Code Style
### JavaScript/TypeScript
- Use TypeScript for new code
- Follow Airbnb JavaScript style guide
- Maximum 100 character line length
- Use ESLint for linting
```typescript
// Example code style
interface Player {
id: number;
name: string;
xp: number;
rp: number;
}
export class PlayerService {
async getPlayer(id: number): Promise<Player> {
const player = await this.repository.findById(id);
return this.transform(player);
}
}
```
### React
- Functional components with hooks
- Use TypeScript for props
- Follow React best practices
- Use Context for global state
```typescript
// Example React component
interface ShopItemProps {
item: ShopItem;
onPurchase: (itemId: number) => void;
}
const ShopItem: React.FC<ShopItemProps> = ({ item, onPurchase }) => {
return (
<div className="shop-item">
<h3>{item.name}</h3>
<p>Cost: {item.cost} RP</p>
<button onClick={() => onPurchase(item.id)}>
Purchase
</button>
</div>
);
};
```
## Database
### Schema
The database uses SQLite by default. The schema is created automatically on first run.
Main tables:
- `players` - Player accounts
- `items` - Shop inventory
- `inventory` - Player item ownership
- `sessions` - Game session tracking
- `webhooks` - Webhook configurations
### Migrations
Migrations are stored in `backend/migrations/`.
```bash
# Run migrations
npm run migrate
# Create new migration
npx knex migrate:make create_new_table
```
## API Development
### Creating a New Endpoint
```bash
backend/src/routes/new-endpoints.ts
```
```typescript
import express, { Request, Response } from 'express';
const router = express.Router();
// GET /new-endpoint
router.get('/', async (req: Request, res: Response) => {
const data = await getNewData();
res.json({ success: true, data });
});
export default router;
```
Add to `server.js`:
```typescript
import newEndpoints from './src/routes/new-endpoints';
app.use('/api/new', newEndpoints);
```
### Adding Authentication
```typescript
import { requireAuth } from '../middleware/auth';
router.get(protectedRoute, requireAuth, async (req, res) => {
// Protected route logic
});
```
## Frontend Development
### Creating a New Component
```bash
frontend/src/components/NewComponent.tsx
```
```typescript
import React from 'react';
interface NewComponentProps {
data: any;
onAction: (action: string) => void;
}
export const NewComponent: React.FC<NewComponentProps> = ({
data,
onAction,
}) => {
const handleClick = () => {
onAction('click');
};
return <div className="new-component">{data.title}</div>;
};
```
### State Management
Use React Context for global state:
```typescript
// frontend/src/store/PlayerContext.tsx
import React, { createContext, useContext, useState } from 'react';
interface PlayerState {
players: Player[];
addPlayer: (player: Player) => void;
}
const PlayerContext = createContext<PlayerState | undefined>(undefined);
export const PlayerProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const [players, setPlayers] = useState<Player[]>([]);
const addPlayer = (player: Player) => {
setPlayers((prev) => [...prev, player]);
};
return (
<PlayerContext.Provider value={{ players, addPlayer }}>
{children}
</PlayerContext.Provider>
);
};
```
## Testing
### Backend Tests
```bash
backend/src/routes/__tests__/new-endpoints.test.ts
```
```typescript
import request from 'supertest';
import app from '../../../server';
describe('New Endpoint', () => {
it('should return 200 for GET', async () => {
const res = await request(app).get('/new-endpoint');
expect(res.statusCode).toBe(200);
expect(res.body.success).toBe(true);
});
});
```
Run tests:
```bash
npm test
```
### Frontend Tests
```bash
frontend/src/components/__tests__/NewComponent.test.tsx
```
```typescript
import { render, screen } from '@testing-library/react';
import NewComponent from '../NewComponent';
describe('NewComponent', () => {
it('renders the title', () => {
render(<NewComponent data={{ title: 'Test' }} />);
expect(screen.getByText('Test')).toBeInTheDocument();
});
});
```
Run tests:
```bash
npm test
```
## Debugging
### Backend Debugging
```bash
# Enable verbose logging
NODE_ENV=development npm run server
# View logs
tail -f backend.log
```
### Frontend Debugging
```bash
# Open DevTools
npm run dev
# Check browser console
# Network tab for API calls
```
## Deployment
### Build
```bash
# Build frontend
npm run build
# Build backend
cd backend
npm run build
```
### PM2 Setup
```bash
# Start with PM2
npm run pm2:start
# View logs
pm2 logs
# Stop
npm run pm2:stop
```
### Production Environment Variables
```bash
# Create production env
cp .env.example .env.production
# Set required variables:
# - NODE_ENV=production
# - SESSION_SECRET
# - X_GM_SECRET
# - PORT
```
## Performance
### Optimization Tips
1. **Database**: Use indexes for frequent queries
2. **Frontend**: Enable code splitting
3. **API**: Implement caching for static data
4. **Images**: Use lazy loading
### Caching
```typescript
// Example: Cache shop data
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
async function getShop() {
const cached = getFromCache('shop');
if (cached) return cached;
const shop = await db.items.findAll();
setCache('shop', shop, CACHE_DURATION);
return shop;
}
```
## Security
### Authentication
All API endpoints use session-based authentication. Implement proper session management:
```typescript
// Session middleware
import { verifyToken } from '../utils/auth';
export const requireAuth = async (req: Request, res: Response, next: NextFunction) => {
const session = req.headers['cookie'];
if (!session) {
return res.status(401).json({ error: 'Unauthorized' });
}
try {
req.user = await verifyToken(session);
next();
} catch (error) {
return res.status(401).json({ error: 'Invalid session' });
}
};
```
### API Security
1. Use HTTPS in production
2. Rate limit API requests
3. Validate all inputs
4. Use prepared statements for SQL
5. Never expose sensitive data
## Contributing
### Pull Request Process
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Update documentation
6. Submit a pull request
### Code Review
All PRs will be reviewed for:
- Code quality
- Test coverage
- Documentation
- Security
- Performance
### Commit Messages
Use conventional commits:
```bash
feat: add new shop item filter
fix: resolve authentication issue
docs: update API documentation
chore: update dependencies
```
## Resources
- [React Documentation](https://react.dev/)
- [Express.js Documentation](https://expressjs.com/)
- [TypeScript Handbook](https://www.typescriptlang.org/docs/)
- [SQLite Documentation](https://www.sqlite.org/docs.html)
+188
View File
@@ -0,0 +1,188 @@
# PM2 Configuration
This document explains how to use PM2 for managing Deathwatch Roller in production.
## What is PM2?
PM2 is a production process manager for Node.js that keeps your application running 24/7.
## Installation
```bash
# Install PM2 globally
npm install -g pm2
# Initialize PM2 ecosystem file
pm2 init
```
## Application Configuration
Create `ecosystem.config.js`:
```javascript
module.exports = {
apps: [
{
name: 'dwroller-frontend',
cwd: './frontend',
script: 'npm',
args: 'start',
env: {
NODE_ENV: 'production',
PORT: 3000
},
env_development: {
NODE_ENV: 'development'
},
instances: 1,
autorestart: true,
max_memory_restart: '500M'
},
{
name: 'dwroller-backend',
cwd: './backend',
script: 'npm',
args: 'start',
env: {
NODE_ENV: 'production',
PORT: 5000
},
env_development: {
NODE_ENV: 'development'
},
instances: 1,
autorestart: true,
max_memory_restart: '500M'
}
]
};
```
## Starting the Application
```bash
# Start both apps
pm2 start ecosystem.config.js
# Start only backend
pm2 start ecosystem.config.js --only backend
# Start only frontend
pm2 start ecosystem.config.js --only frontend
```
## Managing Apps
```bash
# View status
pm2 list
# View logs
pm2 logs
# Restart app
pm2 restart all
# Stop app
pm2 stop all
# Delete app
pm2 delete all
```
## Monitoring
```bash
# Enable monitoring
pm2 monitortype --interval 10000
# View stats
pm2 stats
```
## Logging
```bash
# Rotate logs
pm2 rotate logs
# Save log
pm2 save
# Load saved PM2 process list
pm2 startup
pm2 save
```
## NPM Scripts
Update `package.json` with PM2 scripts:
```json
{
"scripts": {
"start": "npm run build && pm2 start ecosystem.config.js",
"pm2:start": "pm2 start ecosystem.config.js",
"pm2:stop": "pm2 stop all",
"pm2:restart": "pm2 restart all",
"pm2:logs": "pm2 logs",
"pm2:list": "pm2 list",
"pm2:save": "pm2 save",
"pm2:startup": "pm2 startup"
}
}
```
## Production Build
```bash
# Build frontend
cd frontend
npm run build
# Start with PM2
cd ../..
npm run pm2:start
```
## Environment Variables
Store secrets in `.env` or use PM2 env:
```bash
# Set environment variable
pm2 set ecosystem.config.js:* env:SESSION_SECRET="your-secret"
# List all env variables
pm2 env ecosystem.config.js
```
## Backup Strategy
```bash
# Create database backup
npm run backup
# Schedule backup with cron
0 2 * * * /path/to/db/backup.sh
```
## Scaling
For horizontal scaling, configure multiple instances:
```javascript
{
instances: 'max',
exec_mode: 'cluster',
watch: false
}
```
## Auto-restart on reboot
```bash
pm2 startup
pm2 save
```
+127
View File
@@ -0,0 +1,127 @@
# Quick Start Guide
## Prerequisites
Before you begin, ensure you have:
- **Node.js** (v18+ recommended) - Check with `node --version`
- **npm** or **yarn** - Package manager
- **Git** - For version control
## Installation
### 1. Clone the Repository
```bash
git clone https://github.com/alexpolo1/dwroller.git
cd dwroller
```
### 2. Install Dependencies
```bash
npm install
```
This will install all required packages for both frontend and backend.
### 3. Configure Environment
Create a `.env` file in the root directory:
```bash
cp .env.example .env
```
Edit `.env` with your configuration:
```env
# Backend server port
PORT=5000
# Session secret (random string recommended)
SESSION_SECRET=your-random-secret-here
# GM API secret for player management
X_GM_SECRET=your-gm-secret-key
# Database path (optional - defaults to server location)
DATABASE_PATH=./database/data.db
```
### 4. Start the Application
Run both servers:
```bash
# Terminal 1 - Backend API
npm run server
# Terminal 2 - Frontend
npm start
```
The application will be available at:
- **Frontend**: `http://localhost:3000`
- **API**: `http://localhost:5000`
## First Steps
1. Visit `http://localhost:3000` in your browser
2. Browse the shop or view the bestiary
3. If you're a GM, use the player management feature
## Production Deployment
For production builds:
```bash
# Build frontend
npm run build
# Start with PM2
npm run pm2:start
```
See [PM2 Configuration](./pm2.md) for details.
## Troubleshooting
### Port already in use
If port 3000 or 5000 is busy:
```bash
# Find what's using the port
lsof -i :3000
lsof -i :5000
# Kill the process or change the port in .env
```
### Database issues
The application creates the database automatically on first run. If you see errors:
```bash
# Check database exists
ls -la database/
# If database file is corrupted, remove it to recreate
rm database/data.db
```
### Clear cache
If the frontend shows old content:
```bash
rm -rf .next/
npm start
```
## Next Steps
- Read the [User Guide](./user-guide.md) to learn features
- Explore the [API Documentation](./api.md)
- See [Developer Guide](./developer-guide.md) for contribution guidelines
+287
View File
@@ -0,0 +1,287 @@
# Security Guide
This document outlines the security measures and best practices for Deathwatch Roller.
## Authentication
### Session Management
- Sessions use HTTP-only cookies
- Sessions expire after inactivity
- Passwords are hashed with bcrypt
- XSS protection headers enabled
### Session Configuration
```javascript
// Example session config
session: {
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}
}
```
## Database Security
### Password Hashing
```typescript
// Password hashing
import bcrypt from 'bcrypt';
const hashedPassword = await bcrypt.hash(password, 12);
const isMatch = await bcrypt.compare(inputPassword, hashedPassword);
```
### Prepared Statements
All database queries use parameterized statements to prevent SQL injection:
```typescript
// ✅ GOOD - Using parameterized query
const player = await Player.findOne({
where: { email: email },
raw: true
});
// ❌ BAD - String concatenation
const badQuery = `SELECT * FROM players WHERE email = '${email}'`;
```
## Input Validation
### Request Validation
All API requests are validated:
```typescript
import { body, validationResult } from 'express-validator';
router.post('/players', [
body('name').isLength({ min: 1, max: 50 }).trim(),
body('email').isEmail().normalizeEmail(),
body('xp').isInt({ min: 0 })
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Process request
});
```
## CORS Configuration
```typescript
// CORS setup
import cors from 'cors';
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(','),
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
```
## Rate Limiting
```typescript
// Rate limiter
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP, please try again later.'
});
app.use('/api/', limiter);
```
## Security Headers
```typescript
import helmet from 'helmet';
app.use(helmet());
// Custom headers
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
next();
});
```
## Environment Variables
Store sensitive data in environment variables:
```bash
# .env file
SESSION_SECRET=your-secure-random-string
X_GM_SECRET=your-gm-secret-key
DATABASE_PASSWORD=your-database-password
```
Never commit `.env` files:
```bash
# .gitignore
.env
.env.*
!/.env.example
```
## API Security
### GM Authentication
GM endpoints require special authentication:
```typescript
// GM secret header
app.use('/api/players/gm/*', (req, res, next) => {
const secret = req.headers['x-gm-secret'];
if (!secret || secret !== process.env.X_GM_SECRET) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
});
```
### API Rate Limits
```typescript
const apiLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100,
keyGenerator: (req) => req.ip
});
app.use('/api/', apiLimiter);
```
## File Upload Security
```typescript
import multer from 'multer';
const upload = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => cb(null, 'uploads/'),
filename: (req, file, cb) => {
const uniqueName = `${Date.now()}-${Math.random()}-${file.originalname}`;
cb(null, uniqueName);
}
}),
fileFilter: (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Invalid file type'));
}
},
limits: {
fileSize: 10 * 1024 * 1024 // 10MB
}
});
```
## Database Backups
```bash
# Backup script
#!/bin/bash
mysqldump -u user -p database > backup_$(date +%Y%m%d_%H%M%S).sql
# Rotate old backups
find . -name "backup_*.sql" -mtime +30 -delete
```
## Monitoring
Set up monitoring for security events:
```typescript
// Audit logging
import auditlog from 'express-auditlog';
app.use(auditlog());
```
## Security Checklist
- [ ] Session cookies are HTTP-only
- [ ] Passwords are hashed with bcrypt
- [ ] SQL queries use parameterized statements
- [ ] CORS is properly configured
- [ ] Rate limiting is enabled
- [ ] Security headers are set
- [ ] Environment variables are not committed
- [ ] Input is validated on all endpoints
- [ ] File uploads are sanitized
- [ ] Dependencies are up to date
## Common Vulnerabilities
### SQL Injection Prevention
```typescript
// ✅ SAFE
User.findOne({ where: { email: email } });
// ❌ UNSAFE
User.findAll({ where: `email = '${email}'` });
```
### XSS Prevention
```typescript
// ✅ SAFE - Sanitize user input
const displayName = sanitize(userInput);
// ❌ UNSAFE - Direct output
res.send(userInput);
```
## Dependencies
Keep dependencies updated:
```bash
# Check for updates
npm outdated
# Update all
npm update
# Update specific package
npm update express
```
## Security Audits
```bash
# Run security audit
npm audit
# Fix vulnerabilities
npm audit fix
```
## Best Practices
1. **Principle of Least Privilege**: Use minimal permissions
2. **Defense in Depth**: Multiple security layers
3. **Fail Securely**: Default to safe responses
4. **Log Security Events**: Monitor for suspicious activity
5. **Regular Audits**: Periodic security reviews
+336
View File
@@ -0,0 +1,336 @@
# Troubleshooting Guide
Common issues and their solutions for Deathwatch Roller.
## Application Won't Start
### Port Already in Use
```bash
# Check what's using port 3000 or 5000
lsof -i :3000
lsof -i :5000
# Kill the process or change the port in .env
kill -9 <PID>
```
### Dependencies Not Installed
```bash
# Reinstall dependencies
npm install
# Or update existing
npm install --save
```
### Node Version Too Old
```bash
# Check Node version
node --version
# Requires Node.js 18+ (check package.json for version)
# Upgrade Node
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
```
## Database Errors
### Database Not Found
```bash
# Check if database directory exists
ls -la database/
# The database is created automatically on first run
# If missing, remove it to recreate
rm database/data.db
```
### Corrupted Database
```bash
# Backup current database
cp database/data.db database/data.db.backup
# Recreate database
rm database/data.db
# Application will recreate on restart
```
## Frontend Issues
### Cache Not Updating
```bash
# Clear build cache
rm -rf .next/
rm -rf frontend/node_modules/.cache/
# Rebuild
npm run build
npm start
```
### Styles Not Loading
Check that `vite.config.js` or webpack is configured correctly for asset handling.
### Build Fails
```bash
# Clean and rebuild
rm -rf node_modules
rm -rf frontend/node_modules
npm install
npm run build
```
## Backend Issues
### Database Connection Failed
```bash
# Check .env file
cat .env
# Verify database path exists
ls -la $DATABASE_PATH
```
### Server Logs Show Errors
```bash
# Check backend logs
tail -f backend.log
# Clear logs
> backend.log
```
## Authentication Issues
### Cannot Login
- Verify `.env` has `SESSION_SECRET` set
- Check if password is correct
- Try password reset
```bash
# Reset session secret
NODE_ENV=development npm run server
```
### Session Expires Too Soon
```bash
# Check session config in server.js
# Increase maxAge in cookie config
```
## API Issues
### CORS Errors
```bash
# Check CORS configuration in server.js
# Ensure frontend origin is allowed
```
### API Endpoints Not Working
```bash
# Test API directly
curl http://localhost:5000/api/players
# Check backend logs
tail -f backend.log
```
## Deployment Issues
### PM2 Not Starting
```bash
# Check ecosystem.config.js exists
ls ecosystem.config.js
# View PM2 logs
pm2 logs
# Restart apps
pm2 restart all
```
### Build Fails in Production
```bash
# Clean build
npm run clean
npm run build
# Check for build errors
npm run build 2>&1
```
## Performance Issues
### Application is Slow
```bash
# Check for memory leaks
pm2 monitortype --interval 10000
# Check database queries
# Add indexes to frequently queried fields
# Enable compression
npm install compression
app.use(compression());
```
### High CPU Usage
```bash
# Identify the process
ps aux | grep node
# Check for infinite loops in code
# Review recent deployments
```
## Browser Issues
### Styles Not Applying
- Clear browser cache (Ctrl+Shift+Delete)
- Try incognito mode
- Check browser console for errors
### JavaScript Console Errors
```bash
# Check frontend code for syntax errors
cd frontend
npm run lint
# Check browser DevTools
# Network tab for failed requests
```
## Production Issues
### Application Crashes on Restart
```bash
# Check error logs
pm2 logs --err
# Enable better error logging
NODE_ENV=production npm run start
```
### Memory Issues
```bash
# Monitor memory usage
pm2 monitortype --interval 10000
# Increase max_memory_restart in ecosystem.config.js
max_memory_restart: '1G'
```
## Development Issues
### TS Errors
```bash
# Type check
cd backend
npx tsc --noEmit
# Fix errors in .ts files
```
### E2E Tests Failing
```bash
# Run tests in debug mode
npm run test:e2e -- --debug
# Check test logs
npm run test:e2e
```
## Quick Fixes
### Reset Everything
```bash
# Stop all services
pm2 stop all
# Clear caches
rm -rf .next/
rm -rf frontend/node_modules/.cache/
# Recreate database
rm database/data.db
# Reinstall
npm install
# Restart
npm run pm2:start
```
### Debug Mode
```bash
# Enable verbose logging
NODE_ENV=development npm run dev
# Watch mode
npm run dev
```
## Getting Help
1. Check the logs: `tail -f backend.log`
2. Review the [Developer Guide](./developer-guide.md)
3. Search for issues on GitHub
4. Create a new issue with:
- Steps to reproduce
- Expected vs actual behavior
- Logs and error messages
## Common Error Messages
### "Cannot find module"
```bash
npm install
# or
npm install --save <missing-package>
```
### "EADDRINUSE"
```bash
# Check what's using the port
lsof -i :<port>
kill -9 <PID>
```
### "Database connection failed"
```bash
# Check .env has correct database path
cat .env | grep DATABASE_PATH
# Or set it explicitly
DATABASE_PATH=./database/data.db
```
+118
View File
@@ -0,0 +1,118 @@
# User Guide
## Introduction
Deathwatch Roller helps you manage your tabletop RPG sessions, track player progress, and access game resources.
## Main Features
### Dashboard
The main page provides quick access to all features:
- Shop for items
- Browse bestiary
- View rules database
- Access GM tools (if authorized)
### Shop
Browse and purchase equipment:
1. Click **"Shop"** in the navigation
2. Filter by item type (weapons, armor, vehicles)
3. Check RP cost and stats
4. Click **"Purchase"** to buy items
5. Items are added to your requisition
### Bestiary
Look up monsters and enemies:
1. Click **"Bestiary"** in navigation
2. Search by name or type
3. View monster stats and weaknesses
4. Use in combat preparation
### Rules Database
Access game rules:
1. Click **"Rules"** in navigation
2. Search for specific rules
3. View quick reference cards
4. Print rulesheets for reference
### Player Management (GM Only)
Game Masters can manage players:
1. Click **"Players"** in navigation (GM only)
2. Create new player accounts
3. Edit player stats and RP
4. Reset passwords
5. Bulk modify XP/RP
### Session Tracking
Track your game sessions:
1. Click **"Sessions"** in navigation
2. Create a new session
3. Add player notes
4. Track accomplishments
5. Export session data
## Tips and Tricks
### Quick Reference
Print quick reference cards for your next session:
- Click **"Print"** in navigation
- Download PDF reference sheets
- Keep handy for quick lookup
### GM Kit
Game Masters have access to special tools:
- Character generator
- Scenario templates
- Combat generator
- Utility scripts
### Session Organization
Organize your sessions:
- Add notes after each game
- Track player progression
- Maintain a campaign log
- Export data for backups
## Keyboard Shortcuts
| Shortcut | Action |
|----------|--------|
| `Ctrl+K` | Quick search |
| `Ctrl+S` | Save current view |
| `Ctrl+P` | Print current page |
## Accessibility
The application supports:
- Screen readers
- Keyboard navigation
- High contrast mode
- Adjustable text size
## Privacy
- Player data is stored locally
- No external data collection
- Session data is encrypted
- GM tools require secret key
## Support
For issues or questions:
- Check the [Developer Guide](./developer-guide.md)
- Review the [API documentation](./api.md)
- See open issues on GitHub