# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash # Install dependencies uv sync # Database setup python manage.py migrate python manage.py createsuperuser # Run dev server (two terminals needed, or use honcho) python manage.py runserver python manage.py tailwind start # separate terminal # Run all tests python manage.py test # Run tests for a single app python manage.py test members python manage.py test teams # Coverage coverage run --source='.' manage.py test && coverage report # Lint / format (line length 250) ruff check . ruff format . ``` ## Architecture TeamForge is a Django 6 club management app (members + teams). Key libraries: - **HTMX** + **django-htmx**: dynamic interactions without a SPA - **Tailwind CSS 4 + DaisyUI 5**: styling via `python manage.py tailwind start` - **django-waffle**: feature flags (`TF_TEAMS`, `TF_ACTIVITIES`, `TF_MASS_UPLOAD`) - **django-constance**: database-backed config (club name, logo, season defaults) - **django-rules**: object-level permissions (predicates in `members/rules.py`) - **django-filter**: URL-driven queryset filtering ### Apps | App | Responsibility | |-----|----------------| | `members` | Member CRUD, CSV bulk import, permissions | | `teams` | Season model and date-range logic | | `backend` | Dashboard, configuration view | | `theme` | Tailwind source, custom template tags | ### HTMX pattern `HTMXViewMixin` (in `backend/views.py`) is the core convention: views render a full page for normal requests and a named partial for HTMX requests. Partials use django-partials syntax (`template.html#partial_name`). The mixin also injects `HX-Push-Url` and `HX-Trigger` response headers — the trigger drives client-side menu highlighting via a JS event listener. ### Members app details - Every new `User` automatically gets a `Member` profile via a `post_save` signal. - Deleting a member deactivates the `User` (`is_active=False`) — no hard deletes. - `Member.create()` is the canonical way to create a member + user together. - `MemberManager` always `select_related("user")`. - Permissions are two-tier: Django model permissions + rules predicates (`is_member_manager`). ### Feature flags New features should be gated with a `django-waffle` Switch. `WAFFLE_CREATE_MISSING_FLAGS = True` so flags don't need to be pre-created in migrations. Check flags in views with `waffle.switch_is_active("FLAG_NAME")` and in templates with `{% waffle_switch "FLAG_NAME" %}`. ### Configuration Runtime config (club name, logo, season month/day/duration) lives in `django-constance` and is editable via `/backend/configuration/` (superuser only). Access values with `from constance import config; config.TF_CLUB_NAME`. ### Season duration format `TF_DEFAULT_SEASON_DURATION` uses the custom format `"y"` (years) or `"m"` (months), parsed in `Season._add_months()`.