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

# Switch to Hypertune

> How to change the feature flag provider to Hypertune.

export const Authors = ({data}) => {
  const baseUrl = typeof window !== 'undefined' && window.location.origin.includes('localhost') ? '' : 'https://raw.githubusercontent.com/haydenbleasel/JTBDOS/refs/heads/main/docs';
  return <div style={{
    marginBottom: '3rem',
    display: 'flex',
    flexDirection: 'column',
    gap: '0.5rem'
  }}>
      <span style={{
    color: 'rgb(107, 114, 128)',
    fontSize: '0.875rem'
  }}>Co-authored by</span>
      <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    alignItems: 'center',
    gap: '0.5rem'
  }}>
        {data.map(author => <div key={author.name} style={{
    padding: '0.75rem',
    paddingRight: '1rem',
    display: 'inline-flex',
    alignItems: 'center',
    gap: '0.75rem',
    fontWeight: 'normal',
    position: 'relative',
    ringWidth: '2px',
    ringColor: 'transparent',
    borderRadius: '0.75rem',
    backgroundColor: 'white',
    border: '1px solid rgba(0,0,0,0.1)',
    overflow: 'hidden'
  }}>
            <div style={{
    position: 'relative'
  }}>
              <div style={{
    overflow: 'hidden',
    border: '1px solid #e5e7eb',
    borderRadius: '9999px',
    width: '2rem',
    height: '2rem'
  }}>
                <img style={{
    margin: 0,
    width: '100%',
    height: '100%',
    objectFit: 'cover'
  }} src={`${baseUrl}/images/authors/${author.company.id}/${author.user.id}.jpg`} alt="" width={32} height={32} />
              </div>
              <div style={{
    position: 'absolute',
    border: '1px solid white',
    overflow: 'hidden',
    borderRadius: '9999px',
    objectFit: 'cover',
    width: '1rem',
    height: '1rem',
    right: '-0.25rem',
    bottom: '-0.25rem'
  }}>
                <img style={{
    margin: 0,
    width: '100%',
    height: '100%',
    objectFit: 'cover'
  }} src={`${baseUrl}/images/authors/${author.company.id}/logo.jpg`} alt="" width={16} height={16} />
              </div>
            </div>
            <div style={{
    display: 'flex',
    flexDirection: 'column'
  }}>
              <span style={{
    fontWeight: 600,
    lineHeight: 1.25,
    fontSize: '13px',
    letterSpacing: '-0.01em'
  }}>
                {author.user.name}
              </span>
              <span style={{
    color: 'rgb(107, 114, 128)',
    lineHeight: 1.25,
    fontSize: '11px'
  }}>
                {author.company.name}
              </span>
            </div>
          </div>)}
      </div>
    </div>;
};

<Authors
  data={[{
user: {
name: 'Hayden Bleasel',
id: 'haydenbleasel',
},
company: {
name: 'JTBDOS',
id: 'JTBDOS',
},
}, {
user: {
name: 'Michal Bock',
id: 'michalbock',
},
company: {
name: 'Hypertune',
id: 'hypertune',
},
}, {
user: {
name: 'Miraan Tabrez',
id: 'miraantabrez',
},
company: {
name: 'Hypertune',
id: 'hypertune',
},
}]}
/>

