ppr

Configures partial prerendering to serve cached HTML shells with live streaming holes in Rango routes.

Updated Nov 7, 2025
One-click install
npx skills add https://github.com/rangojs/rango --skill ppr-rangojs
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: ppr
Source: https://github.com/rangojs/rango/tree/main/packages/rangojs-router/skills/ppr
Command: npx skills add https://github.com/rangojs/rango --skill ppr-rangojs

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill requires @rangojs/router.

What problem does it solve? Pages that mix a stable layout with live data force a choice between fully dynamic rendering (slow first byte) and full response caching (stale data). This Skill configures Partial Prerendering in the Rango router so the rendered HTML shell is cached and served immediately while designated holes stream fresh content on every request. ## Core Features & Use Cases - One-option opt-in: Add the ppr path option to a page route; the router handles shell capture, storage, and serving with no middleware to mount. - Two hole mechanisms: Use loader() plus loading() for guaranteed-fresh structural holes, or pass un-awaited promises under <Suspense> for physics-based holes with no loader at all. - Middleware-safe commit point: The shell commit happens after the entire middleware chain, so auth guards and redirects always run before any cached byte is served. - Observability and testing: Verify behavior with the x-rango-shell: HIT | MISS header, x-rango-ppr-replay on partial navigations, and helpers like assertShellStatus from @rangojs/router/testing. - Use Case: A product page whose header and layout rarely change but whose price must be live: declare ppr: { ttl: 600, swr: 120 } on the route, register a LivePriceLoader with a loading() fallback, and every visitor gets the cached shell instantly while the price streams in fresh. ## Quick Start Ask the AI to add the ppr path option to a page route in the Rango urls() tree and configure a cache store such as CFCacheStore so the route serves a cached shell with live holes.

Frequently Asked Questions about ppr

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I enable partial prerendering for a route in Rango?

Add the ppr path option to the page route in your urls() tree, for example ppr: true or ppr: { ttl: 600, swr: 120 }. The router serves the shell itself; you only need a createRouter cache store implementing getShell/putShell such as CFCacheStore or MemorySegmentCacheStore.

What is the difference between PPR shell caching and document-cache in Rango?

PPR caches only the rendered HTML shell and keeps designated holes live per request, so loaders stay fresh. document-cache freezes the entire response including loader output, serving all-or-nothing bytes with nothing live on a hit.

Does Rango PPR require a loader to create live holes?

No. A route with no loader can PPR using promise holes: pass an un-awaited promise as a prop and let the consumer suspend under its own Suspense boundary. The boundary postpones at capture and resumes fresh on every hit.

How do I verify PPR is working on my route?

Check the x-rango-shell header on a document GET: the first request reports MISS with a background capture, and later requests report HIT. In tests, use assertShellStatus from @rangojs/router/testing against a real served response.

Why does my ppr route never show a HIT and serve without the header?

A declared ppr route that cannot be honored falls back to plain rendering with no header and a once-per-key warning. Common causes are a cache store missing the shell family, a per-request nonce, or ctx.dynamic() being called in middleware or handlers.

Can middleware and authentication protect a PPR-cached route?

Yes. The shell commit point is after the entire middleware chain, including global router.use() and route DSL middleware. Any rejection, redirect, or 401 runs before a single shell byte is served, on both misses and warmed hits.