Nuxt

Learn how to use ArkEnv in a Nuxt project.

Edit on GitHub

Nuxt already hydrates public config through Nitro. ArkEnv validates the schema on server and client routes, and keeps server secrets off the browser while those public keys ride runtime config.

How this host compares with Next.js, Vite, and Bun is in Frameworks.

Quickstart

arkenv init is the default on an existing Nuxt app. It registers @arkenv/nuxt/module in your Nuxt config and writes the first schema file.

npx arkenv init

Manual installation

Already ran init?

Skip this section. The CLI already registered the module and wrote the schema.

Install @arkenv/nuxt next to the engine you write schemas with, when nuxt.config.ts is already yours and you want each package explicit in package.json.

ArkType engine

Install @arkenv/core and its peer dependency arktype:

npm install @arkenv/core @arkenv/nuxt arktype

Standard Schema engine

If you aren't using ArkType, install @arkenv/standard with Zod or Valibot:

npm install @arkenv/standard @arkenv/nuxt zod
npm install @arkenv/standard @arkenv/nuxt valibot @valibot/to-json-schema

Module configuration

Nuxt loads modules from nuxt.config.ts. Registering @arkenv/nuxt there is what injects runtime config and validates variables during development and build. Without the module, importing env only checks the process that happens to load it.

./nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@arkenv/nuxt/module"],
});

Schema

One env.ts is the schema. Public keys use the NUXT_PUBLIC_ prefix so Nitro can hydrate them on the client. Everything else stays on the server.

Zod and Valibot both import @arkenv/nuxt/standard and register @arkenv/nuxt/standard/module.

@arkenv/nuxt/standard binds the root @arkenv/standard engine. Zod 4.2+ coerces numbers and booleans from that entry. Valibot does not: there is no @arkenv/nuxt/standard/valibot binding, so installing @valibot/to-json-schema does not coerce v.number() or v.boolean() here. Keep Valibot fields as strings on this entry, or validate them with @arkenv/standard/valibot outside the Nuxt module.

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

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

Unlike Next.js, Nuxt does not emit an env.gen.ts file; @arkenv/nuxt acts as the primary entrypoint.

If you split client and server modules for name/type isolation, never import the server module from client or Vue code. See the two-module recipe.

Read env in application code

Import { env } from "./env" in server routes and Vue components. One module is the typed object everywhere.

Do not read process.env directly

Reading process.env skips ArkEnv. Import { env } so public keys stay typed and coerced and server secrets stay out of the client bundle.

Standard Schema

Zod and Valibot both point the module at the standard module path. The schema tabs above already import from @arkenv/nuxt/standard.

./nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@arkenv/nuxt/standard/module"],
});

Nitro boot gate and runtimeConfig hydration

Staging and production containers inject environment variables when the process starts, not when the image is built. Vite and Bun inline literals at build time. @arkenv/nuxt hooks into Nitro instead:

  1. Server boot gate: At server startup, an internal Nitro plugin runs before route handlers execute. Nuxt compiles your schema into the server bundle, then the plugin validates live environment variables against that schema and throws fail-fast errors on invalid values. A copied .output directory does not need the source env.ts beside it.
  2. Runtime configuration hydration: An internal Nitro plugin passes validated public variables (NUXT_PUBLIC_*) into useRuntimeConfig().public.
  3. Client access: Client components read public values from runtime configuration during browser rendering and hydration, avoiding hardcoded build-time literals.

You can update environment variables across deployment stages without rebuilding client JavaScript bundles. Ship one image and change env at container start for staging versus production.

Unlike Next.js env.gen.ts, @arkenv/nuxt writes no generated files to commit or gitignore. The module validates at boot and registers public keys on runtimeConfig.

Next steps