# Use Hypertune on static pages

## 1. Set up Hypertune

To use feature flags and run experiments on static pages without layout shift or flickering, first integrate Hypertune using one of the quickstarts:

* [Next.js (App Router) quickstart](/getting-started/next.js-app-router-quickstart.md) with the **(Static) Client Components** setup
* [Next.js (Pages Router) quickstart](/getting-started/next.js-pages-router-quickstart.md) with the **Client-side Rendering** setup

These quickstarts instruct you to wrap your page with the generated `<HypertuneHydrator>` and `<HypertuneRootProvider>` components, passing `dehydratedState` and `rootArgs` from the server. However, while this avoids layout shift, it requires `getHypertune`, which makes the page dynamic.

Instead, this guide shows you how to:

* Generate a static variant of your page for each combination of flag values.
* Use Middleware to route each visitor to the correct variant.

## 2. Define the flags for your page

Create an array with the flags that you want to use on your page:

{% code title="lib/constants.ts" %}

```typescript
import { FlagPath } from '@/generated/hypertune'

export const offerPageFlagPaths: FlagPath[] = [
  'exampleFlag',
  'enableDesignV2',
]
```

{% endcode %}

## 3. Add a Dynamic Segment

Add a Dynamic Segment to your page called `[encodedFlagValues]`. This will hold the encoded flag values in the URL.

Then, on your page:

* Use the generated `decodeFlagValues` function to access flag values.
* Add the generated `<HypertuneClientLogger>` component so flag evaluations and experiment exposures are logged on the client.
* Return an empty array from `generateStaticParams` to enable ISR. This ensures that once a static variant of your page is generated, it is cached and reused.

{% code title="app/offer/\[encodedFlagValues]/page.tsx" %}

```typescript
import { decodeFlagValues } from '@/generated/hypertune'
import { HypertuneClientLogger } from '@/generated/hypertune.react'
import { offerPageFlagPaths } from '@/lib/constants'

export async function generateStaticParams() {
  // Enable ISR
  return []
}

export default async function Page({
  params,
}: {
  params: { encodedFlagValues: string }
}) {
  const { exampleFlag, enableDesignV2 } = decodeFlagValues(
    params.encodedFlagValues,
    offerPageFlagPaths
  )

  return (
    <div>
      <div>Example Flag: {String(exampleFlag)}</div>
      <div>Enable Design V2: {String(enableDesignV2)}</div>
      <HypertuneClientLogger flagPaths={offerPageFlagPaths} />
    </div>
  )
}
```

{% endcode %}

## 4. Encode flags in Middleware

In Middleware, match on your static page, encode the flag values for the visitor, and rewrite the URL to include them:

{% code title="middleware.ts" %}

```typescript
import { NextRequest, NextResponse } from 'next/server'
import { flagFallbacks } from '@/generated/hypertune'
import { offerPageFlagPaths } from '@/lib/constants'
import getHypertune from '@/lib/getHypertune'

export const config = {
  matcher: '/offer',
}

export async function middleware(request: NextRequest) {
  const hypertune = await getHypertune()

  const encodedFlagValues = hypertune.encodeFlagValues({
    flagFallbacks,
    flagPaths: offerPageFlagPaths,
  })

  // Rewrites the request to include the encoded flag values
  const nextUrl = new URL(
    `/offer/${encodedFlagValues}${request.nextUrl.search}`,
    request.url
  )

  return NextResponse.rewrite(nextUrl, { request })
}
```

{% endcode %}

## Summary

1. A visitor requests `/offer`.
2. Middleware computes their flag values, encodes them, and rewrites the request to `/offer/[encodedFlagValues]`.
3. Your page decodes the values and renders the correct static variant.
4. Once generated, that variant is cached via ISR for future visitors who have the same flag values.

## Benefits

* Fully static pages with feature flags and experiments.
* No hydration mismatch, layout shift, or flickering.
* Variants cached at the edge for fast subsequent loads.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hypertune.com/guides/use-hypertune-on-static-pages.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
