Appearance
Backend deepdive
The backend is a Django app in backend/. It exposes Django views, Django Allauth auth routes, and a Django Ninja API.
Entry points
txt
backend/manage.py
backend/asgi.py
backend/wsgi.py
backend/conf/settings.py
backend/conf/urls.pyconf/settings.py contains the main Django settings. conf/urls.py wires the URL routes up and creates the Ninja API instance.
App layout
txt
backend/apps/users/ custom user model and user views
backend/apps/demo/ demo app, incl. example Celery tasks (tasks.py)
backend/lib/ vendored libraries (e.g. celery-tracker)
backend/tests/ backend tests (unit + e2e)Installed local apps:
py
"apps.users"
"apps.demo"Configuration
Settings are loaded from environment variables using uncouple config classes.
Main config classes in conf/settings.py:
DjangoConfigEmailConfigCeleryConfigProjectConfig
Common local values are defined in:
txt
local/conf/defaultThe default local database URL points to the Postgres service we can spin up with Docker Compose:
txt
postgresql://postgres:postgres@postgres:5432/webappURLs
All backend URLs are mounted under settings.URL_PREFIX, which defaults to -.
Main local URL groups:
| Path | Description |
|---|---|
/-/admin/ | Django admin |
/-/users/ | user views |
/-/.auth/accounts/ | Django Allauth account URLs |
/-/.auth/headless/ | Django Allauth headless API |
/-/api/ | Django Ninja API |
/-/api/docs | Django Ninja API docs |
/-/_health/ | health check |
The admin route uses settings.ADMIN_PATH, which defaults to admin/. LOGIN_URL and STATIC_URL are also prefixed with settings.URL_PREFIX.
API setup
The Ninja API is created in:
txt
backend/conf/urls.pyIt uses session auth:
py
SessionAuth(csrf=False)Routers are registered through API_ROUTERS. The current custom routers are:
txt
/-/api/trackerUsers app
The users app defines the custom user model:
txt
backend/apps/users/models.pyapps.users.User extends Django AbstractUser.
Key behavior:
- email is unique
- email is used as
USERNAME_FIELD - username is disabled
- first name and last name are disabled
nameis available as a display field
Related files:
txt
backend/apps/users/managers.py
backend/apps/users/forms.py
backend/apps/users/admin.py
backend/apps/users/urls.py
backend/apps/users/views.pyAuth
Authentication is handled by Django Allauth.
Enabled pieces include:
allauth.accountallauth.socialaccountallauth.socialaccount.providers.amazon_cognitoallauth.headlessallauth.usersessions
The frontend mainly uses the headless routes under:
txt
/-/.auth/headless/Current account settings:
- registration is enabled
- login is by email
- email verification is disabled
- social account email authentication is enabled
The local development entrypoint always seeds a superuser on startup, defaulting to test@localhost / test. Override the credentials with the DJANGO_SUPERUSER_EMAIL and DJANGO_SUPERUSER_PASSWORD env vars (set in local/conf/).
Background tasks
Celery handles asynchronous work, with Redis as the broker and result backend (the CELERY_* settings in conf/settings.py, fed by CeleryConfig).
txt
backend/conf/celery.py Celery app (started with `celery -A conf worker`)
backend/apps/demo/tasks.py example task (demo.tasks.sample_task)
backend/lib/tracker/ vendored celery-tracker (import name `tracker`)conf/__init__.py re-exports the Celery app as conf.celery_app, and tasks are auto-discovered from the tasks module of every installed app.
The tracker library records task steps and progress and serves them through the /-/api/tracker router (created in conf/urls.py), which the frontend /tracker page consumes. In the local stack a dedicated worker service runs the Celery worker, restarting on code changes.
backend/lib/ is on the Python path, so vendored packages like tracker are importable by their top-level name; see backend/lib/README.md for how it is pinned and updated.
Static and media files
Static files are served by Whitenoise.
This is mostly for Django-owned assets, such as admin CSS/JS and any static files used by backend-rendered pages. User-facing React assets should usually live in the frontend instead.
Configured storage backend:
py
whitenoise.storage.CompressedManifestStaticFilesStoragebackend/staticfiles/ is generated output from Django collectstatic. It is not a source directory for app assets.
Media files are different from static files. They are for uploaded or generated user content. The local media root is:
txt
backend/apps/media/Local development
Each layer's justfile is mounted as a submodule of the root justfile, so commands run from the generated project root as just <layer> <recipe>.
Bring up the local Docker Compose environment:
sh
just local upjust local up prints the local app URL and the seeded local dev credentials.
Run backend tests and management commands against the container:
sh
just local test-unit
just local test-e2e
just local manage checkThe backend also has its own justfile for host-side commands via uv:
sh
just backend check
just backend makemigrations
just backend runserverDependencies
Python dependencies are managed with uv in backend/.
Main dependency files:
txt
backend/pyproject.toml
backend/uv.lockDev tools include:
- pytest, pytest-django, pytest-xdist
- httpx (e2e tests)
- ruff
- django-extensions
- watchdog (worker autoreload)
Docker image
The backend Dockerfile is:
txt
backend/docker/DockerfileIt has three main targets:
development: installs production and dev dependenciesbuild: builds production wheelsruntime: production image running as a non-root user