The rendering layer is where the content your AI-native CMS produces becomes a page a human (or a crawler, or an LLM) actually reads. This chapter maps the four core rendering strategies — SSG, SSR, ISR, and edge rendering — and how 2026's meta-frameworks (Next.js 16, Astro 5/6, SvelteKit 2, Nuxt 4, and the React Router 7 / Remix 3 split) implement them. It then tackles the two problems that break naive setups for a content-heavy CMS: serving 1,000+ static pages without 30-minute builds, and letting editors preview unpublished drafts. It closes with a concrete decision framework.
These terms are used loosely in marketing, so pin them down before choosing a framework.
| Strategy | When HTML is built | Freshness | Cost per request | Best for |
|---|---|---|---|---|
| SSG (Static Site Generation) | At build/deploy time | Stale until next build (or on-demand revalidate) | ~$0, served from CDN | Marketing pages, docs, blogs, anything that changes on a publish cadence |
| SSR (Server-Side Rendering) | On every request | Always fresh | Compute per request | Personalized dashboards, auth-gated pages, search results |
| ISR (Incremental Static Regeneration) | First request or on-demand, then cached + revalidated | Stale-while-revalidate, configurable TTL or webhook | Near-$0 after first hit | Large catalogs, news, e-commerce — the CMS sweet spot |
| Edge rendering | On request, but at a CDN PoP near the user | Fresh, low latency | Compute per request, capped runtime | Geo/locale personalization, A/B tests, light SSR |
The crucial conceptual shift in 2026 is that these are no longer page-level choices but component-level choices. The same page can have a statically cached shell, an edge-personalized header, and a server-rendered "recommended for you" widget. Next.js calls this Partial Prerendering (PPR); Astro calls the dynamic fragments ; Nuxt expresses it through . For a CMS this matters because a typical article page is 95% cacheable body content with a few dynamic slivers (view count, "logged-in as", related-content rail).
routeRulesPPR was experimental in Next.js 14, refined in 15, and shipped stable in Next.js 16 (October 2025) under the renamed cacheComponents: true config — the old experimental.ppr flag was removed (Next.js docs; Pockit, PPR Deep Dive). The mental model: everything outside a React <Suspense> boundary is part of the static, CDN-cached shell; everything inside streams in dynamically. Functions and components opt into caching with the new "use cache" directive.
// Static shell served instantly from the edge:
export default function ArticlePage({ params }) {
return (
<Article slug={params.slug} /> {/* "use cache" → static */}
<Suspense fallback={<Skeleton />}>
<ReaderStats slug={params.slug} /> {/* dynamic, streamed */}
</Suspense>
);
}
This is the closest the industry has come to "one rendering model to rule them all," and Vercel's own guidance is that PPR should be the default strategy for most new Next.js apps going forward (samcheek.com, PPR in Production 2026). The cost: it is React/Next-specific and adds conceptual overhead — you must reason carefully about which data is request-time vs build-time, and the failure mode (accidentally opting a whole route into dynamic rendering) silently destroys your cache hit rate.
The opposing philosophy says: most of a content page is never interactive, so why ship and replay JavaScript for all of it? Islands architecture renders static HTML and hydrates only discrete interactive components ("islands"), with the rest as zero-JS HTML.
For an AI-native CMS, islands are attractive: the body of an AI-drafted article needs no JS, and a sidebar "ask the AI about this page" widget can be a single hydrated island. Astro routinely tops Core Web Vitals and SEO benchmarks for content sites precisely because it ships crawlable HTML with almost no JavaScript (Vero Scale, Astro/Svelte benchmarks).
| Framework | Latest | Rendering model | JS baseline | ISR support | Killer feature for a CMS |
|---|---|---|---|---|---|
| Next.js | 16 (Oct 2025) | SSG + SSR + ISR + PPR, edge; App Router + RSC | 80–120KB React runtime | Best-in-class, on-demand + time-based, ~300ms global purge | PPR, mature draft mode, ISR, huge ecosystem |
| Astro | 5 / 6 | SSG-first + islands + server islands; SSR adapters | ~0KB default | Limited/native gap; via adapters + Cloudflare KV | Content Layer API, zero-JS, server islands |
| SvelteKit | 2 (Svelte 5 runes) | SSG + SSR + edge, file routing | 15–30KB per route | No first-class ISR equivalent | Smallest bundles, simplest mental model |
| Nuxt | 4 (Nitro, Vue 3.5) | Hybrid via routeRules: SSR/SSG/ISR/SWR/edge | Vue runtime, moderate | Yes (ISR + SWR), maps to Vercel/Netlify native rules | routeRules per-route control, Nitro portability |
| React Router 7 (Framework Mode) | v7 (2024–25) | SSR + SSG, Vite-based, loaders/actions | React runtime | Via host platform | Remix DX merged into React Router; app-style UIs |
Two ecosystem shifts deserve attention because they affect long-term framework risk:
Remix merged into React Router. Remix v2 had become a thin wrapper over React Router, so the projects merged: "Remix" features now live in React Router v7 "Framework Mode" (loaders, actions, SSR, Vite compiler, type safety) (remix.run, Merging Remix and React Router). If you want the Remix DX with React, you choose React Router 7.
Remix 3 abandons React entirely. Announced May 2025, with a first stable release targeted for early 2026, Remix 3 is built on a fork of Preact, runs on Fetch API Request/Response primitives, favors "runtime over build steps," and explicitly optimizes its abstractions and docs for LLMs as a design principle (InfoQ; Appwrite, Remix 3). There is no migration path from Remix 2 (byteiota). This makes Remix 3 intriguing for an AI-native project philosophically, but bleeding-edge — not a safe production default in 2026.
This is where many CMS front-ends die. A pure SSG build that renders every page at deploy time scales linearly: 1,000 pages might be tolerable, 10,000 painful, 50,000+ a multi-hour ordeal that blocks every editorial change. There are three viable patterns:
Pattern A — ISR with a hot/cold split (Next.js / Nuxt). Pre-render only the "hot" top ~1,000 pages at build time; serve the long tail on first request and cache it; revalidate everything on a TTL or webhook. For 50K+ page sites this is effectively the only practical approach besides truly incremental builders (PkgPulse; Vercel ISR docs). On Vercel, on-demand revalidation propagates across all regions within ~300ms.
// Next.js: pre-render hot pages, ISR for the rest
export async function generateStaticParams() {
return getTopArticles(1000); // build only the hot set
}
export const revalidate = 3600; // background refresh hourly
// + call revalidatePath('/articles/[slug]') from a CMS webhook on publish
Pattern B — Incremental SSG (Eleventy, Astro caching). Eleventy builds only changed files incrementally, making it viable for very large static sites without server compute. Astro added a build cache, but for true publish-time freshness on huge catalogs you still bolt on ISR-like behavior via Cloudflare KV or an SSR adapter (launchfa.st, Astro ISR on Cloudflare KV).
Pattern C — On-demand SSR + aggressive CDN. Render everything server-side but cache responses with stale-while-revalidate headers. Nuxt's SWR route rule does exactly this: serve the cached response instantly, regenerate in the background when the TTL expires; ISR is the same but persists to the CDN on Vercel/Netlify (nuxt.com, Rendering Modes v4).
The decisive design rule for an AI-native CMS: never tie freshness to a full rebuild. Wire the CMS's "publish" event to an on-demand revalidation webhook (revalidatePath/revalidateTag in Next.js, a cache purge on Nuxt/Astro). Builds should be for code changes; content changes flow through revalidation. This is doubly important when an AI agent can publish dozens of pages per hour — a build-per-publish model would never keep up.
Editors must see unpublished content rendered with full styling before it goes live — and for an AI-CMS, a human reviewing AI-generated drafts is often the core workflow (the human-in-the-loop gate).
Next.js Draft Mode is the reference implementation. A Route Handler calls draftMode().enable(), which sets a cookie; subsequent requests with that cookie bypass the static/ISR cache and switch to dynamic rendering, fetching the latest (draft) content from the CMS at request time (nextjs.org, Draft Mode). Headless CMSs — DatoCMS, Storyblok, Sanity, Optimizely — ship official integrations; Storyblok's Visual Editor appends _storyblok URL params and combines its SDK with draft mode for live, click-to-edit preview.
Astro's gap. Because Astro is SSG-first, it historically had no clean draft-preview story — previewing draft content requires switching to SSR mode at runtime, which Astro doesn't do as gracefully as Next.js or Nuxt (withastro/roadmap discussion #564). The practical workaround is a separate SSR-mode preview deployment, or using server islands to fetch draft content dynamically. This is a real, often-overlooked cost of choosing Astro for an editor-heavy CMS.
Nuxt supports preview via runtime config and the usePreviewMode composable plus routeRules to force SSR on preview routes.
For the AI angle specifically, the preview surface is where you expose provenance and confidence: render AI-drafted sections with a visible "AI-generated, unreviewed" badge in draft mode that disappears on publish, and consider a side-by-side diff of the AI draft vs. the human-edited version. The rendering layer is the natural place to enforce these editorial guardrails.
A 2026 CMS front-end must render for three audiences: humans, search crawlers, and LLM crawlers / agents. This reframes the SSG-vs-SSR debate:
llms.txt — the emerging convention (a Markdown manifest at /llms.txt listing your key pages for LLM consumption) — is something your rendering layer should generate as a build artifact alongside sitemap.xml.Article, FAQPage, Product) should be emitted server-side in the document <head>; both Google and LLM extractors rely on it.routeRules all let one page mix static, edge, and dynamic regions.cacheComponents: true, "use cache") and is Vercel's recommended default; it collapses the historical SSG-vs-SSR tradeoff but is React-specific.llms.txt build artifact make AI-generated content discoverable by the agents and crawlers that increasingly mediate readership.cacheComponents in Next.js 16.routeRules for hybrid SSR/SSG/ISR/SWR and edge rendering via Nitro.