Files
2025-11-24 23:10:55 -06:00

13 KiB

CLAUDE.md - Public Web Frontend

Service Overview

Public Web Frontend for Code of Conquest - Browser-based UI using Flask + Jinja2 + HTMX.

Tech Stack: Flask + Jinja2 + HTMX + Vanilla CSS Port: 5001 (development), 8080 (production) Location: /public_web


Architecture Role

This web frontend is a thin UI layer that makes HTTP requests to the API backend:

  • Render HTML templates (Jinja2)
  • Form validation (UI only)
  • Make HTTP requests to API backend
  • Display API responses
  • Handle user input

What this service does NOT do:

  • No business logic (all in /api)
  • No direct database access (use API)
  • No direct Appwrite calls (use API)
  • No game mechanics calculations (use API)

Communication:

User Browser → Public Web (views) → HTTP Request → API Backend
                    ↑                                   ↓
                    ←─────────── HTTP Response ─────────┘

Documentation Index

Web Frontend Documentation:

Project-Wide Documentation:

Documentation Guidelines:

  • Place all public_web service documentation in /public_web/docs/
  • Each microservice maintains its own documentation
  • Do NOT add public_web-specific docs to /docs/ (main repo docs are for cross-service architecture only)

Development Guidelines

Project Structure

public_web/
├── app/                   # Application code
│   ├── views/            # View blueprints (Flask routes)
│   └── utils/            # Utilities (logging, auth helpers, API client)
├── templates/            # Jinja2 HTML templates
│   ├── auth/            # Authentication pages
│   ├── character/       # Character pages
│   ├── errors/          # Error pages (404, 500)
│   └── base.html        # Base template
├── static/              # CSS, JS, images
│   └── css/            # Stylesheets
├── docs/                # Service-specific documentation
├── config/              # Configuration files
└── README.md            # Setup and usage guide

Coding Standards

Style & Structure

  • Prefer longer, explicit code over compact one-liners
  • Always include docstrings for functions/classes + inline comments
  • Strong typing for view functions (type hints)
  • Keep views simple (delegate to API)

Templates & UI

  • Don't mix large HTML/CSS blocks in Python code
  • Use Jinja2 templates for all HTML rendering
  • Clean CSS, minimal inline styles
  • Readable template logic (avoid complex Python in templates)
  • Use HTMX for dynamic interactions

Logging

  • Use structlog (pip package)
  • Setup logging at app start: logger = structlog.get_logger(__file__)

Preferred Pip Packages

  • Web Server: Flask
  • Templates: Jinja2
  • HTTP Client: Requests
  • Logging: Structlog

View Development Standards

View Functions (Flask Routes):

from flask import Blueprint, render_template, request, redirect, url_for
import requests
from app.config import load_config

character_bp = Blueprint('character', __name__, url_prefix='/characters')

@character_bp.route('/')
def list_characters():
    """
    Display list of user's characters.

    Makes HTTP request to API backend to fetch character data.
    """
    config = load_config()

    # Make API request
    response = requests.get(
        f"{config.api.base_url}/api/v1/characters",
        timeout=config.api.timeout
    )

    if response.status_code == 200:
        data = response.json()
        characters = data.get('result', [])
        return render_template('character/list.html', characters=characters)
    else:
        # Handle error
        return render_template('error.html', message="Failed to load characters"), 500

DO:

  • Make HTTP requests to API backend
  • Pass data to templates
  • Handle errors gracefully
  • Validate form inputs (UI validation only)
  • Redirect to appropriate pages
  • Use flash messages for user feedback

DON'T:

  • No business logic in views
  • No direct database access
  • No game mechanics calculations
  • No complex data transformations (keep it simple)

Template Best Practices

Base Template (templates/base.html):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Code of Conquest{% endblock %}</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
    <script src="https://unpkg.com/htmx.org@1.9.10"></script>
</head>
<body>
    <header>
        {% include 'components/navbar.html' %}
    </header>

    <main>
        {% block content %}{% endblock %}
    </main>

    <footer>
        {% include 'components/footer.html' %}
    </footer>
</body>
</html>

Child Template:

{% extends "base.html" %}

{% block title %}Characters - Code of Conquest{% endblock %}

{% block content %}
<div class="container">
    <h1>Your Characters</h1>

    {% for character in characters %}
    <div class="character-card">
        <h2>{{ character.name }}</h2>
        <p>{{ character.class_name }} - Level {{ character.level }}</p>
    </div>
    {% endfor %}
</div>
{% endblock %}

HTMX Usage:

<!-- Form with HTMX -->
<form hx-post="/api/v1/characters"
      hx-target="#character-list"
      hx-swap="beforeend">
    <input type="text" name="name" placeholder="Character name">
    <button type="submit">Create</button>
</form>

<!-- Result container -->
<div id="character-list"></div>

CSS Standards

Organization:

  • Use BEM naming convention (Block Element Modifier)
  • Group related styles together
  • Use CSS variables for colors/spacing
  • Mobile-first responsive design

Example:

:root {
    --color-primary: #8b5cf6;
    --color-bg: #1a1a1a;
    --color-text: #e5e7eb;
    --spacing-unit: 1rem;
}

.character-card {
    background: var(--color-bg);
    color: var(--color-text);
    padding: calc(var(--spacing-unit) * 2);
    border-radius: 8px;
}

