Next.js
Type-safe config for Next.js — inject safe client env, validate in dev, show errors in the overlay, and read config in Server Components and Route Handlers.
This guide covers a complete, ergonomic setup for Next.js (App Router and Pages Router). A working example lives at examples/nextjs
in the repo.
TL;DR
Use @confkit/next
to merge safe client env into next.config
, enable a zero‑boilerplate dev overlay, and import @confkit/next/client
for client env (works in Turbopack and Webpack). The Vite‑style confkit:client
alias is still supported in Webpack builds.
pnpm add confkit @confkit/next
npm i confkit @confkit/next
yarn add confkit @confkit/next
bun add confkit @confkit/next
import { defineConfig, s, source } from 'confkit';
export const config = defineConfig({
sources: [source().env(), source().file('config.yaml')],
schema: {
NODE_ENV: s.enum(['development','test','production']).default('development'),
DATABASE_URL: s.url(),
NEXT_PUBLIC_APP_NAME: s.string().client().default('Confkit Next'),
NEXT_PUBLIC_FEATURE_FLAG: s.boolean().client().default(false),
},
});
import { defineNextConfig } from '@confkit/next';
export default defineNextConfig();
Pass a custom path if needed:
export default defineNextConfig({ file: './conf/config.ts' });
Prefer the dev overlay for validation feedback. If you want to fail fast at boot, enable strict validation in config:
import { defineNextConfig } from '@confkit/next';
export default defineNextConfig({ ensure: true });
What the wrapper does:
- Merges Confkit’s safe client env (only
.client()
keys and well‑known prefixes) intonext.config.env
. - Adds a Webpack alias + loader so
import 'confkit:client'
works in Next - In development, validates your config at build time and surfaces readable errors in Next’s overlay.
Using config in Next.js
- Server Components: import your config and
await config.ready()
. - Route Handlers / API routes: same as above (set
export const runtime = 'nodejs'
). - Client Components: don’t import the server config; read injected env via
process.env.NEXT_PUBLIC_...
.
import config from './conf/config';
export default async function Page() {
const env = await config.ready();
return <pre>{JSON.stringify(env, null, 2)}</pre>;
}
import config from '../../conf/config';
export const runtime = 'nodejs';
export async function GET() {
const redacted = await config.toJSON({ redact: true });
return Response.json({ redacted });
}
'use client';
import env from '@confkit/next/client';
function FromVirtualModule() {
return (
<>
<div>App Name: {env.NEXT_PUBLIC_APP_NAME}</div>
<div>Flag: {String(env.NEXT_PUBLIC_FEATURE_FLAG)}</div>
</>
);
}
export default function ClientEnv() {
return (
<>
<FromProcessEnv />
<FromVirtualModule />
</>
);
}
Client env rules
- Included: keys marked
.client()
or named withPUBLIC_
,NEXT_PUBLIC_
, orEXPO_PUBLIC_
. - Excluded: everything else (secrets, server‑only values).
- Customize: set
clientPrefix
/clientPrefixes
orrequireClientPrefix
indefineConfig
.
Edge runtime
Confkit uses Node APIs to load/validate TypeScript configs. Use the Node.js runtime for middleware and route handlers that touch Confkit: export const runtime = 'nodejs'
.
Middleware
Validate early in development or fail fast in production using a small middleware wrapper:
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { middlewareEnsureConfkit } from '@confkit/next';
export default async function middleware(_req: NextRequest) {
const res = await middlewareEnsureConfkit({ /* file: './conf/config.ts' */ });
return res ?? NextResponse.next();
}
Turbopack and Webpack
- Recommended import for client env:
@confkit/next/client
(no bundler config needed). - The Vite‑style alias
confkit:client
is supported when using Webpack via the Next plugin wrapper; Turbopack does not use Webpack loaders. - The Confkit dev overlay uses a Webpack loader. With Turbopack, prefer enabling
ensure
to fail fast or rely on console errors from server components.
Typing and Troubleshooting
- Auto types: when you use
defineNextConfig
/withConfkit
, Confkit generatesconfkit-env.d.ts
onnext dev
/next build
soimport '@confkit/next/client'
andimport 'confkit:client'
are fully typed. Configure viatypesOutFile
or disable withtypesOutFile: false
. - Manual types: alternatively, run
npx confkit types
(ornpx confkit types --watch
) to generate/updateconfkit-env.d.ts
. - Overlay shows an error but build continues: this is expected — the loader emits an error for the overlay panel without stopping the build. Fix the issues and it clears.
- Client env missing: ensure your key is
.client()
or matches one of the allowed prefixes, and that you wrappednext.config
withwithConfkit(...)
. - TypeScript config not picked up: check the
file
path you pass; default is./conf/config.ts
from CWD.
Complete example
See examples/nextjs
for a ready‑to‑run app demonstrating all of the above.