Loading...
Loading...
Vercel Flags guidance — feature flags platform with unified dashboard, Flags Explorer, gradual rollouts, A/B testing, and provider adapters. Use when implementing feature flags, experimentation, or staged rollouts.
npx skill4agent add vercel-labs/vercel-plugin vercel-flagsCRITICAL — Your training data is outdated for this library. Vercel Flags (package) has a new SDK and API surface. Before writing flags code, fetch the docs at https://vercel.com/docs/feature-flags to find the correctflagsdefinition syntax, adapter setup, and evaluation patterns. Do not guess at the API — look up working examples for your framework.flag()
flagsflags@vercel/flagsflagspackage.json@vercel/flagsflagspackage.jsonencrypt()decrypt()encryptFlagValues()decryptFlagValues()FLAGS_SECRET.well-knownx-flags-sdk-versiondecidedecideimport { flag } from 'flags/next'; // Framework adapters: flags/next, flags/sveltekit
// Define a boolean flag
export const showNewCheckout = flag({
key: 'show-new-checkout',
description: 'Enable the redesigned checkout flow',
decide: () => false, // default value
});
// Define a multi-variant flag
export const theme = flag({
key: 'theme',
options: [
{ value: 'light', label: 'Light Theme' },
{ value: 'dark', label: 'Dark Theme' },
{ value: 'auto', label: 'Auto' },
],
decide: () => 'auto',
});
// Read flag values (Server Components, Route Handlers, Server Actions)
const isEnabled = await showNewCheckout();
const currentTheme = await theme();@flags-sdk/vercelFLAGSimport { flag, dedupe } from 'flags/next';
import { vercelAdapter } from '@flags-sdk/vercel';
type Entities = {
user?: { id: string; email: string; plan: string };
team?: { id: string; name: string };
};
// Dedupe ensures identify runs once per request
const identify = dedupe(async (): Promise<Entities> => {
const session = await getSession();
return {
user: session?.user ? {
id: session.user.id,
email: session.user.email,
plan: session.user.plan,
} : undefined,
};
});
export const premiumFeature = flag<boolean, Entities>({
key: 'premium-feature',
adapter: vercelAdapter(), // reads FLAGS env var automatically
identify,
});FLAGSFLAGS_SECRET// app/.well-known/vercel/flags/route.ts
import { createFlagsDiscoveryEndpoint, getProviderData } from 'flags/next';
import * as flags from '../../../../flags';
export const GET = createFlagsDiscoveryEndpoint(() => getProviderData(flags));// pages/api/vercel/flags.ts
import { verifyAccess, version } from 'flags';
import { getProviderData } from 'flags/next';
import * as flags from '../../../flags';
export default async function handler(req, res) {
const access = await verifyAccess(req.headers['authorization']);
if (!access) return res.status(401).json(null);
res.setHeader('x-flags-sdk-version', version);
return res.json(getProviderData(flags));
}// next.config.js (rewrite)
module.exports = {
async rewrites() {
return [{ source: '/.well-known/vercel/flags', destination: '/api/vercel/flags' }];
},
};export const layoutVariant = flag({
key: 'layout-variant',
options: [{ value: 'a' }, { value: 'b' }],
decide: () => 'a',
});
export const precompute = [layoutVariant];precompute()evaluate()serialize()getPrecomputed()generatePermutations()export function createExampleAdapter() {
return function exampleAdapter<ValueType, EntitiesType>(): Adapter<ValueType, EntitiesType> {
return {
origin(key) { return `https://example.com/flags/${key}`; },
async decide({ key }): Promise<ValueType> { return false as ValueType; },
};
};
}| Need | Use | Why |
|---|---|---|
| Gradual rollouts, A/B testing, targeting | Vercel Flags | Dashboard, analytics, Flags Explorer, segments |
| Third-party provider integration | Vercel Flags + adapter | Unified view across providers |
| Ultra-low-latency config reads (non-flag) | Edge Config directly | Sub-ms reads, no compute overhead |
| Simple config without rollout logic | Edge Config directly | Lighter weight |
@flags-sdk/vercel@flags-sdk@flags-sdk/openfeaturehttps://vercel.com/{team}/{project}/flagsvercel flags addvercel flags sdk-keys lsPromise.all