2026-10-14 02:51:54 +02:00
2026-10-14 02:51:54 +02:00
2026-10-14 02:51:54 +02:00
2026-05-20 01:02:02 +02:00
2026-10-14 02:51:54 +02:00
2026-08-04 03:02:09 +02:00

neuf-www

The neuf.no website. Wagtail CMS backend (dnscms/) feeding a Next.js frontend (web/) over GraphQL.

Tools are managed by mise. Run mise install to get python, uv, node, and prek.

Backend (dnscms/)

cd dnscms
uv sync
uv run ./manage.py migrate
uv run ./manage.py runserver
uv run pytest

GraphQL endpoint: http://127.0.0.1:8000/api/graphql/.

Frontend (web/)

cd web
npm install
npm run dev         # http://localhost:3000
npm run codegen     # regenerate GraphQL types (needs the backend running)
npm run build
npm test            # vitest (npm run test:watch for watch mode)

Pre-commit hooks

prek runs ruff lint + format on dnscms/**/*.py, vitest on web/ changes, plus a few sanity hooks. Hooks are configured in prek.toml.

prek install            # registers the git hook
prek run --all-files    # run on everything

Caching and revalidation

The frontend caches all pages and GraphQL responses (ISR) under a single cms cache tag. Wagtail purges it via a webhook on any publish/unpublish/move/delete (see dnscms/dnscms/revalidation.py). Date-sensitive queries (futureEvents, opening hours) additionally expire at Oslo midnight. REVALIDATE_WEBHOOK_SECRET must be set to the same value on both sides (web/.env.local and dnscms/dnscms/settings/local.py or env); unset disables the webhook.

# manual purge
curl -X POST -H "X-Revalidate-Secret: $SECRET" https://<frontend>/api/revalidate

Note: ISR is off under npm run dev; use npm run build && npm run start to test caching.

CMS login via Galtinn

Editors log in to the CMS with their Galtinn account over OIDC (see dnscms/dnscms/oidc.py). Access follows membership of one Galtinn group, which is checked at every login: members become Wagtail editors, and a linked user who has left the group is deactivated. Users are identified only by their stored Galtinn ID, never by username or email, so an existing local user must be linked by hand under /django-admin/ before they can use it. Linked users have no local password; unlinked local users still log in with theirs.

Set these in dnscms/dnscms/settings/local.py or env. The Galtinn button only shows when the group and client ID are set.

Setting Value
GALTINN_BASE_URL Galtinn's public URL, defaults to https://galtinn.neuf.no
GALTINN_EDITOR_GROUP name of the Galtinn group that grants editor access
OIDC_RP_CLIENT_ID, OIDC_RP_CLIENT_SECRET the OAuth application registered in Galtinn's admin
WAGTAIL_BASE_URL must be the CMS's public URL; the callback is <WAGTAIL_BASE_URL>/oidc/callback/

To link existing local users in bulk, match them against Galtinn and review the result by hand:

uv run manage.py galtinn_users export > cms-users.csv                 # in dnscms
uv run manage.py match_cms_users cms-users.csv > matched.csv          # in galtinn, suggests a galtinn_id per row
uv run manage.py galtinn_users link matched.csv                       # in dnscms, dry run; add --apply to save

Rows with an empty galtinn_id stay local users. A linked user keeps their password until their first Galtinn login.

S
Description
No description provided
Readme
7.7 MiB
0 Stars 8 Watchers 0 Forks
Languages
TypeScript 55.9%
Python 39.9%
SCSS 3.3%
HTML 0.4%
JavaScript 0.3%
Other 0.2%