# Architecture ## System Overview **Microservices Architecture** - Three independent, deployable components: ``` ┌─────────────────────────────────────────────────────────────┐ │ Frontend Layer (2 options) │ │ │ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │ │ Public Web │ │ Godot Client │ │ │ │ (Flask + Jinja2) │ │ (Native Game) │ │ │ │ │ │ │ │ │ │ - Browser-based UI │ │ - Desktop/Mobile │ │ │ │ - HTMX interactions │ │ - Cross-platform │ │ │ │ - Server-side │ │ - GDScript │ │ │ │ rendering │ │ │ │ │ └──────────────────────┘ └──────────────────────┘ │ │ │ │ │ │ └──────────────┬───────────────┘ │ │ │ │ │ │ HTTP/REST │ └──────────────────────────┼─────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ API Backend (Flask) │ │ │ │ Single Source of Truth - All Business Logic │ │ - Authentication (via Appwrite) │ │ - Game logic & mechanics │ │ - Character management │ │ - Combat system │ │ - Marketplace transactions │ │ - Session management │ │ - Data models & validation │ │ - AI orchestration │ └─────────────────────────────────────────────────────────────┘ │ ┌───────────────────┼──────────────────┐ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Appwrite │ │ Redis + RQ │ │ AI APIs │ │ │ │ │ │ │ │ - Auth │ │ - Job Queue │ │ - Replicate │ │ - Database │ │ - Caching │ │ - Anthropic │ │ - Storage │ │ - Sessions │ │ │ │ - Realtime │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ ``` ### Component Responsibilities **`/api` - API Backend (Port 5000)** - **Role:** Single source of truth, all business logic - **Tech:** Flask REST API + Appwrite + RQ + Redis - **Contains:** Models, services, game logic, AI integration - **Deployment:** Independent with own venv, config, tests - **Location:** `/api` directory **`/public_web` - Web Frontend (Port 5001)** - **Role:** Thin UI layer for browsers - **Tech:** Flask + Jinja2 + HTMX - **Contains:** Views, templates, static assets - **Communication:** HTTP requests to API backend - **Deployment:** Independent with own venv, config - **Location:** `/public_web` directory **`/godot_client` - Game Client** - **Role:** Native cross-platform game client - **Tech:** Godot 4.5 + GDScript - **Contains:** UI, scenes, client-side logic - **Communication:** HTTP requests to API backend - **Deployment:** Exports to Desktop/Mobile/Web - **Location:** `/godot_client` directory --- ## Core Design Principles 1. **Microservices Architecture:** Three independent, deployable components (API, Web, Godot) 2. **API as Single Source of Truth:** All business logic centralized in API backend 3. **AI-Driven Narrative:** Claude models generate story, NPC dialogue, combat descriptions 4. **Code-Driven Mechanics:** All game mechanics (damage, stats, effects) use deterministic formulas (JRPG-style) 5. **Turn-Based Gameplay:** Classic D&D style, not real-time 6. **Scalable Architecture:** Independent services, horizontal scaling ready 7. **Security First:** Developer is cybersecurity senior engineer/director - security is paramount 8. **Monetization:** Tiered subscription model with free tier --- ## Tech Stack ### API Backend (`/api`) | Component | Technology | Purpose | |-----------|-----------|---------| | **Framework** | Flask 3.x | REST API framework | | **Authentication** | Appwrite Auth | User management, session tokens | | **Database** | Appwrite Database | NoSQL document storage | | **Realtime** | Appwrite Realtime | WebSocket connections for multiplayer | | **Storage** | Appwrite Storage | User assets, logs | | **Job Queue** | RQ (Redis Queue) | Async AI calls, background tasks | | **Caching** | Redis | Session data, rate limiting | | **AI (Free)** | Replicate API | Free tier users (Llama 3 70B) | | **AI (Paid)** | Anthropic Claude | Paid tier users (Haiku/Sonnet) | | **Data Models** | Dataclasses | Typed domain models | | **Logging** | Structlog | Structured logging | | **Testing** | Pytest | Unit and integration tests | | **WSGI Server** | Gunicorn | Production WSGI server | ### Web Frontend (`/public_web`) | Component | Technology | Purpose | |-----------|-----------|---------| | **Framework** | Flask 3.x | Lightweight web server | | **Templates** | Jinja2 | Server-side HTML rendering | | **UI Enhancement** | HTMX | Dynamic updates without heavy JS | | **Styling** | Vanilla CSS | Custom dark theme | | **API Client** | Python requests | HTTP calls to API backend | | **Logging** | Structlog | Structured logging | | **WSGI Server** | Gunicorn | Production WSGI server | ### Godot Client (`/godot_client`) | Component | Technology | Purpose | |-----------|-----------|---------| | **Engine** | Godot 4.5 | Cross-platform game engine | | **Language** | GDScript | Game logic and UI | | **HTTP Client** | HTTPClient singleton | API communication | | **State Management** | StateManager singleton | Global game state | | **Fonts** | Cinzel + Lato | Display and body fonts | | **Exports** | Desktop/Mobile/Web | Multi-platform deployment | ### Shared Infrastructure | Component | Technology | Purpose | |-----------|-----------|---------| | **Configuration** | YAML files | Environment-specific settings | | **Secrets** | .env files | API keys, credentials | | **Deployment** | Docker | Containerized services | | **Version Control** | Git | Source code management | --- ## AI Model Strategy ### Model Selection Philosophy - Use **Anthropic Claude models** for all paid tier interactions - Use **Replicate free models** only for free tier users - Model selection is **per-call based**, determined by context importance and user tier ### Model Tiers | Tier | Provider | Model | Max Tokens | Temperature | Use Cases | |------|----------|-------|------------|-------------|-----------| | **FREE** | Replicate | meta-llama-3-70b-instruct | 256 | 0.7 | Free tier users only | | **STANDARD** | Anthropic | claude-3-5-haiku-20241022 | 512 | 0.8 | Most interactions (paid) | | **PREMIUM** | Anthropic | claude-3-5-sonnet-20241022 | 1024 | 0.9 | Important moments (paid) | ### Context-Based Model Selection | Context | Model Tier | Examples | |---------|-----------|----------| | Simple acknowledgment | FREE | "You enter the room", "Item picked up" | | Item description | FREE | Basic item lore | | NPC dialogue | STANDARD | Merchant conversations, quest givers | | Combat narrative | STANDARD | Regular combat descriptions | | Story progression | PREMIUM | Major plot developments | | Boss encounter | PREMIUM | Epic boss fight narratives | | Character death | PREMIUM | Dramatic death scenes | **Note:** Free tier users always get FREE tier models regardless of context. ### Prompt Management - Use **Jinja2 templates** for all AI prompts - Enable easy data injection and maintainability - Templates stored in `app/ai/prompt_templates.py` --- ## Appwrite Collections ### users Handled automatically by Appwrite Auth. ### characters | Field | Type | Description | |-------|------|-------------| | `$id` | String | Unique ID | | `userId` | String | Owner user ID | | `characterData` | JSON String | Serialized Character dataclass | | `created_at` | ISO Timestamp | Creation time | | `updated_at` | ISO Timestamp | Last update | | `is_active` | Boolean | Active character flag | ### game_sessions | Field | Type | Description | |-------|------|-------------| | `$id` | String | Session ID | | `party_member_ids` | Array[String] | Character IDs in party | | `config` | Object | Session configuration | | `combat_encounter` | JSON String | Current combat or null | | `conversation_history` | Array[Object] | Turn-by-turn history | | `game_state` | Object | Current location, quests, events | | `turn_order` | Array[String] | Character IDs in turn order | | `current_turn` | Integer | Index in turn_order | | `turn_number` | Integer | Global turn counter | | `created_at` | ISO Timestamp | Session start | | `last_activity` | ISO Timestamp | Last action | | `status` | String | active, completed, timeout | **Session Config Structure:** ```json { "min_players": 2, "timeout_minutes": 30, "auto_save_interval": 5 } ``` **Conversation History Entry:** ```json { "turn": 1, "character_id": "char_id_1", "character_name": "Aragorn", "action": "I search for traps", "dm_response": "You notice...", "combat_log": [] } ``` ### marketplace_listings | Field | Type | Description | |-------|------|-------------| | `$id` | String | Listing ID | | `seller_id` | String | User ID | | `character_id` | String | Character ID | | `item_data` | Object | Full item details | | `listing_type` | String | "auction" or "fixed_price" | | `price` | Integer | For fixed_price | | `starting_bid` | Integer | For auction | | `current_bid` | Integer | For auction | | `buyout_price` | Integer | Optional instant buy | | `bids` | Array[Object] | Bid history | | `auction_end` | ISO Timestamp | For auction | | `status` | String | active, sold, expired, removed | | `created_at` | ISO Timestamp | Listing creation | ### transactions | Field | Type | Description | |-------|------|-------------| | `$id` | String | Transaction ID | | `buyer_id` | String | User ID | | `seller_id` | String | User ID | | `listing_id` | String | Listing ID | | `item_data` | Object | Item details | | `price` | Integer | Final price | | `timestamp` | ISO Timestamp | Transaction time | | `transaction_type` | String | marketplace_sale, shop_purchase, etc. | --- ## Project Structure **Repository Root:** ``` /coc ├── api/ # API Backend Component ├── public_web/ # Web Frontend Component ├── godot_client/ # Godot Game Client Component ├── docs/ # Project-wide documentation ├── CLAUDE.md # Development guidelines └── README.md # Project overview ``` ### API Backend (`/api`) **Single source of truth - All business logic** ``` api/ ├── app/ │ ├── __init__.py # Flask app factory │ ├── config.py # Configuration management │ ├── models/ # Data models (dataclasses) │ │ ├── __init__.py │ │ ├── enums.py # All enum types │ │ ├── stats.py # Stats dataclass │ │ ├── effects.py # Effect dataclass │ │ ├── abilities.py # Ability dataclass │ │ ├── items.py # Item dataclass │ │ ├── skills.py # SkillNode, SkillTree, PlayerClass │ │ ├── origins.py # Origin dataclass │ │ ├── character.py # Character with get_effective_stats() │ │ ├── combat.py # Combatant, CombatEncounter │ │ ├── session.py # GameSession, SessionConfig │ │ └── marketplace.py # Marketplace models │ ├── api/ # REST API endpoints │ │ ├── __init__.py │ │ ├── health.py # Health check │ │ ├── auth.py # Authentication endpoints │ │ ├── characters.py # Character CRUD │ │ ├── sessions.py # Session management (TODO) │ │ ├── combat.py # Combat actions (TODO) │ │ ├── marketplace.py # Marketplace operations (TODO) │ │ └── shop.py # NPC shop (TODO) │ ├── game_logic/ # Game mechanics │ │ ├── __init__.py │ │ ├── combat_engine.py # Combat calculations (TODO) │ │ ├── damage_calculator.py # Damage formulas (TODO) │ │ ├── effect_processor.py # Effect tick processing (TODO) │ │ ├── skill_manager.py # Skill unlock logic (TODO) │ │ └── loot_generator.py # Random loot generation (TODO) │ ├── ai/ # AI integration │ │ ├── __init__.py │ │ ├── ai_client.py # Replicate + Anthropic clients (TODO) │ │ ├── model_selector.py # Model tier selection (TODO) │ │ ├── prompt_templates.py # Jinja2 prompt templates (TODO) │ │ └── narrative_generator.py # AI narrative wrapper (TODO) │ ├── tasks/ # Background jobs (RQ) │ │ ├── __init__.py │ │ ├── ai_tasks.py # RQ jobs for AI calls (TODO) │ │ ├── combat_tasks.py # Async combat processing (TODO) │ │ └── marketplace_tasks.py # Auction processing (TODO) │ ├── services/ # Business logic & integrations │ │ ├── __init__.py │ │ ├── appwrite_service.py # Appwrite SDK wrapper │ │ ├── database_service.py # Database operations │ │ ├── database_init.py # Database initialization │ │ ├── character_service.py # Character management │ │ ├── class_loader.py # Load classes from YAML │ │ └── origin_service.py # Load origins from YAML │ ├── utils/ # Utilities │ │ ├── __init__.py │ │ ├── logging.py # Structlog setup │ │ ├── response.py # Standardized API responses │ │ └── auth.py # Auth decorators │ └── data/ # Game data (YAML) │ ├── abilities/ # Ability definitions │ ├── classes/ # Character class definitions │ ├── items/ # Item definitions (TODO) │ └── origins.yaml # Origin definitions ├── config/ # Environment configs │ ├── development.yaml # Dev environment settings │ └── production.yaml # Production settings ├── tests/ # Pytest test suite │ ├── __init__.py │ ├── test_character.py │ ├── test_stats.py │ ├── test_effects.py │ ├── test_combat_simulation.py │ ├── test_class_loader.py │ ├── test_origin_service.py │ ├── test_character_service.py │ └── test_api_characters_integration.py ├── scripts/ # Utility scripts │ ├── init_database.py # Database initialization │ ├── setup.sh # Project setup │ └── README.md ├── logs/ # Application logs │ └── app.log ├── docs/ # API documentation │ ├── API_REFERENCE.md # API endpoint docs │ ├── API_TESTING.md # API testing guide │ ├── DATA_MODELS.md # Data model documentation │ ├── GAME_SYSTEMS.md # Game mechanics docs │ └── APPWRITE_SETUP.md # Database setup guide ├── requirements.txt # Python dependencies (full stack) ├── wsgi.py # WSGI entry point ├── docker-compose.yml # Redis service ├── .env.example # Environment variable template └── README.md # API backend README ``` ### Web Frontend (`/public_web`) **Thin UI layer - Makes HTTP requests to API** ``` public_web/ ├── app/ │ ├── __init__.py # Flask app factory │ ├── config.py # Configuration loader │ ├── views/ # View blueprints (Flask routes) │ │ ├── __init__.py │ │ ├── auth_views.py # Auth pages (login, register, etc.) │ │ └── character_views.py # Character pages │ ├── services/ # (Stub) API client services │ │ ├── __init__.py # TODO: Refactor to HTTP client │ │ ├── character_service.py # Stub (raises NotImplementedError) │ │ ├── class_loader.py # Stub (raises NotImplementedError) │ │ └── origin_service.py # Stub (raises NotImplementedError) │ └── utils/ # Utilities │ ├── __init__.py │ ├── logging.py # Structlog setup │ └── auth.py # Auth helpers (stubs, need refactor) ├── templates/ # Jinja2 HTML templates │ ├── base.html # Base layout │ ├── auth/ # Authentication pages │ │ ├── login.html │ │ ├── register.html │ │ ├── forgot_password.html │ │ ├── reset_password.html │ │ └── verify_email.html │ └── character/ # Character pages │ ├── list.html # Character list │ ├── detail.html # Character detail │ ├── create_origin.html # Creation step 1 │ ├── create_class.html # Creation step 2 │ ├── create_customize.html # Creation step 3 │ └── create_confirm.html # Creation step 4 ├── static/ # CSS, JS, images │ └── css/ │ └── main.css # Main stylesheet ├── config/ # Web frontend configs │ ├── development.yaml # Dev settings (API URL, etc.) │ └── production.yaml # Production settings ├── logs/ # Application logs ├── docs/ # Frontend documentation ├── requirements.txt # Python dependencies (minimal) ├── wsgi.py # WSGI entry point ├── .env.example # Environment template └── README.md # Web frontend README ``` **Known Technical Debt:** - Views currently import stub services that raise `NotImplementedError` - Need to refactor views to make HTTP requests to API backend - Auth helpers need to validate sessions via API - See `/public_web/README.md` for details ### Godot Client (`/godot_client`) **Native cross-platform game client** ``` godot_client/ ├── project.godot # Godot project configuration ├── scenes/ # Godot scene files (.tscn) │ ├── main.tscn # Entry point │ ├── auth/ # Authentication scenes │ │ └── login.tscn │ ├── character/ # Character scenes │ ├── combat/ # Combat scenes │ ├── world/ # World exploration scenes │ └── components/ # Reusable UI components ├── scripts/ # GDScript code │ ├── main.gd # Main scene controller │ ├── services/ # Singleton autoloads │ │ ├── settings.gd # Settings management │ │ ├── http_client.gd # HTTP client for API calls │ │ └── state_manager.gd # Global state management │ ├── models/ # Data models │ │ └── api_response.gd # API response wrapper │ ├── components/ # Component scripts │ │ ├── form_field.gd # Form input component │ │ ├── card.gd # Card container │ │ └── custom_button.gd # Styled button │ └── utils/ # Helper utilities │ └── theme_colors.gd # Color constants ├── assets/ # Game assets │ ├── fonts/ # Cinzel + Lato fonts │ ├── themes/ # UI theme files │ └── ui/ # UI assets ├── docs/ # Godot client documentation │ ├── ARCHITECTURE.md # Client architecture │ ├── GETTING_STARTED.md # Setup guide │ ├── EXPORT.md # Export instructions │ └── THEME_SETUP.md # Theming guide ├── ARCHITECTURE.md # Architecture overview ├── README.md # Setup and usage └── EXPORT.md # Platform export guide ``` --- ## RQ Job Processing ### Job Types | Queue | Job Function | Purpose | |-------|--------------|---------| | **ai_tasks** | `generate_dm_response()` | Generate narrative responses | | | `generate_npc_dialogue()` | NPC conversations | | | `narrate_combat_action()` | Combat descriptions | | **combat_tasks** | `process_combat_round()` | Execute combat turn | | | `finalize_combat()` | Handle combat end | | **marketplace_tasks** | `process_ended_auctions()` | Periodic auction cleanup | | | `cleanup_old_session_logs()` | Periodic log cleanup | ### Worker Configuration **Start RQ workers:** ```bash # Single worker for all queues rq worker ai_tasks combat_tasks marketplace_tasks --url redis://localhost:6379 # Or separate workers rq worker ai_tasks --url redis://localhost:6379 rq worker combat_tasks --url redis://localhost:6379 rq worker marketplace_tasks --url redis://localhost:6379 ``` ### Job Flow 1. User takes action in game 2. Action queued to RQ with job ID 3. API returns 202 Accepted with job ID 4. Worker processes job asynchronously 5. Worker updates Appwrite document 6. Appwrite Realtime notifies all clients 7. UI updates automatically --- ## Realtime Synchronization **Use Appwrite Realtime for WebSocket connections:** Frontend subscribes to session updates and receives automatic notifications when game state changes. **Benefits:** - No polling required - Instant updates for all party members - Built-in connection management - Automatic reconnection --- ## Subscription Tiers | Tier | Price | AI Calls/Day | AI Model | Marketplace | Log Retention | Max Chars | Party Size | |------|-------|--------------|----------|-------------|---------------|-----------|------------| | **FREE** | $0 | 50 | Replicate | ✗ | 7 days | 1 | Solo | | **BASIC** | $4.99 | 200 | Haiku | ✗ | 14 days | 3 | 2 | | **PREMIUM** | $9.99 | 1000 | Sonnet | ✓ | 30 days | 10 | 6 | | **ELITE** | $19.99 | Unlimited | Sonnet | ✓+ | 90 days | Unlimited | 10 | **ELITE Perks:** - Priority marketplace listings - Early access to new classes - Exclusive items --- ## Security Architecture ### Authentication & Authorization - Appwrite Auth handles user authentication - HTTP-only cookies (`coc_session`) for session storage - Prevents XSS attacks (JavaScript cannot access) - HTTPS only in production (Secure flag) - SameSite=Lax for CSRF protection - 24-hour sessions (30 days with "remember me") - Email verification required before login - Password reset via email flow - Auth decorators for protected routes: - `@require_auth` - Enforce authentication - `@require_tier(tier)` - Enforce minimum subscription tier - `@require_email_verified` - Enforce verified email - User tier system (Free/Basic/Premium/Elite) - Session validation on every protected API call - User ID verification (users can only access their own data) ### Input Validation - Validate all JSON payloads against schemas - Sanitize user inputs (character names, chat messages) - Prevent injection attacks ### Rate Limiting - AI endpoint limits based on subscription tier - Marketplace actions (max listings per day) - Combat actions (prevent spam/automation) - Use Flask-Limiter with Redis backend ### API Security - CORS properly configured (only allow frontend domain) - API keys stored in environment variables - Appwrite permissions set correctly on all collections - HTTPS only in production ### Cost Control (AI) - Daily limits on AI calls per tier - Max tokens per request type - Cost logging for analytics and alerts - Graceful degradation if limits exceeded ### Data Protection | Resource | Read Access | Write Access | |----------|-------------|--------------| | **Characters** | Owner only | Owner only | | **Sessions** | Party members | Active player | | **Marketplace** | All users | Listing owner | | **Transactions** | Buyer + Seller | System only | --- ## Why These Technologies? ### Flask over FastAPI - Team familiarity with Flask - Async handled by RQ (don't need FastAPI's native async) - Mature ecosystem for templates (Jinja2) - Can migrate specific endpoints later if needed ### RQ over Celery - Simpler setup and configuration - Adequate for current scale - Easier debugging - Redis already required for caching ### Appwrite - Reduces infrastructure overhead - Built-in auth, database, storage, realtime - Handles scaling of data layer - Real-time WebSocket support out of box - Self-hosted option available if needed later ### Dataclasses over ORM - Flexibility in data structure (easy to change) - No database migration headaches - JSON storage in Appwrite is schema-flexible - Easier to serialize/deserialize - Performance (no ORM overhead) ### Turn-Based - Simpler AI prompt construction - Better for multiplayer coordination - Classic D&D feel - Easier to balance than real-time - Less server load (no constant state updates) ### Microservices Architecture - **Independent Deployment:** Each component can be updated/scaled separately - **Technology Flexibility:** Can use different tech stacks per component (Flask + Godot) - **Team Scalability:** Different teams can work on different components - **Fault Isolation:** Failures in one component don't crash entire system - **API as Contract:** Clear interface between frontend and backend --- ## Microservices Communication ### API-First Design All frontends communicate with the API backend exclusively via HTTP/REST: ``` ┌─────────────┐ │ Public Web │──┐ └─────────────┘ │ │ HTTP/REST ┌─────────────┐ │ (JSON) │ Godot Client│──┼──────────► ┌──────────────┐ └─────────────┘ │ │ API Backend │ │ │ (Port 5000) │ │ └──────────────┘ │ Other │ Clients │ (Future) ────┘ ``` ### Communication Patterns **1. Request/Response (Synchronous)** - Standard CRUD operations - Character creation, updates - Authentication - Data retrieval **Example:** ``` POST /api/v1/characters { "name": "Aragorn", "class_id": "vanguard", "origin_id": "noble_exile" } → API processes request → Returns character data Response: { "app": "Code of Conquest", "status": 200, "result": { character_data }, "error": null } ``` **2. Job Queue (Asynchronous)** - AI narrative generation - Combat processing - Long-running operations **Example:** ``` POST /api/v1/sessions/{id}/action { "action": "I search the ancient library" } → API queues job to RQ → Returns job ID immediately Response: { "status": 202, "result": { "job_id": "abc123", "status": "queued" } } → Worker processes AI call → Updates Appwrite document → Appwrite Realtime notifies clients ``` **3. Real-Time (WebSocket via Appwrite)** - Multiplayer session updates - Combat state changes - Party member actions **Example:** ```javascript // Subscribe to session updates appwrite.subscribe('sessions.{sessionId}', callback); // When another player acts: → Worker updates session in Appwrite → Appwrite broadcasts to all subscribers → All clients update UI automatically ``` ### API Endpoints Structure ``` /api/v1/ ├── health # Health check ├── auth/ # Authentication │ ├── login │ ├── register │ ├── logout │ └── reset-password ├── characters/ # Character management │ ├── GET / # List characters │ ├── POST / # Create character │ ├── GET /{id} # Get character │ ├── PUT /{id} # Update character │ └── DELETE /{id} # Delete character ├── sessions/ # Game sessions (TODO) │ ├── POST / # Create session │ ├── GET /{id} # Get session │ └── POST /{id}/action # Take action ├── combat/ # Combat system (TODO) │ └── POST /sessions/{id}/combat/action ├── marketplace/ # Marketplace (TODO) │ ├── GET /listings │ └── POST /listings └── shop/ # NPC shop (TODO) └── GET /items ``` ### Frontend Responsibilities **API Backend (`/api`):** - ✅ All business logic - ✅ Data validation - ✅ Database operations - ✅ Authentication & authorization - ✅ Game mechanics calculations - ✅ AI orchestration **Web Frontend (`/public_web`):** - ❌ No business logic - ✅ Render HTML templates - ✅ Form validation (UI only) - ✅ Make HTTP requests to API - ✅ Display API responses - ⚠️ **Current:** Has stub services (needs refactoring) **Godot Client (`/godot_client`):** - ❌ No business logic - ✅ Render game UI - ✅ Handle user input - ✅ Make HTTP requests to API - ✅ Display API responses - ✅ Client-side animations/effects --- ## Deployment Architecture ### Development Environment ``` ┌────────────────────┐ │ Developer Machine │ ├────────────────────┤ │ │ │ API Backend │ ← Port 5000 │ (Flask dev server)│ │ │ │ Web Frontend │ ← Port 5001 │ (Flask dev server)│ │ │ │ Godot Editor │ ← F5 to test │ │ │ Redis (Docker) │ ← Port 6379 │ │ └────────────────────┘ │ │ API calls ▼ ┌──────────────┐ │ Appwrite │ │ (Cloud) │ └──────────────┘ ``` **Commands:** ```bash # Terminal 1: API Backend cd api source venv/bin/activate python wsgi.py # → http://localhost:5000 # Terminal 2: Web Frontend cd public_web source venv/bin/activate python wsgi.py # → http://localhost:5001 # Terminal 3: Redis cd api docker-compose up # Terminal 4: RQ Worker (optional) cd api source venv/bin/activate rq worker ai_tasks --url redis://localhost:6379 # Godot: Open project and press F5 ``` ### Production Environment ``` ┌──────────────────────────────────────┐ │ Load Balancer / CDN │ └────────────┬─────────────────────────┘ │ ┌──────┴──────┐ │ │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ Web │ │ Web │ ← Port 8080 (internal) │ Frontend │ │ Frontend │ │(Gunicorn)│ │(Gunicorn)│ └────┬─────┘ └────┬─────┘ │ │ │ HTTP Requests └──────┬──────┘ ▼ ┌──────────┐ │ API │ ← Port 5000 (internal) │ Backend │ │(Gunicorn)│ └────┬─────┘ │ ┌────┴────┬──────────┬──────────┐ ▼ ▼ ▼ ▼ ┌──────────┐ ┌─────┐ ┌────────┐ ┌────────┐ │ Appwrite │ │Redis│ │ RQ │ │ AI │ │ │ │ │ │Workers │ │ APIs │ └──────────┘ └─────┘ └────────┘ └────────┘ ``` **Deployment Strategy:** - Each component containerized with Docker - Independent scaling (more web servers if needed) - API backend as single deployment (multiple workers via Gunicorn) - Godot client exported to native apps (distributed separately) ### Environment Variables **API Backend:** ``` FLASK_ENV=production APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1 APPWRITE_PROJECT_ID=... APPWRITE_API_KEY=... APPWRITE_DATABASE_ID=... ANTHROPIC_API_KEY=... REPLICATE_API_TOKEN=... REDIS_URL=redis://redis:6379 SECRET_KEY=... ``` **Web Frontend:** ``` FLASK_ENV=production SECRET_KEY=... API_BASE_URL=https://api.codeofconquest.com ``` **Godot Client:** ```gdscript # In settings.gd or environment config var api_base_url = "https://api.codeofconquest.com" ```