flags-sdk について
flags-sdk は Next.js と SvelteKit 向けの機能フラグツールキットと関連スキルです。フラグを呼び出し可能な関数として宣言し、アダプターで各プロバイダーに接続します。サーバー側評価と事前計算により、レイアウトシフトを避けながら静的ページを利用できます。
主な機能
- 01機能フラグを関数として宣言
- 02アダプターによるプロバイダー接続
- 03サーバー側でのフラグ評価
- 04静的バリアントの事前計算
- 05Next.js と SvelteKit に対応
活用シーン
- 01Next.js アプリへの機能フラグ追加
- 02SvelteKit プロジェクトでのフラグ評価
- 03異なるプロバイダー向けアダプター設定
- 04静的ページを保ちながら表示バリアントを事前計算
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vercel/ flags --skill flags-sdkインストール後、Claude Code で/flags-sdkを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api.mdnextjs.mdproviders.mdsveltekit.md詳細
Flags SDK をセットアップして使用する
Flags SDK(flags npm パッケージ)は、Next.js と SvelteKit 向けのフィーチャーフラグツールキットです。各フィーチャーフラグを呼び出し可能な関数に変換し、アダプターを介してあらゆるフラグプロバイダーに対応し、事前計算パターンを使用してページを静的に保ちます。Vercel Flags はファーストパーティプロバイダーで、そのアダプターは @flags-sdk/vercel です。
- ドキュメント:https://flags-sdk.dev
- リポジトリ:https://github.com/vercel/flags
このスキルではコードを扱います。フラグの計画、Flags SDK、@vercel/flags-core、OpenFeature の選択、ダッシュボードや vercel flags CLI を使ったフラグの管理は、vercel-flags スキルの対象です。フラグのアーカイブ、削除、バリアントの削除には、そのスキルに記載された確認手順が必要です(先にコードを削除し、Skew Protection の期間中に評価がないことを確認してから、アーカイブして rm を実行します)。そのスキルなしにこれらのコマンドを実行しないでください。利用できない場合は npx skills add vercel/flags@vercel-flags を提案し(自動インストールはしないでください)、その間に vercel flags <cmd> --help を実行してください。別のフレームワークを使用するプロジェクトでは、この SDK の代わりに @vercel/flags-core を使用します(Core SDK)。
ユーザーから SDK のインストール、設定、セットアップを依頼された場合は、SDK のセットアップに従ってください(.env.local がない場合は vercel env pull も実行します)。コードへのフラグ追加を依頼された場合は、フラグの作成またはVercel にすでに存在するフラグの追加に従ってください。アプリのリポジトリ内で依頼内容が曖昧な場合は、全手順を実行する依頼として扱ってください。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(@flags-sdk/vercel)はファーストパーティアダプターです。Statsig、LaunchDarkly、PostHog などのサードパーティ製アダプターも利用できます。
import { flag } from 'flags/next';
import { vercelAdapter } from '@flags-sdk/vercel';
export const exampleFlag = flag({
key: 'example-flag',
adapter: vercelAdapter,
});
バージョンに関する注意:SDK は
flagsとして公開されています(@vercel/flagsから改名されました。以前の名前は変更履歴に引き続き記載されています)。flags4.2.0 以降では、アダプターファクトリーを参照渡し(adapter: vercelAdapter)で指定でき、宣言ごとに一度だけ解決されます。古いバージョンでは呼び出しが必要です(adapter: vercelAdapter())。新しいバージョンでも呼び出す形式は引き続き動作するため、flags< 4.2.0 を対象にする場合を除き、省略形を優先してください。
SDK のセットアップ
プロジェクトで一度だけ行うセットアップです。Flags SDK がまだインストールされていない場合や、Toolbar、Flags Explorer、.env.local がない場合に実行してください。完了済みの手順はスキップしてください。
始める前に
プロジェクトの状態を確認し、コマンドを調整してスキップできる手順を判断してください。
- どのロックファイルが存在しますか(
pnpm-lock.yaml、package-lock.json、yarn.lock、bun.lockb)? → それに応じてすべてのパッケージマネージャーコマンドを調整してください(pnpm add、npm install、yarn add、bun add)。 package.jsonにflagsはありますか? → インストールをスキップします(手順 1)- プロジェクトはリンク済みですか? → 手順 2 の
vercel linkをスキップします .env.localにVERCEL_OIDC_TOKEN=(または SDK キーのFLAGS=)が含まれていますか? → 環境変数はすでに取得済みなので、手順 3 をスキップしますpackage.jsonに@vercel/toolbarはありますか? → Toolbar のセットアップをスキップします(手順 4)flags.ts(またはlib/flags.ts、src/flags.ts)は存在しますか? → 作成をスキップします(手順 5)app/.well-known/vercel/flags/route.tsは存在しますか? → Flags Explorer はすでにセットアップ済みなので、手順 6 をスキップします
手順
-
パッケージをインストールする(
package.jsonにまだない場合):pnpm i flags @flags-sdk/vercel -
プロジェクトを Vercel にリンクする(
vercel env pullとローカルでの OIDC トークン更新に必要です):前提条件:Vercel CLI がインストールされ、認証済みである必要があります。インストールされていない場合は、
pnpm i -g vercelを実行してください。認証またはリンクに問題がある場合、vercel-cliスキルがすでに利用可能であれば、その手順に従ってください。利用できない場合は、ユーザーにnpx skills add vercel/vercel@vercel-cliでインストールするよう提案し(自動インストールはしないでください)、その間はvercel <command> --helpを利用してください。vercel project inspect --non-interactiveでリンクを確認し、報告されたオーナーとプロジェクト名を確認してください。.vercel/ディレクトリがあるだけでは、リンクされている証明にはなりません。link_requiredと報告された場合は、vercel linkを実行してください。ユーザーがプロジェクトまたはチームを指定しており、出力が異なる場合は、再リンクせずに作業を中断して確認してください。 -
環境変数を取得する:
.env.localにVERCEL_OIDC_TOKEN=がない場合は、環境変数を取得するに従ってください。 -
Vercel Toolbar を設定する(まだ設定されていない場合):
pnpm i @vercel/toolbarを実行しますnext.config.tsを Toolbar プラグインでラップします- ルートレイアウトで
<VercelToolbar />をレンダリングします コード全体はreferences/nextjs.md — Toolbar の設定を参照してください。
-
flags.tsがあることを確認する:ない場合は、flags.ts(またはプロジェクトに合わせてlib/flags.ts/src/flags.ts)を作成し、TypeScript がモジュールとして扱うようにexport {}を記述してください。Flags Explorer はこのファイルをインポートします。検出ルートを作成する前に、このファイルを作成してください。 -
Flags Explorer を設定する(まだ設定されていない場合):
app/.well-known/vercel/flags/route.tsを作成してください。Flags Explorer の設定を参照してください。flags.tsが存在してから実行してください。インポート先には実際の flags ファイルのパスを指定してください(以下のスニペットではルートのflags.tsを想定しています)。
環境変数を取得する
vercel env pull は Development の認証情報を .env.local に書き込みます。これには、vercelAdapter がローカルで使用する Vercel OIDC トークン(デプロイメントでは自動的に付与されます。はじめにを参照)と、Flags Explorer およびオーバーライド用の Development FLAGS_SECRET が含まれます。次の場合に実行してください。
.env.localにVERCEL_OIDC_TOKEN=(またはFLAGS=SDK キー)がない- プロジェクトで最初のフラグを作成した。Vercel Flags を有効にすると、環境ごとに
FLAGS_SECRETが作成されます - ローカルでの評価が認証エラーになる。SDK はリンク済みプロジェクトを通じて期限切れのトークンを更新します。再取得はその代替手段です
SDK キー(FLAGS)は、Vercel 外部のアプリ、カスタム環境、または別のプロジェクトのフラグでのみ使用します(SDK キーを参照)。取得後も FLAGS_SECRET がない場合は、FLAGS_SECRETに従って生成してください。
フラグを作成する
ユーザーから、まだ Vercel に存在しないフィーチャーフラグの作成または追加を依頼された場合は、以下の手順を順番に実行してください。ダッシュボードですでにフラグが作成されている場合(プロンプトにその旨が記載されている、または vercel flags create でキーがすでに存在すると報告される場合)は、代わりにVercel にすでに存在するフラグを追加するに従ってください。
開始前
- パッケージ、Vercel のリンク、
.env.local、Toolbar、flags.ts、または Flags Explorer がない場合は、先にSDK を設定するを完了してください。すでに完了している手順は省略してください。 .env.localにVERCEL_OIDC_TOKEN=が含まれていますか? → 環境変数は取得済みです。ローカルでの評価が認証エラーになる場合は、環境変数を取得するを参照してください。flags.ts(またはlib/flags.ts、src/flags.ts)は存在しますか? → 一から作成するのではなく、そのファイルに追加してください。
手順
-
SDK がセットアップされていることを確認する:必要に応じてSDK のセットアップに従ってから、次に進みます。
-
Vercel にフラグを登録する:リンク済みのプロジェクトに対して
vercel flags create <flag-key> --kind boolean --description "<description>"を実行するか、--project <name-or-id>と--scope <team>を指定します。フラグの型パラメーターに合った kind を選択してください。後から変更することはできません。 -
環境変数を取得する:このプロジェクトで初めてフラグを作成する場合は、環境変数の取得にもう一度従ってください。有効化によって
FLAGS_SECRETが作成されています。 -
コードでフラグを宣言する:
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 ? 'Feature on' : 'Feature off'}</div>; }
Vercel にすでに存在するフラグを追加する
フラグがダッシュボードで作成された場合や、ほかのユーザーが作成した場合など、プロンプトにフラグが「すでに作成されている」と記載されている場合や、vercel flags inspect の実行が求められている場合は、この手順を使用します。既存のキーに対して vercel flags create を実行しないでください。
- SDK がセットアップされていることを確認する:必要に応じてSDK のセットアップに従います。
- 定義を読み取る:
vercel flags inspect <flag-key>を実行します。kind、バリアント(値とラベル)、説明、および各環境で提供される内容を確認します。 - 環境変数を取得する:
.env.localにVERCEL_OIDC_TOKEN=がない場合は、環境変数の取得に従います。 - フラグを宣言する:
vercelAdapterを使ってflags.tsに追加します。inspectの出力を次のように対応させます。key:出力されたフラグキーをそのまま指定- kind → 型パラメーター:
boolean→flag<boolean>、string→flag<string>、number→flag<number>、json→flag<YourType> description:inspectの出力からコピーdefaultValue:フラグがアーカイブされた場合や評価に失敗した場合に提供する値(通常は現在本番環境で提供されている値)options:任意。事前計算を使用する場合や Flags Explorer に表示する場合は、バリアントに合わせますidentify:フラグにターゲティングがある場合は、ダッシュボードで設定されたエンティティ属性を使って追加するか、既存のものを再利用します(評価コンテキストを含むフラグを参照)
export const welcomeMessage = flag<string>({ key: 'welcome-message', description: 'Copy shown on the landing page', defaultValue: 'control', adapter: vercelAdapter, }); - フラグを作成するの手順 5 と同様に、フラグを使用します。
Vercel Flags アダプター
@flags-sdk/vercel は flag() 宣言を Vercel Flags に接続します。vercelAdapter はプロジェクトの Vercel OIDC トークンで認証し、現在の環境の設定を評価します。SDK キー(FLAGS)は、手動認証が必要な場合にのみ使用します。対象は、Vercel 外のアプリ、カスタム環境、または別のプロジェクトのフラグです(SDK キー)。Vercel Flags を有効にすると、Flags Explorer 用に環境ごとの FLAGS_SECRET が作成されます。
ユーザーターゲティング、属性の型、カスタムアダプターの設定、@vercel/flags-core クライアントの共有、Flags Explorer のエンドポイントについては、references/providers.md — Vercelを参照してください。
フラグが提供する内容(有効化、設定、分割、ロールアウト、ルール、アーカイブ)の変更は、コードではなくダッシュボードまたは vercel flags で行います。これらの手順については vercel-flags スキルを参照してください。オプションの一覧は vercel flags <cmd> --help で確認できます。
フラグの宣言
Vercel Flags を使用する場合は、フラグを作成するに示すように vercelAdapter でフラグを宣言します。ほかのプロバイダーについては、references/providers.mdを参照してください。以下に、一般的な flag() のパターンを示します。
基本的なフラグ
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; },
});
評価コンテキストを使ったフラグ
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);
},
});
vercelAdapter では、返されたオブジェクト内のエンティティ名と属性名(ここでは user.id)が、ダッシュボードのルールおよび vercel flags split|rollout|rules --by の対象になります。これらは、ダッシュボードで設定されたエンティティおよび属性の型と一致している必要があります。references/providers.md — ユーザーターゲティング と 属性の型 を参照してください。
別のアダプターを使ったフラグ
アダプターはフラグをサードパーティープロバイダーに接続します。各アダプターは 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 } };
});
注:Pages Router では dedupe を利用できません。
一括評価
複数のフラグを一度に評価するには、フラグを一つずつ await したり Promise.all() を使用したりする代わりに、evaluate()(flags/next から)を呼び出します。単一のフラグを評価するには、await myFlag() を呼び出すだけです。
import { evaluate } from 'flags/next';
import { flagA, flagB } from '../flags';
// avoid: each await blocks the next, so the flags resolve sequentially
const a = await flagA();
const b = await flagB();
// avoid: parallel, but each flag is evaluated in isolation
const [a, b] = await Promise.all([flagA(), flagB()]);
// prefer: shares work across the batch
const [a, b] = await evaluate([flagA, flagB]);
evaluate() はどちらの方法よりも高速です。フラグを一つずつ await すると、合計レイテンシーは最も遅い単一のフラグではなく、すべてのフラグの評価時間の合計になります。一方、Promise.all() は並列で実行しますが、それぞれを個別に評価します。evaluate() はバッチ全体のヘッダー、Cookie、オーバーライドを一度だけ事前に読み込み、アダプターがグループを一度の呼び出しで解決できるようにします。これにより、ランタイムが管理する並列プロミスの数が減り、非同期処理がほかのマイクロタスクによって中断される余地も小さくなります。
配列(位置順の結果)またはオブジェクト(キー付きの結果)を渡せます。
const [a, b] = await evaluate([flagA, flagB]);
const { a, b } = await evaluate({ a: flagA, b: flagB });
App Router 以外(Pages Router の getServerSideProps/API ルート、またはルーティングミドルウェア)では、リクエストを第 2 引数として渡します:await evaluate([flagA, flagB], request)。
evaluate() は常にリクエスト時にフラグを評価します。事前計算済みの(静的な)値を読み取るためのものではありません。その場合は getPrecomputed を使うか、コードと flagGroup を指定してフラグを呼び出してください(await myFlag(code, flagGroup))。
アダプターは、任意の bulkDecide フックを実装して一括処理に対応できます。Vercel アダプター(@flags-sdk/vercel)はこれを実装しており、数百のフラグを解決する際の評価時間を約 10 分の 1 に短縮します。bulkDecide の実装方法については references/providers.md — カスタムアダプター を、完全なシグネチャーについては references/api.md — evaluate を参照してください。
Flags Explorer のセットアップ
Next.js(App Router)
// app/.well-known/vercel/flags/route.ts
import { createFlagsDiscoveryEndpoint } from 'flags/next';
import { getProviderData } from '@flags-sdk/vercel';
import * as flags from '../../../../flags'; // adjust if flags live under lib/ or src/
export const GET = createFlagsDiscoveryEndpoint(async () => {
return getProviderData(flags);
});
外部プロバイダーのデータを使用する場合
Vercel Flags とサードパーティープロバイダーを併用する場合は、mergeProviderData でそれぞれのデータを統合します。各プロバイダーアダプターは独自の getProviderData をエクスポートします。プロバイダー別の例は、references/providers.md をご覧ください。
SvelteKit
// 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_SECRET
precompute と Flags Explorer に必要です。Vercel Flags を有効にすると、環境ごとに値が作成されます。既存の値を保持し、通常の SDK セットアップ時にはローテーションしないでください。ローカルに値がないからといって、リモートに値がないとは限りません。まず対象の環境を確認してから、Development については 環境変数を取得する の手順に従ってください。
シークレットは、環境に存在しない場合に限り生成してください。暗号学的に安全な乱数を 32 バイト使用し、Base64 でエンコードしたうえで、環境ごとに異なる値を設定します。Preview と Production の値は Sensitive としてマークしてください。生成した値は、vercel env add の標準入力などを使って直接ストレージに渡してください。ターミナル出力、ログ、チャットには表示せず、コマンド引数にも埋め込まないでください。
Precompute パターン
precompute を使用すると、機能フラグを使いながらページを静的に保てます。ミドルウェアでフラグを評価し、rewrite を使って結果を URL にエンコードします。ページでは再評価せず、事前計算された値を読み取ります。
大まかな流れ:
- フラグを宣言し、配列にまとめる
- ミドルウェアで
precompute(flagGroup)を呼び出し、code文字列を取得する - リクエストを
/${code}/original-pathに rewrite する - ページで
codeからフラグの値を読み取る:await myFlag(code, flagGroup)
実装の詳細については、フレームワーク別のリファレンスをご覧ください。
- Next.js:references/nextjs.md をご覧ください。proxy ミドルウェア、precompute のセットアップ、ISR、generatePermutations、複数グループについて説明しています
- SvelteKit:references/sveltekit.md をご覧ください。reroute フック、ミドルウェア、precompute のセットアップ、ISR、プリレンダリングについて説明しています
カスタムアダプター
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} />;
}
React コンポーネント
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: '...' } }} />
リファレンス
コンテキストを簡潔に保つため、フレームワークとプロバイダーの詳細なガイドは別ファイルにまとめられています。
- references/nextjs.md:Next.js のクイックスタート、ツールバー、App Router、Pages Router、ミドルウェア/proxy、precompute、重複排除、ダッシュボードページ、マーケティングページ、Suspense のフォールバック
- references/sveltekit.md:SvelteKit のクイックスタート、ツールバー、フックのセットアップ、reroute とミドルウェアを使った precompute、ダッシュボードページ、マーケティングページ
- references/providers.md:すべてのプロバイダーアダプター — Vercel、Global Config、Statsig、LaunchDarkly、PostHog、GrowthBook、Flagsmith、Reflag、Split、Optimizely、OpenFeature、およびカスタムアダプター
- references/api.md:
flags、flags/react、flags/next、flags/sveltekitの完全な API リファレンス