Skip to content

Rendering modes — ISR, SSG, SSR

@ghostwritr/next doesn’t impose a caching strategy. You pick your rendering mode with a single revalidate flag on createGhostwritr, and the client folds your choice into Next’s fetch so every feed request — manifest and pages — is cached the way you asked.

lib/ghostwritr.ts
import "server-only";
import { createGhostwritr } from "@ghostwritr/next/server";
export const gw = createGhostwritr({
siteId: process.env.GHOSTWRITR_SITE_ID!,
revalidate: 3600, // <- this flag is the whole story
});
You wantrevalidateBehavior under the hood
ISR (default)3600 (any positive N)next: { revalidate: N } — served from cache, refreshed in the background every N seconds.
Pure SSGfalsenext: { revalidate: false } — fetched at build, cached indefinitely. Rebuild to update.
Dynamic SSR0cache: "no-store" — fetched on every request. Always live.

revalidate must be a non-negative integer or false; anything else throws a GhostwritrError with code CONFIG at client-creation time. The default when you omit it is 3600.

createGhostwritr({ siteId, revalidate: 600 }); // ISR, 10-minute window
createGhostwritr({ siteId, revalidate: false }); // pure SSG
createGhostwritr({ siteId, revalidate: 0 }); // dynamic SSR

The default and the right answer for most blogs. Pages are pre-rendered and served from cache; after N seconds the next request triggers a background refresh, so visitors never wait on the feed.

  • Pick it when you want fast static pages but don’t want to redeploy to publish.
  • Trade-off new articles appear within the revalidate window, not instantly — tune N lower for fresher, higher for fewer feed fetches. For true instant publishing, keep a generous window and add instant revalidation.

The feed is fetched once at build and cached forever. The pages are fully static — fastest possible serve, no runtime feed fetches at all.

  • Pick it when you rebuild and redeploy on every publish anyway (e.g. you trigger a deploy from the feed.updated webhook), or your content rarely changes.
  • Trade-off content is frozen until the next build. Without a rebuild, new and edited articles never appear.

Every request fetches the feed fresh (cache: "no-store"). Always live, never stale.

  • Pick it when you need real-time freshness and can absorb a feed round-trip per request — a preview environment, or a low-traffic page where caching buys little.
  • Trade-off no static caching means every render pays the feed latency, and you lose the CDN-edge speed of static pages.

ISR with a long window plus on-demand busting gives you static speed and instant freshness. Add tags, and a verified feed.updated webhook busts them the moment the engine rebuilds your feed:

lib/ghostwritr.ts
export const gw = createGhostwritr({
siteId: process.env.GHOSTWRITR_SITE_ID!,
revalidate: 3600,
tags: ["ghostwritr"], // <- on-demand revalidation
});

tags must be an array of strings or you get a CONFIG error. The tags you pass here must match the tags the handler revalidates. See Instant revalidation for the full wiring and Instant updates for the concept.