npm.io
0.1.1 • Published 2d ago

@arkenv/nextjs

Licence
MIT
Version
0.1.1
Deps
4
Size
194 kB
Vulns
0
Weekly
299

@arkenv/nextjs

ArkEnv integration for Next.js. Provides a typesafe, zero-dependency (except peer dependencies) environment variable parser and validator for Next.js applications, with automatic code generation to eliminate manual runtimeEnv boilerplate.

Installation

pnpm add @arkenv/nextjs arktype

Setup & Codegen

Next.js requires client-side environment variables to be statically destructured (process.env.NEXT_PUBLIC_...) to allow static inlining during bundling.

To automate this, @arkenv/nextjs/config provides withArkEnv, which statically extracts your keys and writes a tailored factory in generated/env.gen.ts.

1. Configure next.config.ts

Wrap your Next.js configuration in withArkEnv:

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

const nextConfig: NextConfig = {
  // Your standard Next.js config options
};

export default withArkEnv(nextConfig);
2. Define your schema in env.ts

Import arkenv from the generated ./generated/env.gen file instead of the package:

// src/env.ts
import arkenv from "./generated/env.gen";

export const env = arkenv({
  server: {
    DATABASE_URL: "string",
    STRIPE_API_KEY: "string",
  },
  client: {
    NEXT_PUBLIC_API_URL: "string.host",
  },
  shared: {
    NODE_ENV: "string",
  },
});

Note: For the best DX and CI/CD compatibility, we recommend committing generated/env.gen.ts to source control.


Customizing Paths

If you want to keep generated files in a separate subdirectory (like src/generated/), you can specify the schemaPath and outputPath options in next.config.ts:

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

const nextConfig: NextConfig = {
  reactStrictMode: true,
};

export default withArkEnv(nextConfig, {
  schemaPath: "src/env.ts",
  outputPath: "src/generated/env.gen.ts"
});

Then, import from the custom location:

// src/env.ts
import arkenv from "./generated/env.gen";

export const env = arkenv({
  client: {
    NEXT_PUBLIC_API_URL: "string",
  }
});

The Danger of Shared Variables

Restrict the shared block only to NODE_ENV. Avoid placing custom variables (like PORT or other custom configuration) in the shared block.

The Undefined Fallback Bug

Next.js statically strips process.env references from client-side bundles unless they are prefixed with NEXT_PUBLIC_. If you define a custom variable in shared with a default value (e.g., PORT defaulting to 3000 or THEME defaulting to 'dark'), the environment behaves asymmetrically:

  • On the server, ArkEnv reads the actual value from the environment (e.g. PORT = 8080).
  • On the client, Next.js strips process.env.PORT to undefined, causing ArkEnv to fall back to the default value (3000).

This asymmetry causes React hydration mismatches and corrupts client-side state. Always place non-prefixed variables under server so they are strictly server-only.

Keywords