Fargo Flags
Enhanced toolkit built on Vercel's Flags SDK with CLI tools, component registry, and streamlined developer experience.
๐ค Built on Vercel's Flags SDK
Fargo Flags is a thin layer of abstraction that enhances Vercel's Flags SDK with streamlined tooling and distribution. We embrace the same core principles while making them easier to adopt and scale.
๐๏ธ Flags SDK Foundation
- โFlags as code - declarative definitions with consistent call sites
- โServer-side resolution - secure, performant flag evaluation
- โType safety - full TypeScript support with runtime validation
- โNo vendor lock-in - your flag logic stays in your codebase
๐ Fargo Enhancements
- +Interactive CLI wizard for guided flag creation
- +Automatic registry management - no manual imports
- +Component registry distribution via shadcn CLI
- +Enhanced React components and testing utilities
- +Consistency validation for CI/CD pipelines
๐ก Why This Approach?
The Flags SDK provides excellent architectural patterns, but setting up the boilerplate and maintaining consistency across a growing codebase can be tedious. Fargo Flags automates the repetitive parts while preserving all the benefits of the "flags as code" approach.
โจ Key Features
๐ฏ One File Per Flag
Each feature flag lives in its own file with schema, defaults, and decision logic.
๐ Type Safety
Full TypeScript support with Zod schemas for runtime validation.
๐ No Build Step
Static imports with checked-in aggregator. No codegen required.
๐ SSR First
Resolve flags on the server, hydrate client-safe subset.
๐ง Developer Tools
Wizard for creating flags, consistency checker for CI.
๐งช Testing Ready
Test provider for overriding flags in tests and Storybook.
๐ Getting Started
๐ฆ Installation
1. Install core system:
2. Install CLI tools:
3. Add package.json scripts:
โก Quick Start
1. Create your first flag:
2. Validate consistency:
๐งโโ๏ธ Interactive Wizard
The CLI wizard guides you through creating flags with prompts for type, default value, client exposure, and more.
๐๏ธ Architecture & How It Works
๐ Directory Structure
lib/flags/ โโโ kit.ts # Core types โโโ runtime.ts # Server resolver โโโ registry.config.ts # Aggregator โโโ defs/ # Flag definitions โโโ feature-a.flag.ts โโโ feature-b.flag.ts components/flags/ โโโ flags-provider.tsx # React context โโโ flag.tsx # Conditional component โโโ flags-test-provider.tsx # Testing utilities
โก Resolution Flow
defs/*.flag.ts
filesregistry.config.ts
automatically<Flag>
wrapperโก resolveAllFlags() Engine
The server-side engine that evaluates all your feature flags and returns their resolved values.
๐ The Resolution Process
decide()
function with contextdefaultValue
if no decide function๐ฏ Usage Patterns
Basic Usage
await resolveAllFlags()
Simple flags using defaultValue
With Context
await resolveAllFlags({ getUser, getWorkspace })
Personalized flags with user data
In API Routes
const flags = await resolveAllFlags(ctx)
Server-side flag access
๐ Security & Performance
Server-Only Execution
All decision logic runs securely on the server
Parallel Processing
All flags resolve simultaneously for speed
๐ Interactive Demo & Components
Try changing the flag values below to see how they instantly affect the UI components. Plus explore the React components that make working with feature flags seamless.
๐ค AI Assistant Feature
DISABLEDFlag: enable-ai-assistant-in-pdf-toolbar
๐๏ธ Try It Yourself
Watch the PDF toolbar update instantly when you toggle this flag!
๐ Pagination Layout
BOTTOMFlag: pagination-ui-location
๐๏ธ Try It Yourself
See how the pagination controls move around the content area!
๐จ Theme Mode
LIGHTFlag: theme-mode
๐๏ธ Try It Yourself
Watch the theme change instantly across the entire interface!
๐งฉ React Components
Fargo Flags comes with several React components to make working with feature flags seamless.
๐ช useFlag Hook
Get flag values directly in your components with full type safety.
๐ท๏ธ <Flag> Component
Conditionally render content based on flag values.
๐ FlagsProvider
Integrates with Next.js App Router for SSR-first flag resolution.
๐งช FlagsTestProvider
Override flag values for testing and development.
๐ก Pro Tip
All components are fully typed! Your IDE will provide autocomplete for flag names and values, catching typos at compile time instead of runtime.
๐ป Code Examples
1. Define a Flag
// lib/flags/defs/my-feature.flag.ts import { z } from "zod"; import { defineFlag } from "../kit"; export const key = "my-awesome-feature" as const; export const schema = z.boolean(); export default defineFlag({ key, schema, description: "Enable my awesome new feature", defaultValue: false, client: { public: true }, async decide(ctx) { const user = await ctx.getUser?.(); return user?.plan === "premium"; }, });
2. Use in Components
import { useFlag } from "@/components/flags/flags-provider"; import { Flag } from "@/components/flags/flag"; function MyComponent() { const isEnabled = useFlag("my-awesome-feature"); return ( <div> <h1>My App</h1> {/* Using the hook */} {isEnabled && <NewFeatureButton />} {/* Using the component */} <Flag when="my-awesome-feature"> <NewFeaturePanel /> </Flag> </div> ); }
3. Next.js App Router Integration
// app/layout.tsx (Server Component) import { resolveAllFlags, pickClientFlags } from "@/lib/flags/runtime"; import { FlagsProvider } from "@/components/flags/flags-provider"; export default async function RootLayout({ children }) { // ๐ resolveAllFlags() runs on the server and: // - Calls each flag's decide() function with context // - Validates results against Zod schemas // - Returns ALL flags (including server-only ones) const serverFlags = await resolveAllFlags({ getUser: async () => getCurrentUser(), getWorkspace: async () => getCurrentWorkspace(), }); // ๐ pickClientFlags() creates client-safe subset: // - Only includes flags with client: { public: true } // - Applies optional serialize() functions // - Excludes sensitive server-only flags const clientFlags = pickClientFlags(serverFlags); return ( <html lang="en"> <body> <FlagsProvider flags={clientFlags}> {children} </FlagsProvider> </body> </html> ); }
4. Testing with Overrides
import { FlagsTestProvider } from "@/components/flags/flags-test-provider"; function MyStory() { return ( <FlagsTestProvider overrides={{ "my-awesome-feature": true }} > <MyComponent /> </FlagsTestProvider> ); }