This is a Next.js project that demonstrates how teams can incorporate feature flags and experimentation into their development workflow. This project uses a simple ecommerce website as an example.
This project uses:
- Next.js
- App Router
- RSC (React Server Components) and Suspense
- Server Actions
- Edge Middleware
- Tailwind CSS & shadcn/ui
- The Vercel Toolbar
- Flags
- Experimentation with Optimizely
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
Sign up for a free Optimizely Feature Flags account and create a new project.
The following environment variables are required for running this project. Optimizely environment variables values can be retrieved from app.optimizely.com:
OPTIMIZELY_API_KEY
OPTIMIZELY_SDK_KEY
OPTIMIZELY_PROJECT_ID
FLAGS_SECRET
Create via:node -e "console.log(crypto.randomBytes(32).toString('base64url'))"
Run the development server locally:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
Open http://localhost:3000 with your browser to see the result.
File(s) | Description |
---|---|
/app/[code]/page.tsx |
Static homepage with dynamic segment for multiple variations |
/app/product/[slug]/page.tsx |
Product detail page |
/app/cart/page.tsx |
Cart page |
/app/.well-known/vercel/flags/route.ts |
API route exposing flags to toolbar |
/lib/actions.ts |
File containing server actions (e.g. track purchase event) |
/lib/flags.ts |
Contains declared flags and precomputed flags |
/middleware.ts |
Evaluates precomputed flags, set new shopper cookie |
/lib/products.ts |
A hardcoded set of products |
The following code snippet demonstrates how to create a user context and then execute context.decide
to determine whether a feature should be enabled and what variation should be shown.
const client = optimizely.createInstance({
sdkKey: process.env.OPTIMIZELY_SDK_KEY!,
});
if (!client) {
throw new Error("Failed to create client");
}
await client.onReady();
const context = client.createUserContext("user-1");
if (!context) {
throw new Error("Failed to create user context");
}
const decision = context.decide("buynow");
You can filter and break down your site's page views and custom analytics events by feature flags, helping you gain a deeper understanding of how your flags will impact your users. This granular level of analysis in Web Analytics empowers data-driven decisions, allowing you to optimize your experiments for maximum impact.
reportValue
lets you report the value of a resolved flag, which will make it available when viewing Monitoring, Logs, Analytics and Speed Insights on Vercel. Refer to the Vercel resources for more information.
const decision = context.decide("buynow");
const flag = {
enabled: decision.enabled,
buttonText: decision.variables.buynow_text as string,
};
reportValue("buynow", flag);
The Vercel Toolbar is a tool that assists in the iteration and development process. Through the toolbar, you can leave feedback on deployments with Comments, navigate through important dashboard pages, share deployments, utilize Draft Mode for previewing unpublished content, and Visual Editing for editing content in real-time.
-
Add a
FLAGS_SECRET
environment variable to your project. This must be defined in the environment variables of your Vercel project. The value should be a base64url-encoded string of 32 random bytes. You can generate this value by running the command:node -e "console.log(crypto.randomBytes(32).toString('base64url'))"
. -
Expose the flags to the toolbar via an API route. This route should be defined in the
.well-known/vercel/flags
directory. The route should return an object with the flags that you want to expose to the toolbar.export async function GET(request: NextRequest) { const access = await verifyAccess(request.headers.get("Authorization")); if (!access) return NextResponse.json(null, { status: 401 }); return NextResponse.json<ApiData>(getProviderData(flags)); }
-
Tell the toolbar the value of your flags by including the
<FlagValues />
component when using a flag.// Flag, imported from lib/flags.ts const showGetStarted = await showGetStartedFlag(); return ( <main className="flex min-h-screen flex-col items-center justify-between p-24"> <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex"> {/* Optional: Tells the toolbar about the values of your flags */} <FlagValues values={{ [showGetStartedFlag.key]: showGetStarted }} /> {showGetStarted ? ( <p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4"> Get started by editing <code className="font-mono font-bold">app/page.tsx</code> </p> ) : null} ...
Refer to the Vercel Toolbar documentation for more information on configuring and including the Vercel Toolbar in your application.
Take a look at the following resources to learn more: