This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
The Luminari Wilderness Editor is a full-stack monorepo application for creating and managing wilderness areas in the LuminariMUD game world. It consists of a React/TypeScript frontend and Python FastAPI backend, with shared types and utilities.
CRITICAL ARCHITECTURE NOTES:
- ✅ MIGRATION COMPLETE: Express backend has been replaced with Python FastAPI
- The backend now directly integrates with LuminariMUD's existing MySQL spatial tables
- Supabase was used for initial development but production uses direct MySQL integration
- Real-time integration with the game world through direct database access
# Install dependencies
npm install
# Start frontend only (backend runs separately)
npm run dev:frontend # Frontend on :5173
# Start Python backend
cd apps/backend/src
python -m uvicorn main:app --reload --host 0.0.0.0 --port 8000
# Build frontend
npm run build:frontend
# Python backend doesn't need building (interpreted language)
# Run linting across all packages
npm run lint
# Fix linting issues across all packages
npm run lint:fix
# Type checking across all packages
npm run type-check
# Clean all build artifacts
npm run cleanThis is a monorepo using npm workspaces and Turborepo for build orchestration:
- apps/frontend/: React 18.3 + TypeScript 5.5 + Vite
- apps/backend/: Python 3.8+ + FastAPI + SQLAlchemy + MySQL integration
- packages/shared/: Shared TypeScript types and utilities
- Framework: React 18.3 with TypeScript 5.5
- Build Tool: Vite 7.0
- Styling: Tailwind CSS
- Icons: Lucide React
- Authentication: Supabase Auth (client-side)
- API Client: Custom fetch-based client with error handling
- Framework: FastAPI (Python 3.8+) with Uvicorn ASGI server
- Database: Direct MySQL integration with LuminariMUD spatial tables
- ORM: SQLAlchemy for database operations
- Validation: Pydantic schemas for request/response validation
- API: RESTful endpoints with automatic OpenAPI documentation
- Authentication: JWT token validation (configurable)
- Performance: Async support for high-performance operations
- Types: Shared TypeScript interfaces and types
- Utilities: Common functions used by both frontend and backend
The application follows a clean separation between frontend and backend:
apps/frontend/src/
├── components/ # React UI components
├── hooks/ # Custom React hooks
├── services/ # API client and external services
├── types/ # Type definitions (re-exports from shared)
└── App.tsx # Main application component
apps/backend/src/
├── models/ # SQLAlchemy database models
├── schemas/ # Pydantic request/response schemas
├── routers/ # FastAPI route handlers
├── config/ # Database and app configuration
├── main.py # FastAPI application entry point
└── requirements.txt # Python dependencies
packages/shared/src/
└── types/ # Shared TypeScript interfaces
-
Coordinate System: The wilderness uses a coordinate grid from -1024 to +1024 on both X and Y axes, matching the LuminariMUD wilderness system.
-
Drawing Tools:
select: Click items to view/edit propertiespoint: Place single landmarkspolygon: Draw regions (requires 3+ points)linestring: Draw paths (requires 2+ points)
-
Data Types:
- Region: Polygonal areas with types (geographic, encounter, sector_transform, sector)
- Path: Linear features with types (road, dirt_road, geographic, river, stream)
- Point: Single coordinate landmarks
-
State Management:
- Frontend: React hooks with API integration
- Backend: SQLAlchemy ORM with direct MySQL database access
- Production: Real-time integration with LuminariMUD spatial tables
- Real-time updates: Optimistic UI updates with API persistence
-
API Integration: The frontend communicates with the backend via RESTful API:
- FastAPI automatic OpenAPI documentation at
/docs - Pydantic validation for all requests and responses
- CRUD operations for regions, paths, and points
- Error handling and loading states
- Optimistic updates for better UX
- FastAPI automatic OpenAPI documentation at
Production (LuminariMUD MySQL Spatial Tables)
The backend now directly integrates with LuminariMUD's existing MySQL spatial database:
-- Regions table (MySQL with spatial support)
CREATE TABLE regions (
id INT PRIMARY KEY AUTO_INCREMENT,
vnum INT UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(100) NOT NULL,
coordinates JSON NOT NULL,
properties TEXT,
color VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- Paths table
CREATE TABLE paths (
id INT PRIMARY KEY AUTO_INCREMENT,
vnum INT UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(100) NOT NULL,
coordinates JSON NOT NULL,
color VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- Points table
CREATE TABLE points (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
type VARCHAR(100) NOT NULL,
coordinate JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);Production (LuminariMUD MySQL Spatial Tables) The core system will integrate directly with the existing LuminariMUD MySQL spatial database tables. This provides real-time integration with the game world, allowing changes made in the editor to immediately affect the game environment.
The backend provides RESTful endpoints:
GET /api/health # Health check
GET /api/regions # List all regions
GET /api/regions/:id # Get specific region
POST /api/regions # Create region (auth required)
PUT /api/regions/:id # Update region (auth required)
DELETE /api/regions/:id # Delete region (auth required)
# Similar endpoints for /api/paths and /api/points
- User authenticates with Supabase (frontend)
- Frontend receives JWT access token
- API client sets Authorization header for backend requests
- Backend middleware validates JWT with Supabase
- Protected routes require valid authentication
-
Frontend Development:
- Current tool selection
- Drawing state and temporary coordinates
- Selected items for editing
- Layer visibility toggles
- Zoom level and mouse position
- API integration with loading/error states
-
Backend Development:
- FastAPI server with Python 3.8+
- SQLAlchemy ORM with MySQL integration
- Pydantic schemas for validation
- Async/await support for performance
- RESTful API with automatic OpenAPI docs
- Error handling and validation
-
Shared Development:
- Type definitions in packages/shared
- Both frontend and backend import shared types
- Consistent data structures across the stack
The monorepo uses environment variables for configuration:
VITE_API_URL=http://localhost:8000/api
# Authentication configuration (if needed)
VITE_JWT_SECRET=your_jwt_secret
# Database configuration
MYSQL_DATABASE_URL=mysql+pymysql://username:password@localhost/luminari_mudprod
# Server configuration
PORT=8000
HOST=0.0.0.0
# CORS configuration
FRONTEND_URL=http://localhost:5173
# Authentication (optional)
JWT_SECRET=your_jwt_secret
JWT_ALGORITHM=HS256
Production domain: https://wildedit.luminarimud.com
Implemented:
- ✅ Monorepo structure with npm workspaces
- ✅ FastAPI backend with Python 3.8+
- ✅ Direct MySQL database integration
- ✅ SQLAlchemy ORM models
- ✅ Pydantic validation schemas
- ✅ RESTful API endpoints for all entities
- ✅ Automatic OpenAPI documentation
- ✅ Frontend API client with error handling
- ✅ Optimistic UI updates
- ✅ Shared type definitions
- ✅ Development workflow with Turborepo
In Progress:
- Database table creation (manual setup required)
- Error boundary implementation
- Comprehensive testing
- Production deployment configuration
-
Install dependencies:
npm install
-
Set up Python backend environment:
# Install Python dependencies cd apps/backend/src pip install -r requirements.txt # Configure database connection cp .env.example .env # Edit .env with your MySQL database credentials
-
Set up MySQL database:
- Configure connection to LuminariMUD MySQL database
- Ensure spatial tables exist for regions, paths, points
- Test database connectivity
-
Start development servers:
# Start frontend npm run dev:frontend # Start Python backend (separate terminal) cd apps/backend/src python -m uvicorn main:app --reload --host 0.0.0.0 --port 8000
-
Access the application:
- Frontend: http://localhost:5173
- Backend API: http://localhost:8000/api
- API Documentation: http://localhost:8000/docs
- Health check: http://localhost:8000/api/health
Adding new features:
- Define types in
packages/shared/src/types/ - Add Python models in
apps/backend/src/models/ - Create Pydantic schemas in
apps/backend/src/schemas/ - Add FastAPI endpoints in
apps/backend/src/routers/ - Update frontend API client in
apps/frontend/src/services/api.ts - Test both frontend and backend integration
Debugging:
- Frontend: Check browser console and React DevTools
- Backend: Check FastAPI server logs and uvicorn output
- Database: Use MySQL client or GUI tools for query debugging
- API: Use automatic OpenAPI docs at http://localhost:8000/docs
- Authentication: Verify JWT tokens and authentication flow
Working with the monorepo:
- Frontend: Use
npm run dev:frontend - Backend: Run Python FastAPI server separately
- Use workspace-specific commands:
npm run dev --workspace=@wildeditor/frontend - Shared types are automatically available in frontend
- Changes to shared package require frontend restart
For comprehensive information beyond this technical overview, refer to:
- README.md - Project overview, quick start, and complete documentation map
- docs/SETUP.md - Detailed setup instructions
- docs/README_DOCS.md - Documentation index and organization guide
- docs/DEVELOPER_GUIDE.md - Full development guide and best practices
- docs/API.md - Complete API reference and examples
- docs/WILDERNESS_PROJECT.md - Detailed project specifications and milestones
- docs/WILDERNESS_SYSTEM.md - LuminariMUD wilderness system architecture
- docs/adr/ - Architecture Decision Records for major technical decisions
- docs/MIGRATION.md - Express to Python FastAPI migration guide
- docs/INTEGRATION.md - LuminariMUD game server integration procedures
- docs/TESTING.md - Testing strategy and implementation guide
- docs/TODO.md - Active development tasks and known issues
- docs/CHANGELOG.md - Recent changes and version history
- docs/AUDIT.md - Code quality assessment and recommendations
All documentation is kept up-to-date and reflects the current Python FastAPI backend architecture.
The Wilderness Editor implements a staging pattern for all AI-generated content, ensuring users can review and modify content before persisting to the database.
- Generation: MCP tools (
generate_region_description,generate_hints_from_description) return content only - Staging: Content is held in frontend component state as "staged"
- Review: Users see indicators for staged content and can modify before saving
- Save/Discard: Explicit save commits all staged content to database
- Descriptions: Staged via
onUpdate()which marks region as dirty - Hints: Staged in component state (
stagedHints), saved with region - State Timing: Staged content used immediately, avoiding React prop update delays
- No Direct Saves: Generated content never saves directly to database
Generation tools (return data only):
generate_region_descriptiongenerate_hints_from_description
Persistence tools (save to database):
update_region_descriptionstore_region_hints
The frontend controls when persistence happens via Save/Discard buttons.
- Text Copy: Any text in description field is copied to AI generation prompt
- Staging Indicators: Amber warnings show when content is staged but not saved
- Inline Discard: Quick discard buttons for staged hints
- Unified Save: Save button persists both description and hints together
- ✅ React State Timing Fix: Hints can be generated immediately after description
- ✅ Description Staging: Generated descriptions staged locally before save
- ✅ Hints Staging: Generated hints staged locally, no direct DB saves
- ✅ UI Indicators: Visual feedback for staged content
- ✅ Parent Integration: Save/Discard flow handles all staged content
- ✅ Type Safety: Shared types include staging fields (
_hintsStaged,_stagedHints)
AI-powered chat assistant for wilderness building, running on port 8002 as a separate Docker container.
- Service: FastAPI application with PydanticAI
- Port: 8002 (uses MCP on 8001 as single contact surface)
- Location:
/apps/agent/ - Status: DEPLOYED AND RUNNING - MCP-only refactor complete
- Data Flow: Chat Agent (8002) → MCP Server (8001) → Backend (8000) → MySQL
- Natural language region and path creation
- AI-powered description generation via MCP
- Dynamic hint generation for weather/time variations
- Terrain analysis and map generation
- Session management for conversation history
- MCP-only architecture - single contact surface
- create_region - Create regions with coordinates (integer types)
- create_path - Create paths/roads/rivers
- generate_region_description - AI-powered descriptions
- generate_hints_from_description - Dynamic weather/time variations
- analyze_terrain_at_coordinates - Real-time terrain data
- analyze_complete_terrain_map - Area analysis with overlays
- find_zone_entrances - Locate zone connections
- find_static_wilderness_room - Find static content
- generate_wilderness_map - Create area maps
- search_regions - Search by location/type/name
- search_by_coordinates - Find regions/paths at coordinates
- store_region_hints - Save generated hints
- get_region_hints - Retrieve existing hints
POST /api/chat/message- Send message and get responseGET /api/chat/history- Get conversation historyPOST /api/session/- Create new sessionGET /health/- Health check
# Test deployed agent
SESSION_ID=$(curl -X POST http://localhost:8002/api/session/ -H "Content-Type: application/json" -d '{}' | jq -r .session_id)
curl -X POST http://localhost:8002/api/chat/message \
-H "Content-Type: application/json" \
-d "{\"message\": \"Help me create a forest region\", \"session_id\": \"$SESSION_ID\"}" | jq .
# Docker logs
docker logs -f wildeditor-chat-agentAI_PROVIDER- "openai" or "deepseek" (defaults to openai)OPENAI_API_KEY- OpenAI API keyDEEPSEEK_API_KEY- DeepSeek API key (fallback)OPENAI_MODEL- Model name (defaults to gpt-4-turbo)DEEPSEEK_MODEL- DeepSeek model (defaults to deepseek-chat)WILDEDITOR_MCP_KEY- MCP server authentication
- Deploy chat agent with Docker
- Fix pydantic_ai compatibility issues
- Add DeepSeek as fallback provider
- Refactor to MCP-only architecture (FULLY COMPLETE)
- Remove BackendClient entirely
- Add create_path tool
- Fix API endpoint paths
- Fix MCP error handling ("error": null issue)
- Deploy to production on port 8002
- COMPLETE: Chat Assistant UI with draggable/resizable window
- COMPLETE: Markdown rendering with syntax highlighting
- COMPLETE: Spatial intelligence capabilities for organic regions
- COMPLETE: Frontend integration with view control actions
- Add region type name mapping (forest→4, etc.)
- Implement WebSocket for real-time chat
- Add streaming response support
- Configure Redis for session persistence
The chat assistant now provides a complete user experience with:
- Draggable Window: Full drag support with multi-monitor compatibility
- Resizable Interface: Min/max constraints with localStorage persistence
- Markdown Rendering: Full markdown support with syntax highlighting
- Position Memory: Window position and size restored between sessions
- Spatial Intelligence: Analyzes areas between regions and finds empty spaces
- Organic Region Creation: Generates natural borders using polar coordinate algorithms
- Path Connection: Creates curved paths connecting multiple regions with terrain analysis
- Overlap Prevention: Checks for geographic region overlaps before creation
- View Control: Centers map view and selects items via chat commands
Chat Assistant (Port 5173) → Chat Agent (Port 8002) → MCP Server (Port 8001) → Backend (Port 8000)
The assistant can now handle natural language requests like:
- "Create a forest region between the lake and mountain"
- "Make a river from the highlands to the ocean"
- "Find empty space near the village for a new region"
- "Connect these three regions with a dirt road"
- "Show me the terrain around coordinates (100, 200)"
- Terrain-Aware: Uses elevation data for realistic boundaries
- Natural Borders: 8-12 points with organic curves (no straight lines)
- Multi-Region Paths: Connects several regions with optimal routing
- Geographic Overlap Detection: Prevents conflicting geographic regions
- Content Staging: All AI-generated content is staged for user review before saving
See /apps/agent/TODO.md for detailed status and next steps.
The Region Hints system provides AI-generated dynamic descriptions for wilderness regions. Hints are categorized descriptive elements that can be combined based on weather, time of day, and season to create immersive, contextual descriptions.
- region_hints: Stores categorized hints with weather/time/season conditions
- Categories: atmosphere, fauna, flora, geography, weather_influence, resources, landmarks, sounds, scents, seasonal_changes, time_of_day, mystical
- Weather conditions: MySQL SET type ('clear', 'cloudy', 'rainy', 'stormy', 'lightning')
- Weight ranges: 0-2 (0 = never, 1 = normal, 2 = double probability)
- Note: Column is
agent_idnotai_agent_idin production
- region_profiles: Stores overall theme and mood for regions
- hint_usage_log: Optional analytics tracking
GET /api/regions/{vnum}/hints- List all hints for a regionPOST /api/regions/{vnum}/hints- Create hints (batch)PUT /api/regions/{vnum}/hints/{id}- Update a specific hintDELETE /api/regions/{vnum}/hints/{id}- Delete a specific hintDELETE /api/regions/{vnum}/hints- Delete all hints for a regionPOST /api/regions/{vnum}/hints/generate- Generate hints from description (uses MCP)
- RegionTabbedPanel: Main component with Hints tab for viewing/managing hints
- HintEditor: Modal component for creating/editing individual hints
- Weights displayed as percentages (0-200%) in UI
- Converted to decimals (0.0-2.0) when saving
- Supports seasonal and time-of-day weight multipliers
- Issue: Database stores weights as 0-2, frontend was validating for 0-1
- Solution: Updated validation to accept 0-2 range in
schemas/region_hints.py
- Issue: MySQL SET type needs conversion from string to array
- Solution: Custom validation in
RegionHintResponse.model_validate()splits comma-separated string
- Issue: Model used
ai_agent_idbut database hasagent_id - Solution: Updated models and schemas to use
agent_id
- Issue: Frontend called
getHintsbut method isgetRegionHints - Solution: Fixed method name in
RegionTabbedPanel.tsx
The system integrates with Model Context Protocol (MCP) for AI-powered hint generation:
- Endpoint:
/api/mcp/generate-hints - Uses DeepSeek or fallback AI models
- Generates categorized hints from region descriptions
- Validates weather conditions against allowed set
# Check if hints tables exist in database
cd apps/backend/src
python3 check_hints_tables.py
# Run migrations to create tables (if needed)
mysql -h localhost -u luminari_mud -p'password' luminari_mudprod < apps/backend/migrations/002_add_region_hints_tables.sql- Always run linter before committing:
npm run lint - Test locally first: Backend runs on port 8000, frontend on 5173
- CORS errors with 500 status: Usually means backend is crashing - check detailed error messages
- Weight ranges: 0-2 throughout the system (not 0-1)