6.4 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
FurryPlace is an unofficial open-source backend for wplace (a collaborative pixel art canvas), built with TypeScript, tinyhttp, Prisma, and MySQL. The system manages user authentication, pixel painting with charge-based rate limiting, alliances, leaderboards, and moderation features.
Development Commands
Essential Commands
pnpm dev- Run development server with hot reload (watches src/ directory)pnpm build- Compile TypeScript to dist/pnpm start- Run production build from dist/pnpm test- Run tests oncepnpm test:watch- Run tests in watch modepnpm lint- Check for linting issuespnpm lint:fix- Auto-fix linting issues
Database Commands
pnpm db:push- Push schema changes to database and regenerate Prisma clientpnpm db:generate- Regenerate Prisma client onlypnpm db:migrate- Create and run a new migrationpnpm seed- Seed database with initial data
Requirements
- Node.js >= 24
- pnpm >= 10
- MySQL/MariaDB
Architecture
Backend Structure
Entry Point: src/index.ts - Sets up tinyhttp app with middleware (CORS, cookie parser, JSON body parsing, logging) and registers all route modules.
Authentication Flow: JWT tokens stored in j cookie → validated by src/middleware/auth.ts → checks session validity in database → attaches req.user with { id, sessionId }
Database: Prisma ORM with MySQL. Global instance exported from src/config/database.ts and injected into request via middleware.
Route Organization: Each feature module exports a function that registers routes on the tinyhttp app:
- src/routes/auth.ts - Registration, login, logout
- src/routes/pixel.ts - Pixel painting, tile generation, pixel info
- src/routes/alliance.ts - Alliance CRUD, invites, bans, leaderboards
- src/routes/me.ts - User profile, favorite locations, settings
- src/routes/admin.ts - User management, bans, timeouts, tickets
- src/routes/moderator.ts - Moderation actions
- src/routes/leaderboard.ts - Global leaderboards
- src/routes/store.ts - Purchase colors and flags
Service Layer: Business logic isolated in service classes:
- src/services/pixel.ts -
PixelServicehandles pixel painting with charge validation, color unlocking checks, tile image generation using @napi-rs/canvas, and level calculation - src/services/alliance.ts -
AllianceServicehandles alliance creation, member management, bans - src/services/user.ts -
UserServicehandles user profile updates, favorites
Core Systems:
-
Charge System (src/utils/charges.ts): Rate-limiting mechanism where users have
maxCharges(default 20) that regenerate everychargesCooldownMs(default 30s). Painting consumes charges. FunctioncalculateChargeRecharge()computes current charge based on time elapsed. -
Bitmap System (src/utils/bitmap.ts):
WplaceBitMapclass stores boolean flags as packed bytes for efficient storage (used for unlocked colors, flags). Stored in database as Bytes, converted to base64 for API responses. -
Color Palette (src/utils/colors.ts): Defines available colors with RGB values and whether they're paid.
checkColorUnlocked()validates if user has purchased a color by checking bitmap. -
Tile System: Canvas divided into 1000x1000 tiles. Each pixel has coordinates
(tileX, tileY, x, y). Tile images dynamically generated on-demand from pixel data. -
Regions (src/config/regions.ts): Maps coordinates to geographic regions/countries. Users get 10% charge discount when painting in their equipped flag's region. Currently returns placeholder data - implementation needed.
Database Schema
Key models in prisma/schema.prisma:
- User: Core user data, charge state, pixels painted, level, alliance membership, equipped flag, unlocked colors bitmap
- Pixel: Individual pixel with coordinates (tileX, tileY, x, y), colorId, paintedBy userId, timestamp
- Tile: Metadata for 1000x1000 tile regions, has many Pixels
- Alliance: Groups with members, bans, invites, HQ coordinates, total pixels painted
- Session: JWT session tracking with expiration
- Ticket: Moderation reports with evidence
- UserNote: Moderator notes on users
Frontend
Pre-built SvelteKit frontend in frontend/ directory (served as static files, not part of development workflow). Backend serves 404.html for unmatched routes.
Key Implementation Patterns
-
Route Pattern: Routes validate input → call service method → return JSON or handle service errors via
handleServiceError() -
Service Pattern: Services receive Prisma client in constructor, contain business logic, throw descriptive errors that are caught by error handler middleware
-
Bulk Pixel Insert: Painting uses raw SQL
INSERT ... ON DUPLICATE KEY UPDATEfor performance when updating multiple pixels -
Level Calculation:
Math.floor(Math.sqrt(pixelsPainted / 100)) + 1 -
Validation: Separate validator functions in src/validators/ for common input patterns (seasons, coordinates, pagination)
-
Error Responses: Standardized via
createErrorResponse()and HTTP_STATUS constants in src/utils/response.ts
Environment Setup
Copy .env.example to .env and configure:
DATABASE_URL- MySQL connection string (format:mysql://user:password@host/database)JWT_SECRET- Secret key for JWT signingPORT- Server port (default 3000)
Important Notes
- The project is a work-in-progress with incomplete features (see README.md warnings)
- Region lookup system is stubbed and returns placeholder data - needs implementation
- Authentication uses JWT cookies named
j - All API responses use JSON format
- The backend is designed to work with the wplace.live frontend protocol
- Production deployment requires SSL/HTTPS (enforced by design)
- Use
pnpmas package manager (not npm)