flags-sdk by vercel/flags
npx skills add https://github.com/vercel/flags --skill flags-sdkFlags SDK (flags npm 包) 是一个用于 Next.js 和 SvelteKit 的功能开关工具包。它将每个功能开关转换为可调用的函数,通过适配器与任何开关提供商协同工作,并使用预计算模式保持页面静态。Vercel Flags 是第一方提供商,允许您从 Vercel 仪表板或 vercel flags CLI 管理开关。
每个开关都声明为一个函数。调用处无需字符串键:
import { flag } from 'flags/next';
export const exampleFlag = flag({
key: 'example-flag',
decide() { return false; },
});
const value = await exampleFlag();
开关在服务端进行评估,以避免布局偏移、保持页面静态并维护机密性。将路由中间件与预计算模式结合,从 CDN 提供静态变体。
适配器替换开关声明中的 decide 和 origin,将您的开关连接到提供商。Vercel Flags () 是第一方适配器。第三方适配器可用于 Statsig、LaunchDarkly、PostHog 等。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
@flags-sdk/vercelimport { flag } from 'flags/next';
import { vercelAdapter } from '@flags-sdk/vercel';
export const exampleFlag = flag({
key: 'example-flag',
adapter: vercelAdapter(),
});
当用户要求您创建或添加功能开关时,请按顺序执行以下步骤。不要将 CLI 步骤作为“后续步骤”留给用户——请自行执行。
检查项目状态以调整命令并决定可以跳过哪些步骤:
pnpm-lock.yaml, package-lock.json, yarn.lock, bun.lockb)? → 相应地调整所有包管理器命令 (pnpm add, npm install, yarn add, bun add)。package.json 中是否有 flags? → 跳过安装(步骤 1).vercel/ 目录? → 项目已链接,跳过步骤 2 中的 vercel link.env.local 是否包含 FLAGS=? → 环境变量已拉取,跳过步骤 3flags.ts(或 lib/flags.ts, src/flags.ts)? → 添加到现有文件而不是从头创建(步骤 4)package.json 中是否有 @vercel/toolbar? → 跳过工具栏设置(步骤 6)app/.well-known/vercel/flags/route.ts? → Flags Explorer 已设置,跳过步骤 7安装包(如果尚未在 package.json 中):
pnpm i flags @flags-sdk/vercel
向 Vercel 注册开关:运行 vercel flags add <flag-key> --kind boolean --description "<description>"。
前提条件:
vercel flags命令要求安装并验证 Vercel CLI。如果未安装 Vercel CLI,请运行pnpm i -g vercel。对于身份验证或链接问题,请阅读并遵循vercel-cli技能。如果未安装,请运行npx skills add https://github.com/vercel/vercel --skill vercel-cli。
在运行 vercel flags add 之前,请验证项目是否已链接到 Vercel。检查项目根目录中是否存在 .vercel 目录。如果不存在,请先运行 vercel link。
拉取环境变量:运行 vercel env pull 将 FLAGS 和 FLAGS_SECRET 写入 .env.local。没有这些环境变量,vercelAdapter() 将无法评估开关。创建开关后,此步骤是强制性的。
在代码中声明开关:使用 vercelAdapter() 将其添加到 flags.ts(如果文件不存在则创建):
import { flag } from 'flags/next';
import { vercelAdapter } from '@flags-sdk/vercel';
export const myFlag = flag({
key: 'my-flag',
adapter: vercelAdapter(),
});
使用开关:在您的页面或组件中调用它,并根据结果有条件地渲染:
import { myFlag } from '../flags';
export default async function Page() {
const enabled = await myFlag();
return <div>{enabled ? '功能开启' : '功能关闭'}</div>;
}
设置 Vercel 工具栏(如果尚未存在):
pnpm i @vercel/toolbarnext.config.ts<VercelToolbar />
完整代码请参见 references/nextjs.md — 工具栏设置。设置 Flags Explorer(如果尚未存在):创建 app/.well-known/vercel/flags/route.ts — 请参阅下面的 Flags Explorer 设置部分。
Vercel Flags 是 Vercel 的功能开关平台。您可以从 Vercel 仪表板或 vercel flags CLI 创建和管理开关,然后使用 @flags-sdk/vercel 适配器将它们连接到您的代码。当您在 Vercel 中创建开关时,FLAGS 和 FLAGS_SECRET 环境变量会自动配置。
要端到端创建开关,请遵循上述代理工作流。
完整的 Vercel 提供商参考——用户定位、vercel flags CLI 子命令、自定义适配器配置和 Flags Explorer 设置——请参见 references/providers.md。
使用 Vercel Flags 时,请按照代理工作流中所示使用 vercelAdapter() 声明开关。对于其他提供商,请参见 references/providers.md。以下是通用的 flag() 模式。
import { flag } from 'flags/next'; // 或 'flags/sveltekit'
export const showBanner = flag<boolean>({
key: 'show-banner',
description: '显示推广横幅',
defaultValue: false,
options: [
{ value: false, label: '隐藏' },
{ value: true, label: '显示' },
],
decide() { return false; },
});
使用 identify 来建立请求的对象。返回的实体将传递给 decide:
import { dedupe, flag } from 'flags/next';
import type { ReadonlyRequestCookies } from 'flags';
interface Entities {
user?: { id: string };
}
const identify = dedupe(
({ cookies }: { cookies: ReadonlyRequestCookies }): Entities => {
const userId = cookies.get('user-id')?.value;
return { user: userId ? { id: userId } : undefined };
},
);
export const dashboardFlag = flag<boolean, Entities>({
key: 'new-dashboard',
identify,
decide({ entities }) {
if (!entities?.user) return false;
return ['user1', 'user2'].includes(entities.user.id);
},
});
适配器将开关连接到第三方提供商。每个适配器替换 decide 和 origin:
import { flag } from 'flags/next';
import { statsigAdapter } from '@flags-sdk/statsig';
export const myGate = flag({
key: 'my_gate',
adapter: statsigAdapter.featureGate((gate) => gate.value),
identify,
});
所有支持的适配器请参见 references/providers.md。
| 参数 | 类型 | 描述 |
|---|---|---|
key | string | 唯一的开关标识符 |
decide | function | 解析开关值 |
defaultValue | any | 如果 decide 返回 undefined 或抛出异常时的回退值 |
description | string | 在 Flags Explorer 中显示 |
origin | string | 在提供商仪表板中管理开关的 URL |
options | { label?: string, value: any }[] | 可能的值,用于预计算 + Flags Explorer |
adapter | Adapter | 实现 decide 和 origin 的提供商适配器 |
identify | function | 返回 decide 的评估上下文(实体) |
将共享函数(尤其是 identify)包装在 dedupe 中,以便每个请求只运行一次:
import { dedupe } from 'flags/next';
const identify = dedupe(({ cookies }) => {
return { user: { id: cookies.get('uid')?.value } };
});
注意:dedupe 在 Pages Router 中不可用。
// app/.well-known/vercel/flags/route.ts
import { getProviderData, createFlagsDiscoveryEndpoint } from 'flags/next';
import * as flags from '../../../../flags';
export const GET = createFlagsDiscoveryEndpoint(async () => {
return getProviderData(flags);
});
当同时使用第三方提供商和 Vercel Flags 时,使用 mergeProviderData 合并它们的数据。每个提供商适配器都导出自己的 getProviderData — 请参见 references/providers.md 中的提供商特定示例。
// src/hooks.server.ts
import { createHandle } from 'flags/sveltekit';
import { FLAGS_SECRET } from '$env/static/private';
import * as flags from '$lib/flags';
export const handle = createHandle({ secret: FLAGS_SECRET, flags });
预计算和 Flags Explorer 所必需。必须是 32 个随机字节,base64 编码:
node -e "console.log(crypto.randomBytes(32).toString('base64url'))"
存储为 FLAGS_SECRET 环境变量。在 Vercel 上:vc env add FLAGS_SECRET 然后 vc env pull。
使用预计算可以在使用功能开关的同时保持页面静态。中间件评估开关并通过重写将结果编码到 URL 中。页面读取预计算的值而不是重新评估。
高级流程:
precompute(flagGroup),获取 code 字符串/${code}/original-pathcode 读取开关值:await myFlag(code, flagGroup)完整的实现细节,请参见特定框架的参考:
创建一个适配器工厂,返回一个包含 origin 和 decide 的对象。完整模式(包括默认适配器和单例客户端示例),请参见 references/providers.md。
用于在浏览器中保持开关数据机密性(由 Flags Explorer 使用):
| 函数 | 用途 |
|---|---|
encryptFlagValues | 加密已解析的开关值 |
decryptFlagValues | 解密开关值 |
encryptFlagDefinitions | 加密开关定义/元数据 |
decryptFlagDefinitions | 解密开关定义 |
encryptOverrides | 加密工具栏覆盖 |
decryptOverrides | 解密工具栏覆盖 |
默认情况下都使用 FLAGS_SECRET。示例:
import { encryptFlagValues } from 'flags';
import { FlagValues } from 'flags/react';
async function ConfidentialFlags({ values }) {
const encrypted = await encryptFlagValues(values);
return <FlagValues values={encrypted} />;
}
import { FlagValues, FlagDefinitions } from 'flags/react';
// 为 Flags Explorer 渲染包含开关值的 script 标签
<FlagValues values={{ myFlag: true }} />
// 为 Flags Explorer 渲染包含开关定义的 script 标签
<FlagDefinitions definitions={{ myFlag: { options: [...], description: '...' } }} />
详细的框架和提供商指南在单独的文件中,以保持上下文简洁:
flags、flags/react、flags/next 和 flags/sveltekit 的完整 API 参考每周安装量
344
仓库
GitHub 星标数
574
首次出现
2026年2月27日
安全审计
安装于
amp341
gemini-cli341
codex341
kimi-cli340
cursor340
opencode340
The Flags SDK (flags npm package) is a feature flags toolkit for Next.js and SvelteKit. It turns each feature flag into a callable function, works with any flag provider via adapters, and keeps pages static using the precompute pattern. Vercel Flags is the first-party provider, letting you manage flags from the Vercel dashboard or the vercel flags CLI.
Each flag is declared as a function. No string keys at call sites:
import { flag } from 'flags/next';
export const exampleFlag = flag({
key: 'example-flag',
decide() { return false; },
});
const value = await exampleFlag();
Flags evaluate server-side to avoid layout shift, keep pages static, and maintain confidentiality. Combine routing middleware with the precompute pattern to serve static variants from CDN.
Adapters replace decide and origin on a flag declaration, connecting your flags to a provider. Vercel Flags (@flags-sdk/vercel) is the first-party adapter. Third-party adapters are available for Statsig, LaunchDarkly, PostHog, and others.
import { flag } from 'flags/next';
import { vercelAdapter } from '@flags-sdk/vercel';
export const exampleFlag = flag({
key: 'example-flag',
adapter: vercelAdapter(),
});
When a user asks you to create or add a feature flag, follow these steps in order. Do not leave CLI steps as "next steps" for the user — execute them yourself.
Check the project state to adapt commands and decide which steps you can skip:
pnpm-lock.yaml, package-lock.json, yarn.lock, bun.lockb)? → Adapt all package manager commands accordingly (pnpm add, npm install, yarn add, bun add).flags in package.json? → Skip install (step 1).vercel/ directory exist? → Project is linked, skip in step 2Install packages (if not already in package.json):
pnpm i flags @flags-sdk/vercel
Register the flag with Vercel : Run vercel flags add <flag-key> --kind boolean --description "<description>".
Prerequisite : The
vercel flagscommands require the Vercel CLI to be installed and authenticated. If the Vercel CLI is not installed, runpnpm i -g vercel. For authentication or linking issues, read and follow thevercel-cliskill. If it's not installed, runnpx skills add https://github.com/vercel/vercel --skill vercel-cli.
Before running vercel flags add, verify the project is linked to Vercel. Check for a .vercel directory in the project root. If it doesn't exist, run vercel link first.
Pull environment variables : Run vercel env pull to write FLAGS and FLAGS_SECRET to .env.local. Without these environment variables, vercelAdapter() will not be able to evaluate flags. This step is mandatory after creating a flag.
Declare the flag in code : Add it to flags.ts (or create the file if it doesn't exist) using vercelAdapter():
import { flag } from 'flags/next';
import { vercelAdapter } from '@flags-sdk/vercel';
export const myFlag = flag({
key: 'my-flag',
adapter: vercelAdapter(),
});
Vercel Flags is Vercel's feature flags platform. You create and manage flags from the Vercel dashboard or the vercel flags CLI, then connect them to your code with the @flags-sdk/vercel adapter. When you create a flag in Vercel, the FLAGS and FLAGS_SECRET environment variables are configured automatically.
To create a flag end-to-end, follow the Agent workflow above.
For the full Vercel provider reference — user targeting, vercel flags CLI subcommands, custom adapter configuration, and Flags Explorer setup — see references/providers.md.
When using Vercel Flags, declare flags with vercelAdapter() as shown in the Agent workflow. For other providers, see references/providers.md. Below are the general flag() patterns.
import { flag } from 'flags/next'; // or 'flags/sveltekit'
export const showBanner = flag<boolean>({
key: 'show-banner',
description: 'Show promotional banner',
defaultValue: false,
options: [
{ value: false, label: 'Hide' },
{ value: true, label: 'Show' },
],
decide() { return false; },
});
Use identify to establish who the request is for. The returned entities are passed to decide:
import { dedupe, flag } from 'flags/next';
import type { ReadonlyRequestCookies } from 'flags';
interface Entities {
user?: { id: string };
}
const identify = dedupe(
({ cookies }: { cookies: ReadonlyRequestCookies }): Entities => {
const userId = cookies.get('user-id')?.value;
return { user: userId ? { id: userId } : undefined };
},
);
export const dashboardFlag = flag<boolean, Entities>({
key: 'new-dashboard',
identify,
decide({ entities }) {
if (!entities?.user) return false;
return ['user1', 'user2'].includes(entities.user.id);
},
});
Adapters connect flags to third-party providers. Each adapter replaces decide and origin:
import { flag } from 'flags/next';
import { statsigAdapter } from '@flags-sdk/statsig';
export const myGate = flag({
key: 'my_gate',
adapter: statsigAdapter.featureGate((gate) => gate.value),
identify,
});
See references/providers.md for all supported adapters.
| Parameter | Type | Description |
|---|---|---|
key | string | Unique flag identifier |
decide | function | Resolves the flag value |
defaultValue | any | Fallback if decide returns undefined or throws |
Wrap shared functions (especially identify) in dedupe to run them once per request:
import { dedupe } from 'flags/next';
const identify = dedupe(({ cookies }) => {
return { user: { id: cookies.get('uid')?.value } };
});
Note: dedupe is not available in Pages Router.
// app/.well-known/vercel/flags/route.ts
import { getProviderData, createFlagsDiscoveryEndpoint } from 'flags/next';
import * as flags from '../../../../flags';
export const GET = createFlagsDiscoveryEndpoint(async () => {
return getProviderData(flags);
});
When using a third-party provider alongside Vercel Flags, combine their data with mergeProviderData. Each provider adapter exports its own getProviderData — see the provider-specific examples in references/providers.md.
// src/hooks.server.ts
import { createHandle } from 'flags/sveltekit';
import { FLAGS_SECRET } from '$env/static/private';
import * as flags from '$lib/flags';
export const handle = createHandle({ secret: FLAGS_SECRET, flags });
Required for precompute and Flags Explorer. Must be 32 random bytes, base64-encoded:
node -e "console.log(crypto.randomBytes(32).toString('base64url'))"
Store as FLAGS_SECRET env var. On Vercel: vc env add FLAGS_SECRET then vc env pull.
Use precompute to keep pages static while using feature flags. Middleware evaluates flags and encodes results into the URL via rewrite. The page reads precomputed values instead of re-evaluating.
High-level flow:
precompute(flagGroup) in middleware, get a code string/${code}/original-pathcode: await myFlag(code, flagGroup)For full implementation details, see framework-specific references:
Create an adapter factory that returns an object with origin and decide. For the full pattern (including default adapter and singleton client examples), see references/providers.md.
For keeping flag data confidential in the browser (used by Flags Explorer):
| Function | Purpose |
|---|---|
encryptFlagValues | Encrypt resolved flag values |
decryptFlagValues | Decrypt flag values |
encryptFlagDefinitions | Encrypt flag definitions/metadata |
decryptFlagDefinitions | Decrypt flag definitions |
encryptOverrides | Encrypt toolbar overrides |
decryptOverrides |
All use FLAGS_SECRET by default. Example:
import { encryptFlagValues } from 'flags';
import { FlagValues } from 'flags/react';
async function ConfidentialFlags({ values }) {
const encrypted = await encryptFlagValues(values);
return <FlagValues values={encrypted} />;
}
import { FlagValues, FlagDefinitions } from 'flags/react';
// Renders script tag with flag values for Flags Explorer
<FlagValues values={{ myFlag: true }} />
// Renders script tag with flag definitions for Flags Explorer
<FlagDefinitions definitions={{ myFlag: { options: [...], description: '...' } }} />
Detailed framework and provider guides are in separate files to keep context lean:
flags, flags/react, flags/next, and flags/sveltekitWeekly Installs
344
Repository
GitHub Stars
574
First Seen
Feb 27, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
amp341
gemini-cli341
codex341
kimi-cli340
cursor340
opencode340
D1 Drizzle Schema:为Cloudflare D1生成正确ORM模式,避免SQLite差异错误
569 周安装
Monorepo 包链接指南:pnpm/npm/yarn/bun 工作区依赖管理详解
540 周安装
Sensei:GitHub Copilot for Azure技能合规性自动化改进工具
617 周安装
Google Apps Script 自动化脚本教程 - 免费实现 Google Sheets 与 Workspace 自动化
573 周安装
PowerPoint自动化生成工具:HTML转PPT,高保真布局与模板编辑工作流
558 周安装
AWS SDK Java 2.x DynamoDB 开发指南:增强客户端、事务与Spring Boot集成
332 周安装
vercel link.env.local contain FLAGS=? → Env vars already pulled, skip step 3flags.ts (or lib/flags.ts, src/flags.ts) exist? → Add to it rather than creating from scratch (step 4)@vercel/toolbar in package.json? → Skip toolbar setup (step 6)app/.well-known/vercel/flags/route.ts exist? → Flags Explorer already set up, skip step 7Use the flag : Call it in your page or component and conditionally render based on the result:
import { myFlag } from '../flags';
export default async function Page() {
const enabled = await myFlag();
return <div>{enabled ? 'Feature on' : 'Feature off'}</div>;
}
Set up the Vercel Toolbar (if not already present):
pnpm i @vercel/toolbarnext.config.ts with the toolbar plugin<VercelToolbar /> in the root layout See references/nextjs.md — Toolbar Setup for the full code.Set up Flags Explorer (if not already present): Create app/.well-known/vercel/flags/route.ts — see the Flags Explorer setup section below.
description | string | Shown in Flags Explorer |
origin | string | URL to manage the flag in provider dashboard |
options | { label?: string, value: any }[] | Possible values, used for precompute + Flags Explorer |
adapter | Adapter | Provider adapter implementing decide and origin |
identify | function | Returns evaluation context (entities) for decide |
| Decrypt toolbar overrides |