Instant updates
The content feed changes only when you publish. Instead of waiting on a revalidation timer, you can subscribe to a signed webhook and refresh the instant a rebuild lands.
The feed.updated webhook
Section titled “The feed.updated webhook”When a site’s static feed rebuilds, Ghost Writr POSTs a small JSON body to your registered URL:
interface FeedUpdatedPayload { event: "feed.updated"; siteId: string; buildId: string;}buildId is the new build the manifest now points at. Your handler doesn’t need to trust the body’s contents beyond “something changed” — the next read resolves the manifest and picks up the new build automatically. Your job is just to invalidate whatever cached the previous build.
Verify the signature
Section titled “Verify the signature”Each delivery carries three headers — Webhook-Id, Webhook-Timestamp, and Webhook-Signature (v1=<hex>, an HMAC-SHA256 over the id, timestamp, and raw request body under a shared secret). Signing the id and timestamp together makes it replay-safe. Verify against the raw bytes before acting — parsing the body first and re-serializing it will not match.
import { verifyWebhook } from "@ghostwritr/feed";
const raw = await request.text(); // the RAW body — verify before JSON.parse// verifyWebhook reads Webhook-Id / Webhook-Timestamp / Webhook-Signature from the headers itselfconst ok = await verifyWebhook(process.env.GHOSTWRITR_FEED_SECRET!, raw, request.headers);if (!ok) return new Response("invalid signature", { status: 401 });
const { siteId, buildId } = JSON.parse(raw); // now safe to parseverifyWebhook is constant-time and returns false for a missing, stale-timestamp, or mismatched delivery (rejecting a timestamp outside the ±300s window as replay defense). The verifier (verifyWebhook) and the header constants (WEBHOOK_ID_HEADER / WEBHOOK_TIMESTAMP_HEADER / WEBHOOK_SIGNATURE_HEADER) are re-exported from @ghostwritr/feed, @ghostwritr/next, @ghostwritr/react-router, @ghostwritr/svelte, and @ghostwritr/vue, so both ends sign identically by construction. They run on Web Crypto — the same in Node 20+ and on the edge.
Three freshness strategies
Section titled “Three freshness strategies”How you refresh depends on how your site renders. Each SDK has a dedicated page for the wiring.
| Render model | Strategy | What the handler does |
|---|---|---|
| Next.js (ISR) | On-demand revalidation | Verify, then revalidateTag / revalidatePath so the next request re-fetches. See Next instant revalidation. |
| Astro (static) | Redeploy hook | Verify, then trigger a rebuild/redeploy of the static site so the new build is generated. See Astro: redeploy on publish. |
| React Router / SSR | CDN purge | Verify, then purge the affected paths from your CDN/cache so the edge re-fetches the feed. See React Router feed-freshness webhook. |
The throughline is the same: verify the signature, then invalidate the cache layer your renderer relies on. The next read walks the manifest and serves the new buildId.