# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

MyFastHtml is a Python utility library that simplifies FastHTML application development by providing:
- Command management system for client-server interactions
- Bidirectional data binding system
- Predefined authentication pages and routes
- Interactive control helpers
- Session-based instance management

**Tech Stack**: Python 3.12+, FastHTML, HTMX, DaisyUI 5, Tailwind CSS 4

## Development Workflow and Guidelines

### Development Process

**Code must always be testable**. Before writing any code:

1. **Explain available options first** - Present different approaches to solve the problem
2. **Wait for validation** - Ensure mutual understanding of requirements before implementation
3. **No code without approval** - Only proceed after explicit validation

### Collaboration Style

**Ask questions to clarify understanding or suggest alternative approaches:**
- Ask questions **one at a time**
- Wait for complete answer before asking the next question
- Indicate progress: "Question 1/5" if multiple questions are needed
- Never assume - always clarify ambiguities

### Communication

**Conversations**: French or English
**Code, documentation, comments**: English only

### Code Standards

**Follow PEP 8** conventions strictly:
- Variable and function names: `snake_case`
- Explicit, descriptive naming
- **No emojis in code**

**Documentation**:
- Use Google or NumPy docstring format
- Document all public functions and classes
- Include type hints where applicable

### Dependency Management

**When introducing new dependencies:**
- List all external dependencies explicitly
- Propose alternatives using Python standard library when possible
- Explain why each dependency is needed

### Unit Testing with pytest

**Test naming patterns:**
- Passing tests: `test_i_can_xxx` - Tests that should succeed
- Failing tests: `test_i_cannot_xxx` - Edge cases that should raise errors/exceptions

**Test structure:**
- Use **functions**, not classes (unless inheritance is required)
- Before writing tests, **list all planned tests with explanations**
- Wait for validation before implementing tests

**Example:**
```python
def test_i_can_create_command_with_valid_name():
    """Test that a command can be created with a valid name."""
    cmd = Command("valid_name", "description", lambda: None)
    assert cmd.name == "valid_name"

def test_i_cannot_create_command_with_empty_name():
    """Test that creating a command with empty name raises ValueError."""
    with pytest.raises(ValueError):
        Command("", "description", lambda: None)
```

### File Management

**Always specify the full file path** when adding or modifying files:
```
✅ Modifying: src/myfasthtml/core/commands.py
✅ Creating: tests/core/test_new_feature.py
```

### Error Handling

**When errors occur:**
1. **Explain the problem clearly first**
2. **Do not propose a fix immediately**
3. **Wait for validation** that the diagnosis is correct
4. Only then propose solutions

## Available Personas

This project includes specialized personas (slash commands) for different types of work:

### `/developer` - Development Mode (Default)
**Use for:** Writing code, implementing features, fixing bugs

Activates the full development workflow with:
- Options-first approach before coding
- Step-by-step validation
- Strict PEP 8 compliance
- Test-driven development with `test_i_can_xxx` / `test_i_cannot_xxx` patterns

### `/developer-control` - Control Development Mode
**Use for:** Developing UI controls in the controls directory

Specialized mode with rules for:
- Control class inheritance (`MultipleInstance`, `SingleInstance`, `UniqueInstance`)
- Commands class pattern with `BaseCommands`
- State management with `DbObject`
- Rendering with `render()` and `__ft__()`
- Helper usage (`mk.button`, `mk.icon`, `mk.label`)
- Sub-component composition

### `/technical-writer` - Documentation Mode
**Use for:** Writing user-facing documentation

Focused on creating:
- README sections and examples
- Usage guides and tutorials
- Getting started documentation
- Code examples for end users

**Does NOT handle:**
- Docstrings (developer responsibility)
- Internal architecture docs
- CLAUDE.md updates

### `/reset` - Default Claude Code
**Use for:** Return to standard Claude Code behavior without personas

## Development Commands

### Testing
```bash
# Run all tests
pytest

# Run specific test file
pytest tests/core/test_bindings.py

# Run specific test
pytest tests/core/test_bindings.py::test_function_name

# Run tests with verbose output
pytest -v
```

### Cleaning
```bash
# Clean build artifacts and cache
make clean

# Clean package distribution files
make clean-package

# Clean test artifacts (.sesskey, test databases)
make clean-tests

# Clean everything including source artifacts
make clean-all
```

### Package Building
```bash
# Build distribution
python -m build

# Install in development mode
pip install -e .
```

## Architecture Overview

### Core System: Commands

