@arkenv/nextjs

Next.js integration framework for ArkEnv.

Edit on GitHub

Next.js does not validate an env schema during next dev or next build on its own. @arkenv/nextjs adds that check, Next-aware arkenv() entries, and .arkenv codegen. This page is the subpath and option list. Setup recipes live in the Next.js guide.

Flat arkenv(schema, { exposeToClient }) is the only call shape. Nested bags and expose / shared aliases were removed — see Migrating to v1.

Installation

Install the adapter next to the engine you write schemas with. The adapter does not bundle @arkenv/core or @arkenv/standard.

npm install @arkenv/core @arkenv/nextjs arktype

Or if you use Zod, Valibot, or another Standard Schema validator:

npm install @arkenv/standard @arkenv/nextjs zod

Subpaths

SubpathRole
.Unified arkenv (react-server condition for RSC, default for client/SSR)
./configwithArkEnv, runCodegen, config types
./standardStandard Schema unified entry (react-server for RSC, default for client)
./standard/configStandard withArkEnv (forces Standard codegen)

withArkEnv options

./next.config.ts
import type { NextConfig } from "next";
import { withArkEnv } from "@arkenv/nextjs/config";

const nextConfig: NextConfig = {};

export default withArkEnv(nextConfig);

Function-form next.config is supported. ArkEnv awaits the factory and applies aliases to the resolved object:

./next.config.ts
import type { NextConfig } from "next";
import { withArkEnv } from "@arkenv/nextjs/config";

export default withArkEnv(async (phase, { defaultConfig }): Promise<NextConfig> => ({
  ...defaultConfig,
  reactStrictMode: phase !== "phase-test",
}));

Your app schema imports the generated factory:

./env.ts
import arkenv from "@/.arkenv";

export const env = arkenv({
  DATABASE_URL: "string",
  NEXT_PUBLIC_API_URL: "string = 'https://api.example.com'",
  NODE_ENV: "'development' | 'production' | 'test' = 'development'",
});

Zod and Valibot import withArkEnv from @arkenv/nextjs/standard/config. See Standard Schema codegen.

withArkEnv options

Pass a second argument to change codegen or validation.

OptionDefaultMeaning
codegentrueWrite env.gen.ts
validatetrueValidate during config/build
schemaPathautoSchema entry path
outputPathautoGenerated file path
loggerconsoleBuild-time logger
logLevel(none)Minimum log level

A custom outputPath still imports as @/.arkenv. Next.js aliases the specifier; codegen keeps .arkenv/index.ts re-exporting that file so tsc --noEmit matches.

Skip generation during CLI scaffolds with npx arkenv init --no-codegen.

Programmatic codegen

import { runCodegen } from "@arkenv/nextjs/config";

await runCodegen(schemaPath, outputPath);

Standard Schema codegen

Import withArkEnv from @arkenv/nextjs/standard/config to force Standard Schema-compatible generated imports.

./next.config.ts
import { withArkEnv } from "@arkenv/nextjs/standard/config";

export default withArkEnv(nextConfig);

Client and server keys

Public keys use the NEXT_PUBLIC_ prefix. One schema file plus a runtime Proxy blocks server-key reads on the client.

. and ./standard publish the same export conditions. Next.js resolves react-server in Server Components and Route Handlers, so those imports see every schema key. Client Components and SSR resolve default, which exposes public keys only. Generated env.gen.ts still imports @arkenv/nextjs or @arkenv/nextjs/standard. The bundler selects the build from the importing context.

For name/type isolation beyond values, see the two-module recipe.

Next steps