# 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 { 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 = ({ item, onPurchase }) => { return (

{item.name}

Cost: {item.cost} RP

); }; ``` ## 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 = ({ data, onAction, }) => { const handleClick = () => { onAction('click'); }; return
{data.title}
; }; ``` ### 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(undefined); export const PlayerProvider: React.FC<{ children: React.ReactNode }> = ({ children, }) => { const [players, setPlayers] = useState([]); const addPlayer = (player: Player) => { setPlayers((prev) => [...prev, player]); }; return ( {children} ); }; ``` ## 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(); 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)