{"content":"# Feature Flags with Flags SDK\n\nImplement feature flags using the Vercel Flags SDK with server-side evaluation, environment-based toggles, and Vercel Toolbar integration.\n\n## Overview\n\nThe Flags SDK is a free, open-source library for implementing feature flags and A/B tests. It works with any flag provider or custom setup and is compatible with App Router, Pages Router, and Middleware.\n\n**Key benefits:**\n\n- Server-side evaluation (no client-side flash)\n- Works with the Vercel Toolbar's Flags Explorer\n- Type-safe flag definitions\n- Zero dependencies on external services\n\n## Installation\n\n```bash\nbun add flags\n```\n\n## Declaring Feature Flags\n\nCreate a flags file in the relevant lib folder. Each domain can manage its own flags:\n\n```ts\n// src/lib/auth/flags.ts\nimport { flag } from \"flags/next\";\n\nexport const vercelSignInFlag = flag({\n  key: \"vercel-sign-in\",\n  decide() {\n    // Enable when environment variables are configured\n    return Boolean(\n      process.env.VERCEL_CLIENT_ID && process.env.VERCEL_CLIENT_SECRET,\n    );\n  },\n});\n```\n\nThe `decide()` function runs on the server and determines the flag's value. You can use:\n\n- Environment variables\n- User session data\n- Random assignment for A/B tests\n- External flag providers\n\n## Using Flags in Server Components\n\nCall the flag function directly in your page or component:\n\n```tsx\n// src/app/sign-in/page.tsx\nimport { vercelSignInFlag } from \"@/lib/auth/flags\";\n\nexport default async function SignInPage() {\n  const showVercelSignIn = await vercelSignInFlag();\n\n  return (\n    <main>\n      <SignIn showVercelSignIn={showVercelSignIn} />\n    </main>\n  );\n}\n```\n\n## Passing Flags to Client Components\n\nSince flags are evaluated server-side, pass the resolved value as a prop:\n\n```tsx\n// Client component receives the flag value as a prop\nexport function SignIn({ showVercelSignIn }: { showVercelSignIn: boolean }) {\n  return (\n    <div>\n      {showVercelSignIn && (\n        <Button onClick={handleVercelSignIn}>Sign in with Vercel</Button>\n      )}\n      {/* Rest of the form */}\n    </div>\n  );\n}\n```\n\n## Flag Patterns\n\n### Environment-Based Flags\n\nEnable features based on environment configuration:\n\n```ts\nexport const stripeFlag = flag({\n  key: \"stripe-enabled\",\n  decide() {\n    return Boolean(process.env.STRIPE_SECRET_KEY);\n  },\n});\n```\n\n### Flags with Validated Config\n\nFor flags that depend on validated environment variables, combine with the [config schema](/recipes/config-schema-setup) pattern. Create a config file that uses the feature flag pattern:\n\n```ts\n// src/lib/stripe/config.ts\nimport { configSchema, server } from \"better-env/config-schema\";\n\nexport const stripeConfig = configSchema(\n  \"Stripe\",\n  {\n    secretKey: server({ env: \"STRIPE_SECRET_KEY\" }),\n    webhookSecret: server({ env: \"STRIPE_WEBHOOK_SECRET\" }),\n  },\n  {\n    flag: {\n      env: \"ENABLE_STRIPE\",\n      value: process.env.ENABLE_STRIPE,\n    },\n  },\n);\n```\n\nThen create a flag that checks the config:\n\n```ts\n// src/lib/stripe/flags.ts\nimport { flag } from \"flags/next\";\nimport { stripeConfig } from \"./config\";\n\nexport const stripeFlag = flag({\n  key: \"stripe-enabled\",\n  decide() {\n    return stripeConfig.isEnabled;\n  },\n});\n```\n\nThis approach validates all required env vars when the feature is enabled, giving clear error messages if any are missing.\n\n### Percentage Rollout\n\nGradually roll out features to a percentage of users:\n\n```ts\nexport const newFeatureFlag = flag({\n  key: \"new-feature\",\n  decide() {\n    return Math.random() < 0.1; // 10% of requests\n  },\n});\n```\n\n### User-Based Flags\n\nEnable features for specific users (requires session context):\n\n```ts\nexport const betaFeatureFlag = flag({\n  key: \"beta-feature\",\n  async decide({ headers }) {\n    // Access user session from headers if needed\n    const session = await getSession(headers);\n    return session?.user?.email?.endsWith(\"@mycompany.com\") ?? false;\n  },\n});\n```\n\n## Flags Explorer (Vercel Toolbar)\n\nWhen deployed to Vercel, the [Flags Explorer](https://vercel.com/docs/workflow-collaboration/feature-flags/flags-explorer) in the Vercel Toolbar lets you override flags for your session without affecting other users.\n\nThis is useful for:\n\n- Testing feature states without changing configuration\n- QA testing different flag combinations\n- Debugging flag-dependent behavior\n\nThe Flags SDK automatically respects overrides set by the Flags Explorer.\n\n## Project Structure\n\nOrganize flags by domain, colocated with related code and config:\n\n```\nsrc/lib/\n├── auth/\n│   ├── config.ts     # Auth environment config\n│   ├── flags.ts      # Auth-related flags\n│   ├── client.ts\n│   └── server.tsx\n├── stripe/\n│   ├── config.ts     # Stripe environment config (with flag)\n│   ├── flags.ts      # Stripe-related flags\n│   └── client.ts\n└── common/\n    └── load-config.ts  # Shared config loader\n```\n\n## References\n\n- [Flags SDK Documentation](https://flags-sdk.dev)\n- [Next.js Integration](https://flags-sdk.dev/frameworks/next)\n- [Vercel Flags Explorer](https://vercel.com/docs/workflow-collaboration/feature-flags/flags-explorer)\n- [Vercel Toolbar](https://vercel.com/docs/workflow-collaboration/vercel-toolbar)"}