# neuf-www

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

Tools are managed by [mise](https://mise.jdx.dev/). Run `mise install` to get python, uv, node, and prek.

## Backend (`dnscms/`)

```bash
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/`)

```bash
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](https://github.com/j178/prek) runs ruff lint + format on `dnscms/**/*.py`, vitest on `web/` changes, plus a few sanity hooks. Hooks are configured in [prek.toml](prek.toml).

```bash
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.

```bash
# 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.
