Use SwitchPilot with Next.js
Control product features from Next.js server code while keeping project API keys out of the browser.
NEXT_PUBLIC_SWITCHPILOT_API_KEY. SwitchPilot API keys must never be exposed in Client Components or browser code.Install and configure
pnpm add @switchpilot/nodeThe SDK requires Node.js 18 or newer and must run on the server.
Use it in Server Components, Server Actions, Route Handlers, API routes, and backend services inside your Next.js app.
SWITCHPILOT_API_KEY="sp_live_your_project_key"Correct: SWITCHPILOT_API_KEY
Wrong: NEXT_PUBLIC_SWITCHPILOT_API_KEY
Next.js bundles NEXT_PUBLIC_ values into browser code. Never prefix the SwitchPilot API key with NEXT_PUBLIC_.
1. Create a server-only client
Keep one reusable client in a module protected byserver-only.
import "server-only";
import { createSwitchPilot } from "@switchpilot/node";
export const switchpilot = createSwitchPilot({
apiKey: process.env.SWITCHPILOT_API_KEY!,
});2. Use it in a Server Component
import { switchpilot } from "@/lib/switchpilot";
export default async function Page() {
const newDashboard = await switchpilot.isEnabled("new-dashboard");
return (
<main>
{newDashboard ? "New dashboard" : "Old dashboard"}
</main>
);
}- This code runs server-side, where the API key remains private.
- The flag value updates on the next render or request.
- A page already open in the browser will not live-update automatically.
3. Route Handler usage
// app/api/flags/route.ts
import { NextResponse } from "next/server";
import { switchpilot } from "@/lib/switchpilot";
export async function GET() {
const allFlags = await switchpilot.getAll();
return NextResponse.json({ flags: allFlags });
}- The API key stays on the server.
- The browser calls only the local route in your Next.js app.
- Client Components can safely use this route to receive the boolean flag values they need.
4. Live UI updates with safe server-side polling
Put this Client Component in your app after creating the Route Handler above.
"use client";
import { useEffect, useState } from "react";
export function LiveDashboardFlag() {
const [enabled, setEnabled] = useState(false);
useEffect(() => {
async function loadFlag() {
const response = await fetch("/api/flags", {
cache: "no-store",
});
const data = await response.json();
setEnabled(Boolean(data.flags["new-dashboard"]));
}
loadFlag();
const interval = window.setInterval(loadFlag, 60_000);
return () => window.clearInterval(interval);
}, []);
return (
<div>
{enabled ? "New dashboard" : "Old dashboard"}
</div>
);
}- The browser never talks directly to SwitchPilot.
- The browser never receives the SwitchPilot API key.
- This example polls its own server route every 60 seconds.
- Use manual refresh only when the product genuinely needs it.
- For most backend use cases, simple server-side SDK usage is enough.
Cache and fallback behavior
@switchpilot/node caches successful flag responses for 60 seconds by default. Change the duration with cacheTtlMs. Evaluations are local while fresh. If synchronization fails, the SDK uses Last Known Good for five additional minutes by default, then the configured fallback. The default fallback isfalse.
Current platform support
Supported
- Next.js App Router through @switchpilot/node in server-side code
- Node.js backends through @switchpilot/node
- Python backends through switchpilot
Not supported
- Browser SDK or React Provider
- Client-side API key usage
- Realtime WebSocket or SSE updates
- Targeting or percentage rollout