> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/cloudflare/vinext/llms.txt
> Use this file to discover all available pages before exploring further.

# Route Segment Config

> Configure page and route behavior with route segment config options

# Route Segment Config

Route segment config options allow you to configure the behavior of a Page, Layout, or Route Handler by exporting constants.

## Usage

Export configuration constants from `page.tsx`, `layout.tsx`, or `route.ts`:

```tsx filename="app/page.tsx" theme={null}
export const dynamic = 'auto'
export const revalidate = 3600

export default function Page() {
  return <div>My Page</div>
}
```

## Options

### dynamic

Type: `'auto' | 'force-dynamic' | 'force-static' | 'error'`\
Default: `'auto'`

Control static/dynamic rendering behavior.

```tsx filename="app/page.tsx" theme={null}
export const dynamic = 'force-dynamic'

export default function Page() {
  return <div>Always server-rendered</div>
}
```

#### Values

**`'auto'`** (default)\
Automatic detection. Use static rendering unless dynamic APIs are called.

**`'force-dynamic'`**\
Force dynamic rendering. Page is always server-rendered on each request.

Sets `Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate` header.

```tsx filename="app/dashboard/page.tsx" theme={null}
export const dynamic = 'force-dynamic'

export default async function Dashboard() {
  const user = await getCurrentUser()
  return <div>Welcome, {user.name}</div>
}
```

**`'force-static'`**\
Force static rendering. Page is rendered once at build time.

Sets `Cache-Control: public, max-age=31536000, immutable` header.

```tsx filename="app/about/page.tsx" theme={null}
export const dynamic = 'force-static'

export default function About() {
  return <div>About us</div>
}
```

**`'error'`**\
Throw error if dynamic APIs are used. Useful to ensure pages remain fully static.

```tsx filename="app/terms/page.tsx" theme={null}
export const dynamic = 'error'

export default function Terms() {
  // This would throw an error:
  // const headers = await headers()
  
  return <div>Terms of service</div>
}
```

### revalidate

Type: `number | false`\
Default: `false`

Time in seconds until the page is revalidated (ISR).

```tsx filename="app/blog/[slug]/page.tsx" theme={null}
export const revalidate = 60 // Revalidate every 60 seconds

export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params
  const post = await getPost(slug)
  return <article>{post.content}</article>
}
```

#### Values

**`false`** (default)\
No revalidation. Cached indefinitely (or until manually invalidated).

**`0`**\
No caching. Equivalent to `dynamic = 'force-dynamic'`.

**`number`**\
Revalidate after N seconds. Uses stale-while-revalidate strategy:

* Cached responses served instantly
* Background revalidation triggered after expiry
* New version served on next request after revalidation completes

### Route Handlers

Route handlers support `revalidate` for ISR:

```ts filename="app/api/posts/route.ts" theme={null}
export const revalidate = 60

export async function GET() {
  const posts = await getPosts()
  return Response.json(posts)
}
```

Sets `Cache-Control: s-maxage=60, stale-while-revalidate` header.

### dynamicParams

Type: `boolean`\
Default: `true`

Control behavior for dynamic routes not generated by `generateStaticParams`.

```tsx filename="app/blog/[slug]/page.tsx" theme={null}
export const dynamicParams = false

export async function generateStaticParams() {
  return [
    { slug: 'post-1' },
    { slug: 'post-2' }
  ]
}

export default async function Post({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params
  // Only post-1 and post-2 are valid
  // Other slugs will 404
  return <div>Post: {slug}</div>
}
```

#### Values

**`true`** (default)\
Dynamic segments not in `generateStaticParams` are generated on-demand.

**`false`**\
Dynamic segments not in `generateStaticParams` return 404.

### runtime

<Warning>
  Not supported. vinext runs on a single runtime (Node.js dev server or Cloudflare Workers in production). This option is ignored.
</Warning>

Next.js uses this to switch between Node.js and Edge runtimes. vinext deploys everything to the same environment.

```tsx filename="app/api/route.ts" theme={null}
// This is ignored in vinext
export const runtime = 'edge'

export async function GET() {
  return Response.json({ message: 'Hello' })
}
```

### preferredRegion

<Warning>
  Not supported. Cloudflare Workers deploy globally by default. This option is ignored.
</Warning>

Next.js uses this for Vercel's regional deployments. On Cloudflare Workers, all code runs on the edge globally.

```tsx filename="app/api/route.ts" theme={null}
// This is ignored in vinext
export const preferredRegion = 'iad1'

export async function GET() {
  return Response.json({ message: 'Hello' })
}
```

## Combining Options

You can export multiple segment config options:

```tsx filename="app/products/page.tsx" theme={null}
export const dynamic = 'force-static'
export const revalidate = 3600
export const dynamicParams = true

export async function generateStaticParams() {
  return [{ id: '1' }, { id: '2' }]
}

export default async function Products() {
  const products = await getProducts()
  return <div>{/* ... */}</div>
}
```

## ISR with Cache Handler

For production ISR, set a cache handler:

```ts filename="worker/index.ts" theme={null}
import { KVCacheHandler } from 'vinext/cloudflare'
import { setCacheHandler } from 'next/cache'
import handler from 'vinext/server/app-router-entry'

interface Env {
  VINEXT_CACHE: KVNamespace
}

export default {
  async fetch(request: Request, env: Env) {
    setCacheHandler(new KVCacheHandler(env.VINEXT_CACHE))
    return handler.fetch(request)
  }
}
```

See [KV Cache Handler](/api/cloudflare/kv-cache-handler) for details.

## Cache-Control Headers

Route segment config automatically sets appropriate `Cache-Control` headers:

| Config                     | Cache-Control                                             |
| -------------------------- | --------------------------------------------------------- |
| `dynamic: 'force-dynamic'` | `private, no-cache, no-store, max-age=0, must-revalidate` |
| `dynamic: 'force-static'`  | `public, max-age=31536000, immutable`                     |
| `revalidate: 60`           | `s-maxage=60, stale-while-revalidate`                     |
| `revalidate: false`        | No cache header (default)                                 |

## Type Safety

Import types for route segment config:

```tsx filename="app/page.tsx" theme={null}
import type { Metadata } from 'vinext'

export const dynamic = 'force-dynamic' as const
export const revalidate = 60

export const metadata: Metadata = {
  title: 'My Page'
}

export default function Page() {
  return <div>Page</div>
}
```

## Related

* [KV Cache Handler](/api/cloudflare/kv-cache-handler) - Cloudflare KV cache backend
* [revalidateTag/revalidatePath](/api/cache/revalidation) - Manual cache invalidation
* [generateStaticParams](/api/app/generate-static-params) - Static path generation
