Skip to content

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.

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.

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 itself
const 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 parse

verifyWebhook 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.

How you refresh depends on how your site renders. Each SDK has a dedicated page for the wiring.

Render modelStrategyWhat the handler does
Next.js (ISR)On-demand revalidationVerify, then revalidateTag / revalidatePath so the next request re-fetches. See Next instant revalidation.
Astro (static)Redeploy hookVerify, then trigger a rebuild/redeploy of the static site so the new build is generated. See Astro: redeploy on publish.
React Router / SSRCDN purgeVerify, 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.