# 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:**
- **[README.md](README.md)** - Setup and usage guide
- **[docs/TEMPLATES.md](docs/TEMPLATES.md)** - Template structure and conventions
- **[docs/HTMX_PATTERNS.md](docs/HTMX_PATTERNS.md)** - HTMX integration patterns
- **[docs/TESTING.md](docs/TESTING.md)** - Manual testing guide
- **[docs/MULTIPLAYER.md](docs/MULTIPLAYER.md)** - Multiplayer UI implementation

**Project-Wide Documentation:**
- **[../docs/ARCHITECTURE.md](../docs/ARCHITECTURE.md)** - System architecture overview
- **[../api/docs/API_REFERENCE.md](../api/docs/API_REFERENCE.md)** - API endpoints to call
- **[../docs/DEPLOYMENT.md](../docs/DEPLOYMENT.md)** - Deployment guide
- **[../docs/WEB_VS_CLIENT_SYSTEMS.md](../docs/WEB_VS_CLIENT_SYSTEMS.md)** - Feature distribution between frontends

**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):**
```python
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`):**
```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:**
```html
{% 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:**
```html
<!-- 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:**
```css
: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:**
```yaml
# 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:**
```python
@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:**
```bash
# 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:**
- Python 3.11+
- API backend running at http://localhost:5000

**Setup:**
```bash
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:**
```bash
source venv/bin/activate
export FLASK_ENV=development
python wsgi.py  # → http://localhost:5001
```

### Production

**Run with Gunicorn:**
```bash
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
