# Live updates

Your pages stay cached, and when someone changes content in Sonor, the pages
that use it refresh within seconds. It takes one route file:

```ts
// app/api/seo-revalidate/route.ts
export { POST } from '@sonordev/site-kit/revalidate'
```

`npx sonor-setup scaffold` writes it for you, and `npx sonor-setup doctor`
tells you when it's missing.

## How it works

Everything site-kit fetches from Sonor is cached, and pages built from those
fetches are served from your host's CDN. When content changes in Sonor
(managed copy, a page's title or description, an article, a portfolio item),
Sonor sends this route the paths and cache tags that changed. The route checks
the call was signed with your project's API key, then expires only those
pages and tags. The next visitor gets the new version, and every other page
stays cached.

It's the same `SONOR_API_KEY` the rest of site-kit reads, so there's no
extra secret to set. Sonor finds the route on its own: the first sitemap sync
after a deploy registers `https://your-domain/api/seo-revalidate` and checks
that it answers.

Without the route, nothing breaks. Edits still show up, but only once each
cached fetch ages out: about five minutes for managed copy, up to a day for
metadata.

## Sites with a publication

If your site publishes articles, tell the route where they live so the index
and feeds refresh with each article:

```ts
// app/api/seo-revalidate/route.ts
import { createRevalidateRoute } from '@sonordev/site-kit/revalidate'

export const POST = createRevalidateRoute({ publicationBasePath: '/insights' })
```

| Option                | What it does                                                                                                                    |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `publicationBasePath` | Where your articles live, e.g. `/insights`. The index and its RSS and Atom feeds refresh on every call.                         |
| `extraPaths`          | Local paths to refresh on every call, e.g. a hub page like `/work`.                                                             |
| `extendPayload`       | Map extra fields Sonor sends to more paths or tags. The result is validated again, so it can't widen what a caller may refresh. |
| `secret`              | The key calls are signed with. Defaults to `SONOR_API_KEY`, read on every call.                                                 |

## What Sonor sends

A POST with `Authorization: Bearer <SONOR_API_KEY>` and a JSON body:

```json
{ "paths": ["/services/roofing"], "tags": ["sonor-slots"] }
```

| Field           | Meaning                                                                                                                                                                                 |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `paths`         | Local paths to regenerate. `/sitemap.xml`, `/llms.txt` and `/llms-full.txt` are always refreshed too.                                                                                   |
| `tags`          | Cache tags to expire. The ones Sonor uses are `SITE_CACHE_TAGS`: `sonor-slots` (managed copy), `seo` (metadata, schema, FAQs), `blog` (articles), `editorial-taxonomy` and `portfolio`. |
| `revalidateAll` | Regenerate every page.                                                                                                                                                                  |
| `ping`          | `{ "ping": true }` on its own regenerates nothing and answers `{ "ok": true, "ping": true, "version": "…" }`. Sonor uses it to confirm the route is installed.                          |

The route refuses a bad key (401), a body over 16 KB (413) and any path that
isn't a plain local path or any malformed tag (400). A refused call refreshes
nothing.

## Checking it

```bash
curl -s -X POST https://your-domain/api/seo-revalidate \
  -H "Authorization: Bearer $SONOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ping":true}'
```

`{"ok":true,"ping":true,...}` means Sonor's edits will go live in seconds. A
404 means the route isn't deployed. A 401 means the key on the site doesn't
match the project's key.
