shell-manifest

Feeds replayed handle data from cached RSC shells to live loaders for batched fetching.

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

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill requires @rangojs/router.

What problem does it solve? When a cached or prerendered React Server Components shell contains dynamic holes (like live prices on a prerendered product list), the live data layer cannot know what the shell actually rendered. Per-component fetching causes N+1 queries, and re-querying the list in a loader risks drifting from a stale shell. ## Core Features & Use Cases - Replayed handle manifests: Handlers push IDs or keys to a handle at render time; the data is stored with the Flight payload and replayed into the handle store on every cache or prerender hit. - Batched live loading: A DSL loader awaits ctx.rendered(), reads the collected handle data via ctx.get(), and issues one batched query for exactly the items the shell rendered. - Works with Prerender and runtime cache(): The same replay mechanism applies to build-time Prerender shells and runtime segment caches with TTLs and tags. - Use Case: A prerendered product list page where prices must stay live — the shell records rendered product IDs, and a loader fetches prices for exactly those IDs in one query on every request. ## Quick Start Show me how to keep prices live on a prerendered Rango product list page using a handle and a loader that reads the rendered product IDs.

Frequently Asked Questions about shell-manifest

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

FAQPage Schema
How do I fetch live data for a prerendered React Server Components page?

Push item IDs to a handle during the prerendered render, then have a loader await ctx.rendered() and read the replayed IDs with ctx.get() to issue one batched query. The handle data is stored with the payload and replayed on every cache hit.

How do I avoid N+1 queries in cached RSC shells with dynamic content?

Use the shell manifest pattern: the cached shell records which items it rendered via a handle, and a single live loader reads that collected list after the render barrier and fetches all dynamic data in one batched query instead of per-component fetches.

Does the shell manifest pattern work with runtime cache() or only Prerender?

It works with both. Prerender pushes handle data at build time, while cache() pushes on the cache miss; in both cases the handle data is stored with the Flight payload and replayed on every hit, so the loader logic is identical.

Why does ctx.get(handle) throw in my loader?

Calling ctx.get(handle) before awaiting ctx.rendered() throws in a loader, with an error telling you to await the barrier first. The push form ctx.use(Handle) is legal anywhere in the loader body without the barrier.

What are the limitations of ctx.rendered() in Rango loaders?

ctx.rendered() is experimental and DSL-loaders-only. It throws in fetchable or standalone loader calls, in handler-invoked loaders (a detected deadlock), and in loaders registered with { ssr: false }, and it serializes the loader after the shell render.

Can I put request-specific data like cookies into a manifest handle?

No. Manifest handle data is baked into a shared cached artifact, so it must never contain data derived from cookies() or headers(). IDs, slugs, slot names, and variant keys are safe; anything user-specific would leak across requests.