[Hypertune](https://www.hypertune.com/) is the most flexible platform for feature flags, A/B testing, analytics and app configuration. Built with full end-to-end type-safety, Git version control and local, synchronous, in-memory flag evaluation. Optimized for TypeScript, React and Next.js.

Here's how to switch your JTBDOS project to use Hypertune for feature flags!

## 1. Create a new Hypertune project

Go to Hypertune and create a new project using the [JTBDOS template](https://app.hypertune.com/?new_project=1\&new_project_template=JTBDOS). Then go to the Settings page of your project and copy the main token.

## 2. Update the environment variables

Update the environment variables across the project. For example:

```js apps/app/.env
// Add this:
NEXT_PUBLIC_HYPERTUNE_TOKEN=""
```

Add a `.env` file to the `feature-flags` package with the following contents:

```js packages/feature-flags/.env
NEXT_PUBLIC_HYPERTUNE_TOKEN=""
HYPERTUNE_FRAMEWORK=nextApp
HYPERTUNE_OUTPUT_DIRECTORY_PATH=generated
HYPERTUNE_PLATFORM=vercel
HYPERTUNE_GET_HYPERTUNE_IMPORT_PATH=../lib/getHypertune
```

## 3. Update the `keys.ts` file in the `feature-flags` package

Use the `NEXT_PUBLIC_HYPERTUNE_TOKEN` environment variable in the call to `createEnv`:

```ts packages/feature-flags/keys.ts {6-8,14}
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';

export const keys = () =>
  createEnv({
    client: {
      NEXT_PUBLIC_HYPERTUNE_TOKEN: z.string().min(1),
    },
    server: {
      FLAGS_SECRET: z.string().min(1).optional(),
    },
    runtimeEnv: {
      FLAGS_SECRET: process.env.FLAGS_SECRET,
      NEXT_PUBLIC_HYPERTUNE_TOKEN: process.env.NEXT_PUBLIC_HYPERTUNE_TOKEN,
    },
  });
```

## 4. Swap out the required dependencies

First, delete the `create-flag.ts` file.

Then, uninstall the existing dependencies from the `feature-flags` package:

```sh Terminal
pnpm remove @repo/analytics --filter @repo/feature-flags
```

Then, install the new dependencies:

```sh Terminal
pnpm add hypertune server-only --filter @repo/feature-flags
```

## 5. Set up Hypertune code generation

Add `analyze` and `build` scripts to the `package.json` file for the `feature-flags` package, which both execute the `hypertune` command:

```json packages/feature-flags/package.json
{
  "scripts": {
    "analyze": "hypertune",
    "build": "hypertune"
  }
}
```

Then run code generation with the following command:

```sh Terminal
pnpm build --filter @repo/feature-flags 
```

This will generate the following files:

```txt
packages/feature-flags/generated/hypertune.ts
packages/feature-flags/generated/hypertune.react.tsx
packages/feature-flags/generated/hypertune.vercel.tsx
```

## 6. Set up Hypertune client instance

Add a `getHypertune.ts` file in the `feature-flags` package which defines a `getHypertune` function that returns an initialized instance of the Hypertune SDK on the server:

```ts packages/feature-flags/lib/getHypertune.ts
import 'server-only';
import { auth } from '@repo/auth/server';
import { unstable_noStore as noStore } from 'next/cache';
import type { ReadonlyHeaders } from 'next/dist/server/web/spec-extension/adapters/headers';
import type { ReadonlyRequestCookies } from 'next/dist/server/web/spec-extension/adapters/request-cookies';
import { createSource } from '../generated/hypertune';
import { getVercelOverride } from '../generated/hypertune.vercel';
import { keys } from '../keys';

const hypertuneSource = createSource({
  token: keys().NEXT_PUBLIC_HYPERTUNE_TOKEN,
});

export default async function getHypertune(params?: {
  headers?: ReadonlyHeaders;
  cookies?: ReadonlyRequestCookies;
}) {
  noStore();
  await hypertuneSource.initIfNeeded(); // Check for flag updates

  const { userId, orgId, sessionId } = await auth();

  // Respect flag overrides set by the Vercel Toolbar
  hypertuneSource.setOverride(await getVercelOverride());

  return hypertuneSource.root({
    args: {
      context: {
        environment: process.env.NODE_ENV,
        user: { id: userId ?? '', sessionId: sessionId ?? '' },
        org: { id: orgId ?? '' },
      },
    },
  });
}
```

## 7. Update `index.ts`

Hypertune automatically generates feature flag functions that use the `@vercel/flags` package. To export them the same way as before, update the `index.ts` file to export everything from the `generated/hypertune.vercel.ts` file:

```ts packages/feature-flags/index.ts
export * from "./generated/hypertune.vercel.tsx"
```

Hypertune adds a `Flag` suffix to all these generated feature flag functions, so you will need to update flag usages with this, e.g. `showBetaFeature` => `showBetaFeatureFlag`.

## 8. Add more feature flags

To add more feature flags, create them in the Hypertune UI and then re-run code generation. They will be automatically added to your generated files.
