Skip to content

Commit c9e1a7e

Browse files
authored
Merge pull request dimagi#1013 from dimagi/ce/claudemd-opus
Add CLAUDE.md with project context for Claude Code
2 parents 1699364 + 64ca6b0 commit c9e1a7e

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@CLAUDE.md

CLAUDE.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# CommCare Connect
2+
3+
Django 4.2 + PostGIS monolith for managing community health worker opportunities, payments, and workflows. Integrates with CommCare HQ and ConnectID services.
4+
5+
## Commands
6+
7+
```bash
8+
# Local services (PostgreSQL/PostGIS + Redis)
9+
inv up # docker compose up
10+
inv down # docker compose down
11+
12+
# Django
13+
./manage.py migrate # run migrations (dev)
14+
./manage.py migrate_multi # run migrations on both primary + secondary DB (prod)
15+
./manage.py runserver # dev server
16+
17+
# JavaScript/CSS
18+
npm ci # install deps
19+
inv build-js # dev build
20+
inv build-js -w # dev build with watch
21+
inv build-js --prod # production build
22+
23+
# Celery (local dev)
24+
celery -A config.celery_app worker -B -l info
25+
26+
# Tests
27+
pytest # run all tests
28+
pytest path/to/test_file.py::test_name # run single test
29+
30+
# Linting (runs black, isort, flake8, pyupgrade, django-upgrade, prettier)
31+
pre-commit run -a
32+
33+
# Requirements (pip-tools)
34+
inv requirements # recompile .txt from .in files
35+
inv requirements --upgrade-package <pkg>
36+
37+
# Translations
38+
inv translations
39+
```
40+
41+
## Architecture
42+
43+
- **Monolith**: Django serves both HTML templates (Tailwind + Alpine.js + htmx) and a DRF REST API
44+
- **URL pattern**: Most views scoped under `/a/<org_slug>/` via `OrganizationMiddleware`
45+
- **API versioning**: `AcceptHeaderVersioning` with versions `1.0` and `2.0`
46+
- **Background tasks**: Celery with Redis broker; beat scheduler uses DB
47+
- **Feature flags**: django-waffle with custom `Flag` model; constants in `commcare_connect/flags/switch_names.py`
48+
- **Audit trail**: django-pghistory stores `username` + `user_email` in context (survives user deletion)
49+
- **Database**: PostgreSQL + PostGIS. `ATOMIC_REQUESTS = True` (all requests are transactions)
50+
- **Deployment**: Kamal (Docker-based) + Ansible. NOT Elastic Beanstalk despite README mention
51+
52+
### Key directories
53+
54+
```
55+
commcare_connect/
56+
opportunity/ # Core domain: opportunities, visits, payments (largest app)
57+
organization/ # Org management, membership roles
58+
program/ # Program management, linking orgs/opportunities
59+
users/ # Custom User model, ConnectID links
60+
commcarehq/ # CommCare HQ server integration
61+
connect_id_client/ # HTTP client for ConnectID service
62+
form_receiver/ # Receives xforms from CommCare HQ
63+
microplanning/ # Maps, catchment areas (Mapbox)
64+
reports/ # KPI and admin reports
65+
flags/ # Waffle feature flag/switch name constants
66+
multidb/ # Secondary DB support + logical replication
67+
utils/ # BaseModel, middleware, caching, permissions
68+
config/
69+
settings/ # base.py, local.py, test.py, staging.py, production.py
70+
api_router.py # DRF API URL routing
71+
celery_app.py # Celery config
72+
urls.py # Root URL config
73+
```
74+
75+
## Code Style
76+
77+
- **Python**: black + isort (line length 119, target py311). flake8 for linting
78+
- **JS/CSS**: prettier (tab-width 2, single-quote). Templates excluded from prettier
79+
- **Pre-commit hooks enforce all of the above** plus pyupgrade (--py311-plus) and django-upgrade (--target-version 4.1)
80+
- Django models should extend `BaseModel` from `commcare_connect/utils/db.py` (provides `created_by`, `modified_by`, `date_created`, `date_modified`)
81+
- Custom `User` model uses single `name` field instead of `first_name`/`last_name`
82+
83+
## Testing
84+
85+
- **Framework**: pytest + pytest-django + factory-boy
86+
- **Test location**: `commcare_connect/<app>/tests/` with `factories.py`, `test_*.py`
87+
- **Global fixtures** in `commcare_connect/conftest.py`: `organization`, `user`, `opportunity`, `mobile_user`, `mobile_user_with_connect_link`, `org_user_member`, `org_user_admin`, `api_rf`, `api_client`
88+
- **autouse fixtures**: `media_storage` (redirects to tmpdir), `ensure_currency_country_data` (repopulates Currency/Country flushed between tests)
89+
- HTTP mocking: `pytest-httpx` for httpx calls
90+
91+
## Gotchas
92+
93+
- **PostGIS required everywhere** (including tests). Local dev needs `gdal`, `geos`, `proj` system libs. On macOS, set `GDAL_LIBRARY_PATH` and `GEOS_LIBRARY_PATH` in `.env`
94+
- **`--reuse-db` + Currency/Country data**: These models get flushed between tests. The `ensure_currency_country_data` autouse fixture handles this — don't remove it
95+
- **API UUID transition**: The `API_UUID` waffle switch controls whether API endpoints accept integer PKs or UUIDs. Use `get_object_or_list_by_uuid_or_int()` from `utils/db.py` for API lookups
96+
- **CSRF via sessions**: `CSRF_USE_SESSIONS = True`. Templates use `hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'` on `<body>` for htmx
97+
- **Webpack bundle tracker**: Frontend builds write `webpack-stats.json`. Templates reference bundles from `staticfiles/bundles/`
98+
- **CI uses**: `postgis/postgis:15-3.5` image, Python 3.11, requires `gdal-bin libproj-dev` apt packages

0 commit comments

Comments
 (0)