REEF (RFC Editor Engagement Features) is the IETF self-hosted survey and engagement service, part of the RFC Modernization Phase 2 program alongside Red (the public RFC website). It hosts SurveyJS on our own infrastructure and exposes engagement APIs that Red consumes.
- Surveys, full stack:
- A Django-hosted survey builder (SurveyJS Creator) and analytics dashboard
(SurveyJS Analytics), under
/admin/survey-builder/, for staff. - An API that lists open surveys, serves definitions, and stores responses.
Red queries the open-survey list and hosts the runner (
/survey/?slug=<slug>) where visitors fill out surveys. Reef's own/sredirects there.
- A Django-hosted survey builder (SurveyJS Creator) and analytics dashboard
(SurveyJS Analytics), under
- Ratings and subscriptions: APIs consumed by Red (their UI lives in Red). Reef owns storage and aggregation, and sends subscription emails.
- Popularity: a ranking of RFCs derived from analytics, served as a percentile per document for any consumer to read.
Surveys are built end to end; ratings and subscriptions are scaffolded (models and endpoints in place, to be completed next). See plan.md for the full design.
Django 5 and Django REST Framework with PostgreSQL back the service. An NGINX
front proxy (in a deployment, the Cloudflare Worker in worker/) serves one
origin for the Django site and API. Authentication is OIDC against the IETF
Authentik instance at https://account.ietf.org/. The API contract is generated
by drf-spectacular into reef_api.yaml, which Red consumes.
Browser -> NGINX :8088 -> Django + DRF :8001 -> PostgreSQL
-> /s redirects to Red's survey runner
Red -> /api/reef/... (bearer / anonymous) -> Django + DRF
Red -> precomputed JSON <- blob store <- manage.py precompute
The precomputer renders the public API responses ahead
of time and writes them to a blob store, so that a reader is served a file
rather than a query that aggregates every rating, subscription and set entry.
It is one command, manage.py precompute, meant to be run on a schedule; with
no bucket configured it writes to ./precomputed and needs no object storage.
Requires Docker. Two options:
- VS Code Dev Containers: open the repository in the container. Initialization installs dependencies, runs migrations, vendors the SurveyJS bundles, and starts the Django server behind NGINX.
- Generic Docker: run
docker/run, which builds the containers and launches a tmux session with the servers.
The app image builds FROM ghcr.io/ietf-tools/reef-app-base. Until CI publishes
it, build it locally first:
docker build -f docker/base.Dockerfile -t ghcr.io/ietf-tools/reef-app-base:latest .
Then browse:
- http://localhost:8088/admin/survey-builder/surveys/ - the survey builder and analytics (login)
- http://localhost:8088/admin/ - Django admin (login)
- http://localhost:8088/api/reef/schema/swagger-ui/ - API docs
- http://localhost:8025/ - mailpit (captured email)
- http://localhost:8088/pgadmin/ - pgAdmin
Copy .env.example to .env and fill in the Authentik client credentials and
(for production) the SurveyJS license key. See
docs/development.md for the full list of settings and the
Authentik application setup, including the redirect URIs to register.
./manage.py test # Django tests
ruff check . # lint
ruff format --check . # format check
REEF_DEPLOYMENT_MODE=build ./manage.py spectacular \
--urlconf reef.urls_contract \
--file reef_api.yaml --validate # API schema
cd worker && npm test # worker
Production images are built from dev/build/ and published to ghcr.io by the
GitHub Actions in .github/workflows/, which also deploy the worker in
worker/. The release
workflow dispatches to ietf-tools/infra-k8s, which applies the manifests in k8s/
and supplies each environment's values through the reef-secrets-env secret; see
docs/development.md for the variables it has to carry.
reef/- Django project (settings package, celery, urls)reefauth/- custom user and OIDC (login backend plus bearer resource-server auth)surveys/- survey models, API, and the/admin/survey-builder/builder and analyticsratings/,subscriptions/- engagement API appspopularity/- the popularity ranking, its Matomo import, and the recompute behind ittemplates/- Django templates, currently the notification email bodiesworker/- Cloudflare Worker fronting a deployment: precomputed files, the/sredirect, the page at/vendor/- self-hosted SurveyJS bundlesdocker/- dev container and compose toolingdev/build/- production image buildsk8s/- Kustomize manifests