.character-card__title {
    font-size: 1.5rem;
    margin-bottom: var(--spacing-unit);
}

.character-card--highlighted {
    border: 2px solid var(--color-primary);
}

Configuration

  • Environment-specific configs in /config/*.yaml
    • development.yaml - Local dev settings (API URL: http://localhost:5000)
    • production.yaml - Production settings (API URL from env var)
  • .env for secrets (never committed)
  • Typed config loaders using dataclasses

Configuration Structure:

# config/development.yaml
api:
  base_url: "http://localhost:5000"
  timeout: 30
  verify_ssl: false

server:
  host: "0.0.0.0"
  port: 5001
  workers: 1

session:
  lifetime_hours: 24
  cookie_secure: false
  cookie_httponly: true

Error Handling

View Error Handling:

@character_bp.route('/<character_id>')
def character_detail(character_id):
    """Display character details."""
    config = load_config()

    try:
        response = requests.get(
            f"{config.api.base_url}/api/v1/characters/{character_id}",
            timeout=config.api.timeout
        )
        response.raise_for_status()

        data = response.json()
        character = data.get('result')
        return render_template('character/detail.html', character=character)

    except requests.exceptions.Timeout:
        logger.error("API timeout", character_id=character_id)
        return render_template('error.html', message="Request timed out"), 504

    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 404:
            return render_template('error.html', message="Character not found"), 404
        logger.error("API error", status=e.response.status_code)
        return render_template('error.html', message="An error occurred"), 500

    except Exception as e:
        logger.exception("Unexpected error", character_id=character_id)
        return render_template('error.html', message="An unexpected error occurred"), 500

Dependency Management

  • Use requirements.txt in /public_web directory
  • Minimal dependencies (Flask, Jinja2, requests, structlog)
  • Use virtual environment: python3 -m venv venv
  • Activate venv before running: source venv/bin/activate

Testing Standards

Manual Testing:

  • Use the checklist in README.md
  • Test all user flows:
    • Login flow
    • Registration flow
    • Character creation wizard (all 4 steps)
    • Character list and detail views
    • Logout
    • Error handling

Browser Testing:

  • Test in Chrome, Firefox, Safari
  • Test mobile responsive design
  • Test HTMX interactions

Architecture Status

COMPLETE: All views use the APIClient class for HTTP requests to the API backend.

What's Implemented:

  • All views use get_api_client() from app/utils/api_client.py
  • Typed error handling with APIError, APINotFoundError, APITimeoutError, APIAuthenticationError
  • Session cookie forwarding for authentication
  • Proper JSON serialization/deserialization

Minor Improvements (Optional):

  • Auth decorator could re-validate expired API sessions
  • Origin/class validation could use single-item lookups instead of fetching full lists

Workflow for Web Frontend Development

When implementing new pages:

  1. Design the page - Sketch layout, user flow
  2. Create template - Add Jinja2 template in /templates
  3. Create view - Add Flask route in /app/views
  4. Make API calls - Use requests library to call API backend
  5. Handle errors - Graceful error handling with user feedback
  6. Add styles - Update CSS in /static/css
  7. Test manually - Check all user flows

Example Flow:

# 1. Create template
# templates/quest/list.html

# 2. Create view
# app/views/quest_views.py
@quest_bp.route('/')
def list_quests():
    # Make API request
    response = requests.get(f"{api_url}/api/v1/quests")
    quests = response.json()['result']
    return render_template('quest/list.html', quests=quests)

# 3. Register blueprint
# app/__init__.py
from .views.quest_views import quest_bp
app.register_blueprint(quest_bp)

# 4. Add styles
# static/css/quest.css

# 5. Test in browser
# http://localhost:5001/quests

Running the Web Frontend

Development

Prerequisites:

Setup:

cd public_web
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Edit .env with your settings

Run Development Server:

source venv/bin/activate
export FLASK_ENV=development
python wsgi.py  # → http://localhost:5001

Production

Run with Gunicorn:

gunicorn --bind 0.0.0.0:8080 --workers 4 wsgi:app

Environment Variables:

FLASK_ENV=production
SECRET_KEY=...
API_BASE_URL=https://api.codeofconquest.com

Git Standards

Commit Messages:

  • Use conventional commit format: feat:, fix:, docs:, style:, etc.
  • Examples:
    • feat(web): add quest list page
    • fix(views): handle API timeout errors
    • style(css): improve character card layout

Branch Strategy:

  • Branch off dev for features
  • Merge back to dev for testing
  • Promote to master for production

Notes for Claude Code

When working on the web frontend:

  1. Thin client only - No business logic, just UI
  2. Always call API - Use HTTP requests for all data operations
  3. Handle errors gracefully - Show user-friendly error messages
  4. Keep templates clean - Avoid complex logic in Jinja2
  5. Mobile responsive - Design for all screen sizes
  6. HTMX for interactivity - Use HTMX instead of heavy JavaScript
  7. Document refactoring needs - Note any technical debt you encounter

Remember:

  • This is a thin client - all logic lives in the API backend
  • The API serves multiple frontends (this web UI and Godot client)
  • Security validation happens in the API, but do basic UI validation for UX
  • Keep it simple - complicated logic belongs in the API