- React frontend with Vite + TypeScript - Cloudflare Worker backend with Durable Objects - AI-powered chat moderation via OpenAI - WebSocket-based real-time messaging - XSS prevention, rate limiting, input validation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Real-time chat application with AI-powered moderation. Korean-language community chat ("Anvil Lounge") with an AI bot host (방장) that moderates conversations, answers questions, and provides weather/documentation lookups.
Architecture
chat-app/
├── frontend/ # React SPA (Vite + TypeScript)
│ └── src/
│ ├── components/ # ChatRoom, MessageList, MessageInput
│ ├── hooks/ # useWebSocket (WebSocket client with reconnection)
│ └── utils/ # sanitize.ts (XSS prevention, markdown→HTML)
└── worker/ # Cloudflare Worker + Durable Object
└── src/
├── index.ts # HTTP router, CORS handling
├── ChatRoom.ts # Durable Object: WebSocket hub, message persistence
├── AIManager.ts # OpenAI integration, moderation, tool calling
├── Context7Client.ts # Documentation lookup API
├── RateLimiter.ts # In-memory rate limiting
└── validation.ts # Zod schemas for message validation
Key Design Patterns
Durable Objects with Hibernation API: ChatRoom uses webSocketMessage(), webSocketClose(), webSocketError() handlers instead of event listeners. Session data stored via ws.serializeAttachment().
AI Moderation Flow: Messages are checked by AI for profanity before broadcast. Detected words are masked (첫 글자 + asterisks). Repeated violations trigger auto-silence via trackViolation() → DO storage transaction.
Storage Patterns: All DO storage operations use transactions for atomicity and retry logic with jitter for resilience.
Development Commands
# Root-level (npm workspaces)
npm run dev:worker # Start worker dev server (wrangler)
npm run dev:frontend # Start Vite dev server (localhost:5173)
npm run build:worker # Build worker
npm run build:frontend # Build frontend (tsc + vite)
npm run deploy:worker # Deploy to Cloudflare Workers
npm run deploy:frontend # Deploy to Cloudflare Pages
# Type checking
cd worker && npx tsc --noEmit
cd frontend && npx tsc --noEmit
# Worker secrets
wrangler secret put OPENAI_API_KEY
API Endpoints
| Endpoint | Description |
|---|---|
GET /api/rooms/:roomId/websocket |
WebSocket upgrade for chat |
GET /api/rooms/:roomId/users |
List users in room |
GET /api/health |
Health check |
WebSocket Message Types
Client → Server: { type: "message", content: string } or { type: "rename", name: string }
Server → Client: message, join, leave, userList, history, error
Configuration Alignment
Frontend config.ts and backend validation.ts must stay in sync:
maxMessageLength: 2000 charactersmaxUserNameLength: 50 characters
Security Considerations
- XSS prevention:
sanitize.tsuses DOMPurify + custom URL validation (isUrlSafe()) to block encodedjavascript:attacks - API key redaction:
sanitizeErrorForLogging()in AIManager.ts strips credentials from error logs - CORS: Strict origin allowlist in
index.ts(includes Pages preview deployments) - Input validation: All WebSocket messages validated with Zod schemas before processing
External Services
- OpenAI API: Chat completions with function calling (weather, docs, hosting info, silence user)
- Open-Meteo API: Weather data (no API key required)
- Context7 API: Documentation lookup for technical questions