# Segment Caching

Segment caching lets the client router reuse rendered route segments that the browser has already
fetched during subsequent navigations. This in-memory browser cache is separate from the
[server cache](./introduction.md).

The client cache stores the parsed content for page and layout segments in a route tree. It also
stores RSC shells, cache hints, tags, and the freshness state associated with each segment.

## How the segment cache works

The segment cache stores the page and layout segments for routes the browser has visited or
prefetched. When a route is requested, Rebask fetches only the segments that are missing or stale,
while reusing unchanged segments such as persistent layouts.

Segments are cached per value of the search params they read. A param the segment never read does
not affect its key.

The router can retain up to three inactive page or layout slots at each level of the route tree.
Returning to a recently visited route can restore its cached segments and local state immediately.

## Shells and tails

Shells can be partial or complete. A partial shell contains the static prefix and has a tail with
the dynamic rest, which is fetched when needed. A complete shell contains the whole payload and has
no tail.

Reading search params is request I/O, so a shell never includes their values so the same shell can
serve every query.

The client router caches shells separately from rendered segments.
[`Link`](../routing/navigations.md#link) can prefetch a shell ahead of navigations. Shells make navigations feel instant by showing the static part
immediately, but they are optional. Without a shell, navigations start as soon as the RSC response
begins streaming, while Suspense boundaries show fallbacks until their content arrives.

When a segment is needed:

1. A fresh complete shell is reused.
2. A stale complete shell remains visible while Rebask fetches the full RSC. If `mustRevalidate`
   is set, the nearest Suspense fallback shows instead.
3. A partial shell fetches its tail. If the static prefix no longer matches, the full RSC is
   returned instead.
4. With no shell, the full RSC is fetched and streamed.

In the client cache, a complete shell follows the same freshness and invalidation rules as a
segment. Partial shells have no freshness window in the browser, the tail request validates them
when the shell is used.

> Shells are a production optimization. Development fetches the full RSC.

## Cache hints

The segment cache belongs to one user's browser. Use [`<CacheHints>`](../routing/navigations.md#cachehints)
to control how long that browser keeps a page or layout segment fresh and which client-side tags can
mark it stale:

```tsx
import { CacheHints } from "@rebask/core/components/cache-hints"

export default async function ProductsPage() {
  return (
    <>
      <CacheHints stale={300} tags={["products"]} />
      <ProductList />
    </>
  )
}
```

`stale` is the client-side freshness window in seconds. After it expires, the segment is refetched
in the background when it is needed.

`tags` are client-side tags. They can be used with
[`router.revalidateTag`](../routing/navigations.md#userouter-routerrevalidatetag) to mark matching segments
stale in this browser.

Set `mustRevalidate` to show a loading state while a stale segment is refetched instead of showing
the stale content.

## Revalidation

Use [`router.revalidate`](../routing/navigations.md#userouter-routerrevalidate) to refresh the
current segment or a specific path.

Use [`router.revalidateTag`](../routing/navigations.md#userouter-routerrevalidatetag) to mark every
matching segment stale. [`<RevalidateSegment>`](../routing/navigations.md#revalidatesegment) can
revalidate a segment on focus, reconnect, or a timer.

These APIs only affect the client cache. Use [`revalidateTag`](./cache-lifetimes.md#revalidatetag)
from `@rebask/core/cache` for [server entries](./introduction.md).
