Webhook helpers
When your site’s feed rebuilds, Ghost Writr POSTs a feed.updated body to your registered URL with an X-GW-Signature header. Verify it, then bust your cache and re-fetch. The same two helpers sign and verify, so the signature matches by construction. See instant updates.
The payload
Section titled “The payload”FeedUpdatedPayload:
interface FeedUpdatedPayload { event: "feed.updated"; siteId: string; buildId: string;}Verify on receipt
Section titled “Verify on receipt”verifyFeedSignature(secret, rawBody, signature) returns a Promise<boolean>. It computes HMAC-SHA256 of the raw body with your shared secret and compares it to the header in constant time (so a wrong signature can’t be discovered byte-by-byte via timing). A missing or empty signature returns false.
import { verifyFeedSignature, FEED_SIGNATURE_HEADER } from "@ghostwritr/feed";
export async function POST(request: Request) { const raw = await request.text(); // raw body, BEFORE JSON.parse const sig = request.headers.get(FEED_SIGNATURE_HEADER);
const ok = await verifyFeedSignature(process.env.GHOSTWRITR_FEED_SECRET!, raw, sig); if (!ok) return new Response("invalid signature", { status: 401 });
const payload = JSON.parse(raw); // FeedUpdatedPayload // ...revalidate this site, then re-fetch the feed. return new Response("ok");}FEED_SIGNATURE_HEADER is the header name ("X-GW-Signature") — import it rather than hardcoding the string.
Sign a payload
Section titled “Sign a payload”signFeedPayload(secret, rawBody) returns a Promise<string> — the hex HMAC-SHA256 you’d put in the header. Ghost Writr signs your real webhooks; you’ll mostly use this to build a fixture in tests.
import { signFeedPayload, FEED_SIGNATURE_HEADER } from "@ghostwritr/feed";
const body = JSON.stringify({ event: "feed.updated", siteId, buildId });const sig = await signFeedPayload(secret, body); // 64-char lowercase hex
const res = await app.request("/webhooks/ghostwritr", { method: "POST", headers: { [FEED_SIGNATURE_HEADER]: sig }, body,});What to reach for next
Section titled “What to reach for next”- The concept — how instant updates fit the immutable-snapshot feed. See Instant updates.
- Re-fetch after verifying — the fetchers that read the new build. See Fetchers.
- Full surface — every export, typed. See API reference.