Commands abstract HTMX interactions by encapsulating server-side actions. Located in `src/myfasthtml/core/commands.py`.

**Key classes:**
- `Command`: Base class for all commands with HTMX integration
- `Command`: Standard command that executes a Python callable
- `LambdaCommand`: Inline command for simple operations
- `CommandsManager`: Global registry for command execution

**How commands work:**
1. Create command with action: `cmd = Command("name", "description", callable)`
2. Command auto-registers with `CommandsManager`
3. `cmd.get_htmx_params()` generates HTMX attributes (`hx-post`, `hx-vals`)
4. HTMX posts to `/myfasthtml/commands` route with `c_id`
5. `CommandsManager` routes to correct command's `execute()` method

**Command customization:**
```python
# Change HTMX target and swap
cmd.htmx(target="#result", swap="innerHTML")

# Bind to observable data (disables swap by default)
cmd.bind(data_object)
```

### Core System: Bindings

Bidirectional data binding system connects UI components with Python data objects. Located in `src/myfasthtml/core/bindings.py`.

**Key concepts:**
- **Observable objects**: Use `make_observable()` from myutils to enable change detection
- **Three-phase lifecycle**: Create → Activate (bind_ft) → Deactivate
- **Detection modes**: How changes are detected (ValueChange, AttributePresence, SelectValueChange)
- **Update modes**: How UI updates (ValueChange, AttributePresence, SelectValueChange)
- **Data converters**: Transform data between UI and Python representations

**Binding flow:**
1. User changes input → HTMX posts to `/myfasthtml/bindings`
2. `Binding.update()` receives form data, updates observable object
3. Observable triggers change event → `Binding.notify()`
4. All bound UI elements update via HTMX swap-oob

**Helper usage:**
```python
from myfasthtml.controls.helpers import mk

# Bind input and label to same data
input_elt = Input(name="field")
label_elt = Label()

mk.manage_binding(input_elt, Binding(data, "attr"))
mk.manage_binding(label_elt, Binding(data, "attr"))
```

**Important binding notes:**
- Elements MUST have a `name` attribute to trigger updates
- Multiple elements can bind to same data attribute
- First binding call uses `init_binding=True` to set initial value
- Bindings route through `/myfasthtml/bindings` endpoint

### Core System: Instances

Session-scoped instance management system. Located in `src/myfasthtml/core/instances.py`.

**Key classes:**
- `BaseInstance`: Base for all managed instances
- `SingleInstance`: One instance per parent per session
- `UniqueInstance`: One instance ever per session (singleton-like)
- `RootInstance`: Top-level singleton for application
- `InstancesManager`: Global registry with session-based isolation

**Instance creation pattern:**
```python
# __new__ checks registry before creating
# If instance exists with same (session_id, _id), returns existing
instance = MyInstance(parent, session, _id="optional")
```

**Automatic ID generation:**
- SingleInstance: `snake_case_class_name`
- UniqueInstance: `snake_case_class_name`
- Regular BaseInstance: `parent_prefix-uuid`

### Application Setup

**Main entry point**: `create_app()` in `src/myfasthtml/myfastapp.py`

```python
from myfasthtml.myfastapp import create_app

app, rt = create_app(
    daisyui=True,           # Include DaisyUI CSS
    vis=True,               # Include vis-network.js
    protect_routes=True,    # Enable auth beforeware
    mount_auth_app=False,   # Mount auth routes
    base_url=None           # Base URL for auth
)
```

**What create_app does:**
1. Adds MyFastHtml CSS/JS assets via custom static route
2. Optionally adds DaisyUI 5 + Tailwind CSS 4
3. Optionally adds vis-network.js
4. Mounts `/myfasthtml` app for commands and bindings routes
5. Optionally sets up auth routes and beforeware
6. Creates AuthProxy instance if auth enabled

### Authentication System

Located in `src/myfasthtml/auth/`. Integrates with FastAPI backend (myauth package).

**Key components:**
- `auth/utils.py`: JWT helpers, beforeware for route protection
- `auth/routes.py`: Login, register, logout routes
- `auth/pages/`: LoginPage, RegisterPage, WelcomePage components

**How auth works:**
1. Beforeware checks `access_token` in session before each route
2. Auto-refreshes token if < 5 minutes to expiry
3. Redirects to `/login` if token invalid/missing
4. Protected routes receive `auth` parameter with user info

**Session structure:**
```python
{
    'access_token': 'jwt_token',
    'refresh_token': 'refresh_token',
    'user_info': {
        'email': 'user@example.com',
        'username': 'user',
        'roles': ['admin'],
        'id': 'uuid',
        'created_at': 'timestamp',
        'updated_at': 'timestamp'
    }
}
```

