Migrating from T3 Env

Replace createEnv and runtimeEnv with a flat ArkEnv schema.

Edit on GitHub

A T3 Env Next.js setup keeps a runtimeEnv map in sync with the schema. ArkEnv keeps the flat env object and drops that map.

T3 Env is a major inspiration for that security model. The cheatsheet of what else changes is Why ArkEnv?.

What changes

Edit files against this mapping. The flat schema replaces the nested server / client / runtimeEnv object.

FeatureT3 EnvArkEnv
Core functioncreateEnv from @t3-oss/env-nextjsarkenv from @arkenv/nextjs or @arkenv/core
Schema structureNested { server, client, runtimeEnv }Flat schema (optional two-module recipe for name isolation)
Client inliningManual runtimeEnv objectwithArkEnv writes the mapping
ValidatorZod onlyArkType via @arkenv/core, or Zod and Valibot via @arkenv/standard

A flat layout still infers types and throws if client code reads a server key. Use the two-module recipe when secret names must stay out of the client graph.

Next.js migration steps

Work through these steps on an existing Next.js app.

Install ArkEnv and remove T3 Env

ArkType:

npm install @arkenv/core @arkenv/nextjs arktype
npm rm @t3-oss/env-nextjs

Zod:

npm install @arkenv/standard @arkenv/nextjs zod
npm rm @t3-oss/env-nextjs

Valibot:

npm install @arkenv/standard @arkenv/nextjs valibot @valibot/to-json-schema
npm rm @t3-oss/env-nextjs

Wrap next.config.ts

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

const : NextConfig = {};

export default ();

Without ArkType, import withArkEnv from @arkenv/nextjs/standard/config.

Replace createEnv with a flat schema

T3 Env:

./src/env.js
import { createEnv } from "@t3-oss/env-nextjs";
import * as z from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.url(),
  },
  client: {
    NEXT_PUBLIC_APP_URL: z.url(),
  },
  runtimeEnv: {
    DATABASE_URL: process.env.DATABASE_URL,
    NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
  },
});

ArkEnv. withArkEnv generates .arkenv/env.gen.ts. Zod and Valibot import withArkEnv from @arkenv/nextjs/standard/config.

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

export const  = ({
  DATABASE_URL: "string.url",
  NEXT_PUBLIC_APP_URL: "string.url",
});

You do not copy keys into runtimeEnv. NEXT_PUBLIC_ marks client variables.

Retarget imports

Change import { env } from "~/env" (or src/env.js) to your new ./env module.

Optional: two-module recipe

If you used two createEnv calls in T3 Env for name/type isolation, mirror that with two ArkEnv modules and two imports — not a CLI --strict flag. See Client vs. server.

Next steps