2.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
# 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
Userautomatically gets aMemberprofile via apost_savesignal. - Deleting a member deactivates the
User(is_active=False) — no hard deletes. Member.create()is the canonical way to create a member + user together.MemberManageralwaysselect_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 "<n>y" (years) or "<n>m" (months), parsed in Season._add_months().