@vercel/flags API Reference
Learn about available APIs when supporting feature flags in your applicationsThe @vercel/flags
package provides convenience methods, components, and types for supporting feature flag overrides.
- Install the
@vercel/flags
package:
pnpm i @vercel/flags
- Import the methods you require from the
@vercel/flags
package:
import { ... } from '@vercel/flags';
- For Next.js App Router submodules, import
@vercel/flags/next
- For SvelteKit submodules, import
@vercel/flags/sveltekit
Reports the value of a feature flag to Vercel so it can show up in Runtime Logs and be used with Web Analytics custom server-side events. Returns undefined
.
Parameter | Type | Description |
---|---|---|
key | string | Key of the feature flag |
value | any | Value of the feature flag |
import { reportValue } from '@vercel/flags';
reportValue('summer-sale', true);
A method for encrypting data (Flag definitions, overrides, and values). Returns a Promise
.
Parameter | Type | Description |
---|---|---|
data | Object | Data to be encrypted |
secret (Optional) | string | The secret being used to encrypt. Defaults to process.env.FLAGS_SECRET |
Here is an example of encrypting flag values to be used by the Vercel Toolbar.
import { encrypt } from '@vercel/flags';
import { FlagValues, type FlagValuesType } from '@vercel/flags/react';
async function ConfidentialFlagValues({ values }: { values: FlagValuesType }) {
const encryptedFlagValues = await encrypt(values);
return <FlagValues values={encryptedFlagValues} />;
}
export function Page() {
const values = { exampleFlag: true };
return (
<div>
{/* Some other content */}
<Suspense fallback={null}>
<ConfidentialFlagValues values={values} />
</Suspense>
</div>
);
}
A method for decrypting encrypted data. Returns a Promise
.
Parameter | Type | Description |
---|---|---|
encryptedData | string | Data to be decrypted |
secret (Optional) | string | The secret being used to encrypt data. Defaults to process.env.FLAGS_SECRET |
The decrypt
method's primary use case is decrypting the data stored inside the vercel-flag-overrides
cookie. It's also used by the Vercel Toolbar to handle your feature flag data.
import { FlagOverridesType, decrypt } from '@vercel/flags';
import { type NextRequest } from 'next/server';
import { cookies } from 'next/headers';
async function getFlags(request: NextRequest) {
const overrideCookie = cookies().get('vercel-flag-overrides')?.value;
const overrides = overrideCookie
? await decrypt<FlagOverridesType>(overrideCookie)
: {};
const flags = {
exampleFlag: overrides?.exampleFlag ?? false,
};
return flags;
}
A method for verifying whether a request to your application's flags endpoint was made by the Vercel Toolbar.
You can use verifyAccess
to keep your endpoint private. Returns a Promise
with a true
or false
value.
Parameter | Type | Description |
---|---|---|
authHeader . | string | Authorization header to check |
secret (Optional) | string | The secret being used to encrypt data. Defaults to process.env.FLAGS_SECRET |
import { NextResponse, type NextRequest } from "next/server";
import { verifyAccess, type ApiData } from "@vercel/flags";
export async function GET(request: NextRequest) {
const access = await verifyAccess(request.headers.get('Authorization'));
if (!access) return NextResponse.json(null, { status: 401 });
const apiData: ApiData = /* ... */
return NextResponse.json<ApiData>(apiData);
}
A safe version of JSON.stringify
that escapes the resulting output to prevent XSS attacks. Returns string
.
Parameter | Type | Description |
---|---|---|
value | any | A valid JSON object to convert |
replacer (Optional) | function | Array | A replacer function or Array |
space (Optional) | string | number | Specifies the spacing in the output |
import { safeJsonStringify } from '@vercel/flags';
safeJsonStringify({ markup: '<html></html>' });
// '{"markup":"\\u003chtml>\\u003c/html>"}'
The @vercel/flags
package also providers convenience methods for getting flag definition data from certain providers. Each of these functions returns a Promise
.
Get LaunchDarkly flag definitions. Accepts an options
object with the following keys.
Options key | Type | Description |
---|---|---|
apiKey | string | LaunchDarkly API key |
environment | string | LaunchDarkly environment |
projectKey | string | LaunchDarkly project key |
import { verifyAccess, type ApiData } from '@vercel/flags';
import { getLaunchDarklyData } from '@vercel/flags/providers/launchdarkly';
import { NextResponse, type NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const access = await verifyAccess(request.headers.get('Authorization'));
if (!access) return NextResponse.json(null, { status: 401 });
const launchDarklyData = await getLaunchDarklyData({
apiKey: process.env.LAUNCHDARKLY_API_KEY,
projectKey: process.env.LAUNCHDARKLY_PROJECT_KEY,
environment: process.env.LAUNCHDARKLY_ENVIRONMENT,
});
return NextResponse.json<ApiData>(launchDarklyData);
}
Get Split flag definitions. Accepts an options
object with the following keys.
Options key | Type | Description |
---|---|---|
adminApiKey | string | Split admin API key |
workspaceId | string | Split workspace ID |
organizationId | string | Split organization ID |
environmentId | string | Split environment ID |
import { verifyAccess, type ApiData } from '@vercel/flags';
import { getSplitData } from '@vercel/flags/providers/split';
import { NextResponse, type NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const access = await verifyAccess(request.headers.get('Authorization'));
if (!access) return NextResponse.json(null, { status: 401 });
const splitData = await getSplitData({
adminApiKey: process.env.SPLIT_ADMIN_API_KEY,
environmentId: process.env.SPLIT_ENVIRONMENT_ID,
organizationId: process.env.SPLIT_ORG_ID,
workspaceId: process.env.SPLIT_WORKSPACE_ID,
});
return NextResponse.json<ApiData>(splitData);
}
Get StatSig flag definitions. Accepts an options
object with the following keys.
Options key | Type | Description |
---|---|---|
consoleApiKey | string | Statsig console API key |
projectId | string | StatSig project ID |
import { verifyAccess, type ApiData } from '@vercel/flags';
import { getStatsigData } from '@vercel/flags/providers/statsig';
import { NextResponse, type NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const access = await verifyAccess(request.headers.get('Authorization'));
if (!access) return NextResponse.json(null, { status: 401 });
const statsigData = await getStatsigData({
consoleApiKey: process.env.STATSIG_CONSOLE_API_KEY,
projectId: process.env.STATSIG_PROJECT_ID,
});
return NextResponse.json<ApiData>(statsigData);
}
Get Optimizely flag definitions. Accepts an options
object with the following keys.
Options key | Type | Description |
---|---|---|
apiKey | string | Optimizely API key |
projectId | string | Optimizely project ID |
import { verifyAccess, type ApiData } from '@vercel/flags';
import { getOptimizelyData } from '@vercel/flags/providers/optimizely';
import { NextResponse, type NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const access = await verifyAccess(request.headers.get('Authorization'));
if (!access) return NextResponse.json(null, { status: 401 });
const optimizelyData = await getOptimizelyData({
projectId: process.env.OPTIMIZELY_PROJECT_ID,
apiKey: process.env.OPTIMIZELY_API_KEY,
});
return NextResponse.json<ApiData>(optimizelyData);
}
Get Hypertune flag definitions. Accepts an options
object with the following keys.
Options key | Type | Description |
---|---|---|
token | string | The HYPERTUNE_ADMIN_TOKEN |
import { verifyAccess, type ApiData } from '@vercel/flags';
import { getHypertuneData } from '@vercel/flags/providers/hypertune';
import { NextResponse, type NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const access = await verifyAccess(request.headers.get('Authorization'));
if (!access) return NextResponse.json(null, { status: 401 });
const hypertuneData = await getHypertuneData({
token: process.env.HYPERTUNE_ADMIN_TOKEN,
});
return NextResponse.json<ApiData>(hypertuneData);
}
It is possible to integrate feature flag providers that Vercel does not export a dedicated provider function for.
To integrate any feature flag provider:
- First, use the provider's REST API to fetch their feature flags and return them in the expected format through the Flags API Endpoint. This makes Vercel Toolbar aware of the feature flags defined in your flag provider.
- Then, make your application respect the override cookie set by Vercel Toolbar.
As well as convenience methods, the @vercel/flags
package provides types for the different entities.
type JsonArray = ReadonlyArray<JsonValue>;
export type JsonValue =
| string
| boolean
| number
| null
| JsonArray
| { [key: string]: JsonValue };
interface FlagOptionType {
value: JsonValue;
label?: string;
}
export interface FlagDefinitionType {
options?: FlagOptionType[];
/**
* The URL where the feature flag can be managed.
*/
origin?: string;
description?: string;
}
/**
* Definitions of a feature flags.
*
* Definitions are data like the description, available options, or its origin.
*/
export type FlagDefinitionsType = Record<string, FlagDefinitionType>;
/**
* Values of feature flags.
*
* This record consists of key-value pairs of flag keys and the value they resolved to.
*/
export type FlagValuesType = Record<string, JsonValue>;
/**
* Overrides of feature flags.
*
* This record consists of key-value pairs of flag keys and the override to be used for them.
*/
export type FlagOverridesType = Record<string, JsonValue>;
/**
* Data flag providers can return to integrate with the toolbar.
*/
export type ProviderData = {
definitions: FlagDefinitionsType;
hints?: { key: string; text: string }[];
};
/**
* Data returned by the .well-known/vercel/flags API Route which the toolbar understands.
*/
export type ApiData = {
/**
* Metadata about your application's feature flags
*/
definitions?: FlagDefinitionsType;
/**
* Hints show up in the toolbar. They are meant to be used in case loading
* data from your flag provider fails. For example when the provider fails to
* responed or the configuration is invalid due to a missing environment variable.
*/
hints?: ProviderData['hints'];
/**
* Sets the encryption mode for the vercel-flag-overrides cookie
* - when set to "encrypted" the toolbar will store encrypted overrides
* - when set to "plaintext" the toolbar will store plaintext overrides
*/
overrideEncryptionMode: 'encrypted' | 'plaintext';
};
If you are using React, you can use the FlagValues
and FlagDefinitions
components. These abstract you from needing to manually render script
tags.
These components handle setting the correct data attributes and escaping any data to prevent XSS.
Pass flag data into the FlagValues
component with the values
prop.
import { FlagValues } from '@vercel/flags/react';
export function Page() {
return (
<div>
{/* Some other content */}
<FlagValues values={{ exampleFlag: true }} />
</div>
);
}
To keep your flags confidential, encrypt the input:
import { encrypt } from '@vercel/flags';
import { FlagValues, type FlagValuesType } from '@vercel/flags/react';
async function ConfidentialFlagValues({ values }: { values: FlagValuesType }) {
const encryptedFlagValues = await encrypt(values);
return <FlagValues values={encryptedFlagValues} />;
}
export function Page() {
const values = { exampleFlag: true };
return (
<div>
{/* Some other content */}
<Suspense fallback={null}>
<ConfidentialFlagValues values={values} />
</Suspense>
</div>
);
}
Prop | Type | Description |
---|---|---|
values | FlagValuesType | The feature flag values to expose to the Vercel Toolbar |
Pass flag data into the FlagDefinitions
component with the definitions
prop.
import { FlagDefinitions } from '@vercel/flags/react';
export function Page() {
const flagDefinitions = {
exampleFlag: {
options: [{ value: false }, { value: true }],
origin: 'https://example.com/flag/exampleFlag',
description: 'This is an example flag.',
},
};
return (
<div>
{/* Some other content */}
<FlagDefinitions definitions={flagDefinitions} />
</div>
);
}
To keep your flags confidential, encrypt the input:
import { encrypt, type FlagDefinitionsType } from '@vercel/flags';
import { FlagDefinitions } from '@vercel/flags/react';
async function ConfidentialFlagDefinitions({
definitions,
}: {
definitions: FlagDefinitionsType;
}) {
const encryptedFlagDefinitions = await encrypt(definitions);
return <FlagDefinitions values={encryptedFlagDefinitions} />;
}
export function Page() {
const flagDefinitions = {
exampleFlag: {
options: [{ value: false }, { value: true }],
origin: 'https://example.com/flag/exampleFlag',
description: 'This is an example flag.',
},
};
return (
<div>
{/* Some other content */}
<Suspense fallback={null}>
<ConfidentialFlagDefinitions values={flagDefinitions} />
</Suspense>
</div>
);
}
Prop | Type | Description |
---|---|---|
definitions | FlagDefinitionsType | The feature flag definitions to expose to the Vercel Toolbar |
Was this helpful?