# Partial Pre-Rendering (PPR)

Partial Pre-Rendering (PPR) is Rebask's rendering model. It renders and caches as much
of the route as possible: a shell when part of the render depends on the current request, or
complete HTML when the route can be resolved safely without postponed work.

A shell is server-rendered HTML together with the postponed state needed to resume work that could
not be completed during prerendering. Shells can be broad and reusable or more specific to a route,
depending on how much route context is known.

See [Page Caching](../caching/page-caching.md) to learn how Rebask stores, upgrades, and selects shells.

> PPR does not mean every request streams dynamic content. When complete HTML is available, Rebask
> serves it directly.

## Suspense and dynamic work

Wrap dynamic work in `<Suspense>` so Rebask can capture the surrounding content as a PPR shell. The
fallback is included in the initial shell and is replaced when the dynamic content resumes:

```tsx
import { Suspense } from "react"
import { routeParams } from "@rebask/core/request"

export default function ProductPage() {
  return (
    <Suspense fallback={<ProductSkeleton />}>
      <ProductContent />
    </Suspense>
  )
}

async function ProductContent() {
  const { id } = await routeParams<{ id: string }>()
  const product = await getProduct(id)
  return <ProductDetail product={product} />
}
```

Server Runtime APIs such as `headers()`, `cookies()`, `searchParam()`, and unresolved `routeParams()`
create dynamic work. Rebask stops capturing the shell when one of them is read. If the read is inside
`<Suspense>`, the surrounding content becomes the shell and the rest resumes later. Outside
`<Suspense>`, the route has no static shell and renders dynamically.

Async data that does not read a runtime API is not dynamic work. Rebask waits for it to finish and
includes the result in the prerendered output.

See [Server Runtime APIs](../server-runtime-apis.md) for the request helpers and their effect on PPR.

On a cache hit, Rebask rerenders the RSC tree and uses the shell's postponed state to resume the
HTML. See [Advanced concepts](../advanced.md) for what a shell stores and why the tree is rerendered.