## Project Structure

```
src/myfasthtml/
├── myfastapp.py          # Main app factory (create_app)
├── core/
│   ├── commands.py       # Command system
│   ├── bindings.py       # Binding system
│   ├── instances.py      # Instance management
│   ├── utils.py          # Utilities, routes app
│   ├── constants.py      # Routes, constants
│   ├── dbmanager.py      # Database helpers
│   ├── AuthProxy.py      # Auth proxy instance
│   └── network_utils.py  # Network utilities
├── controls/
│   ├── helpers.py        # mk class with UI helpers
│   ├── BaseCommands.py   # Base command implementations
│   ├── Search.py         # Search control
│   └── Keyboard.py       # Keyboard shortcuts
├── auth/
│   ├── utils.py          # JWT, beforeware
│   ├── routes.py         # Auth routes
│   └── pages/            # Login, Register, Welcome pages
├── icons/                # Icon libraries (fluent, material, etc.)
├── assets/               # CSS/JS files
└── test/                 # Test utilities

tests/
├── core/                 # Core system tests
├── testclient/           # TestClient and TestableElement tests
├── auth/                 # Authentication tests
├── controls/             # Control tests
└── html/                 # HTML component tests
```

## Testing System

**Custom test client**: `myfasthtml.test.TestClient` extends FastHTML test client

**Key features:**
- `user.open(path)`: Navigate to route
- `user.find_element(selector)`: Find element by CSS selector
- `user.should_see(text)`: Assert text in response
- Returns `TestableElement` objects with component-specific methods

**Testable element types:**
- `TestableInput`: `.send(value)`
- `TestableCheckbox`: `.check()`, `.uncheck()`, `.toggle()`
- `TestableTextarea`: `.send(value)`, `.append(text)`, `.clear()`
- `TestableSelect`: `.select(value)`, `.select_by_text(text)`, `.deselect(value)`
- `TestableRange`: `.set(value)`, `.increase()`, `.decrease()`
- `TestableRadio`: `.select()`
- `TestableButton`: `.click()`
- `TestableDatalist`: `.send(value)`, `.select_suggestion(value)`

**Test pattern:**
```python
def test_component(user, rt):
    @rt("/")
    def index():
        data = Data("initial")
        component = Component(name="field")
        label = Label()

        mk.manage_binding(component, Binding(data))
        mk.manage_binding(label, Binding(data))

        return component, label

    user.open("/")
    user.should_see("initial")

    elem = user.find_element("selector")
    elem.method("new_value")
    user.should_see("new_value")
```

## Important Patterns

### Creating interactive buttons with commands
```python
from myfasthtml.controls.helpers import mk
from myfasthtml.core.commands import Command

def action():
    return "Result"

cmd = Command("action", "Description", action)
button = mk.button("Click", command=cmd)
```

### Bidirectional binding
```python
from myutils.observable import make_observable
from myfasthtml.core.bindings import Binding
from myfasthtml.controls.helpers import mk

data = make_observable(Data("value"))
input_elt = Input(name="field")
label_elt = Label()

mk.manage_binding(input_elt, Binding(data, "value"))
mk.manage_binding(label_elt, Binding(data, "value"))
```

### Using helpers (mk class)
```python
# Button with command
mk.button("Text", command=cmd, cls="btn-primary")

# Icon with command
mk.icon(icon_svg, size=20, command=cmd)

# Label with icon
mk.label("Text", icon=icon_svg, size="sm")

# Generic wrapper
mk.mk(element, command=cmd, binding=binding)
```

## Common Gotchas

1. **Bindings require `name` attribute**: Without it, form data won't include the field
2. **Commands auto-register**: Don't manually register with CommandsManager
3. **Instances use __new__ caching**: Same (session, id) returns existing instance
4. **First binding needs init**: Use `init_binding=True` to set initial value
5. **Observable required for bindings**: Use `make_observable()` from myutils
6. **Auth routes need base_url**: Pass `base_url` to `create_app()` for proper auth API calls

## Dependencies

**Core:**
- python-fasthtml: Web framework
- myauth: Authentication backend
- mydbengine: Database abstraction
- myutils: Observable pattern, utilities

**UI:**
- DaisyUI 5: Component library
- Tailwind CSS 4: Styling
- vis-network: Network visualization

**Development:**
- pytest: Testing framework
- httpx: HTTP client for tests
- python-dotenv: Environment variables
