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.

The request carries X-GW-Signature: a hex HMAC-SHA256 of the raw request body under a shared secret. Verify it against the raw bytes before acting — parsing the body first and re-serializing it will not match.

import { verifyFeedSignature, FEED_SIGNATURE_HEADER } from "@ghostwritr/feed";
const raw = await request.text(); // the RAW body — verify before JSON.parse
const ok = await verifyFeedSignature(
process.env.GHOSTWRITR_FEED_SECRET!,
raw,
request.headers.get(FEED_SIGNATURE_HEADER),
);
if (!ok) return new Response("invalid signature", { status: 401 });
const { siteId, buildId } = JSON.parse(raw); // now safe to parse

verifyFeedSignature is constant-time and returns false for a missing or mismatched signature. The same helpers (signFeedPayload / verifyFeedSignature / FEED_SIGNATURE_HEADER) are re-exported from @ghostwritr/feed, @ghostwritr/next, and @ghostwritr/react-router, 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.