Hypertune Toolbar
Overview
The Hypertune Toolbar lets you view and override feature flags directly in your frontend.

Setup
1. Ensure Tailwind CSS is set up
Make sure your project has Tailwind CSS set up and that you are importing its base styles.
2. Create a flag to control visibility
In the Hypertune UI, create a flag called showHypertuneToolbar
. This flag will control whether the Hypertune Toolbar is visible.

3. Set the environment variable
Set the HYPERTUNE_INCLUDE_TOOLBAR
environment variable to true
:
HYPERTUNE_INCLUDE_TOOLBAR=true
4. Regenerate the client
Regenerate the client:
npx hypertune
5. Add the <HypertuneToolbar>
component
<HypertuneToolbar>
componentAdd the generated <HypertuneToolbar>
component to your app, passing it the path to the flag you created earlier via the showFlagPath
prop:
import { HypertuneProvider } from '@/generated/hypertune.react'
import { HypertuneToolbar } from '@/generated/HypertuneToolbar'
import getHypertune from '@/lib/getHypertune'
import './globals.css'
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
const hypertune = await getHypertune()
const dehydratedState = hypertune.dehydrate()
const rootArgs = hypertune.getRootArgs()
return (
<HypertuneProvider
createSourceOptions={{
token: process.env.NEXT_PUBLIC_HYPERTUNE_TOKEN!,
}}
dehydratedState={dehydratedState}
rootArgs={rootArgs}
>
<html lang="en">
<body>
{children}
<HypertuneToolbar showFlagPath="showHypertuneToolbar" />
</body>
</html>
</HypertuneProvider>
)
}
6. Handle overrides on the server
Overrides are stored in a cookie called hypertuneOverride
. If you're using Next.js or hydrating the SDK from the server, update your getHypertune
function to read this cookie and pass it to hypertuneSource.setOverride
:
import 'server-only'
import { DeepPartial } from 'hypertune'
import { unstable_noStore as noStore } from 'next/cache'
import { cookies } from 'next/headers'
import {
createSource,
overrideCookieName,
Source,
} from '@/generated/hypertune'
const hypertuneSource = createSource({
token: process.env.NEXT_PUBLIC_HYPERTUNE_TOKEN!,
})
export default async function getHypertune({
isRouteHandler = false,
}: {
isRouteHandler?: boolean
} = {}) {
noStore()
await hypertuneSource.initIfNeeded()
hypertuneSource.setRemoteLoggingMode(
isRouteHandler ? 'normal' : 'off'
)
hypertuneSource.setOverride(await getOverrideFromCookie())
return hypertuneSource.root({
args: {
context: {
environment: process.env.NODE_ENV,
user: {
id: 'e23cc9a8-0287-40aa-8500-6802df91e56a',
name: 'Example User',
email: '[email protected]',
},
},
},
})
}
async function getOverrideFromCookie(): Promise<DeepPartial<Source> | null> {
try {
const cookieStore = await cookies()
const overrideCookie = cookieStore.get(overrideCookieName)
if (!overrideCookie?.value) {
return null
}
return JSON.parse(overrideCookie.value)
} catch (error) {
console.warn(
`Failed to parse ${overrideCookieName} cookie:`,
error
)
return null
}
}
Last updated