@arkenv/nextjs

Next.js integration framework for ArkEnv.

Edit on GitHub

@arkenv/nextjs adds Next.js-aware arkenv() entries, build-time validation, and .arkenv codegen. Setup recipes: Next.js guide.

Installation

npm install @arkenv/core @arkenv/nextjs arktype
pnpm add @arkenv/core @arkenv/nextjs arktype
yarn add @arkenv/core @arkenv/nextjs arktype
bun install @arkenv/core @arkenv/nextjs arktype

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

npm install @arkenv/standard @arkenv/nextjs zod
pnpm add @arkenv/standard @arkenv/nextjs zod
yarn add @arkenv/standard @arkenv/nextjs zod
bun 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
./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'",
});

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
standardfalseStandard Schema codegen
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.

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

Next steps