# Nuxt environment variables and runtimeConfig

> Nuxt reads .env only in dev and build, then overrides runtimeConfig from NUXT_ variables at runtime. How the mapping works and how to start Nuxt with Crunu.

URL: https://crunu.com/environment-variables/nuxt
Language: en
Updated: 2026-10-30

Nuxt reads environment variables in two different moments. While you run `nuxt dev`, `nuxt build` or `nuxt generate`, the Nuxt CLI loads the `.env` file in the project root into `process.env`. When the built server runs in production, it doesn't read `.env` at all. Instead, Nuxt fills `runtimeConfig` from the server's real environment: a variable named `NUXT_` plus the key in upper snake case replaces a private key, and `NUXT_PUBLIC_` plus the key replaces a public one. Your code reads the result with `useRuntimeConfig()`. This page follows the [Nuxt 4 runtime config guide](https://nuxt.com/docs/4.x/guide/going-further/runtime-config), checked October 30, 2026.

## Two phases, two sources

| Phase                 | Commands                                  | Where values come from                                                  |
| --------------------- | ----------------------------------------- | ----------------------------------------------------------------------- |
| Development and build | `nuxt dev`, `nuxt build`, `nuxt generate` | the process environment plus `.env`, or the file passed with `--dotenv` |
| Production server     | `node .output/server/index.mjs`           | the process environment only, mapped through `NUXT_` names              |
| Local preview         | `nuxt preview`                            | `.env` is loaded for convenience                                        |

*Figure: Diagram of how Nuxt loads environment variables. Env files are read in this order of priority, and the first one wins: .env. Some values are inlined at build time and the rest are read when the app starts. Variables that start with NUXT_PUBLIC\_ go into the browser bundle and are visible to every visitor; server and build code can read every variable.*

The [.env page](https://nuxt.com/docs/4.x/directory-structure/env) explains the production rule: once the server is built, you are responsible for setting variables with the tools of your host, because Nuxt also targets serverless and edge platforms that may not have a normal file system. In development, editing `.env` restarts the Nuxt instance so new values apply. Removing a line doesn't unset a value that was already loaded.

Only one file is read by default. To use another, pass it explicitly, for example `nuxt dev --dotenv .env.local`. There is no automatic chain of `.local` and mode files as in Vite.

## How runtimeConfig and NUXT\_ names fit together

You declare the shape and defaults in `nuxt.config`:

```ts
export default defineNuxtConfig({
  runtimeConfig: {
    apiSecret: '',
    public: {
      apiBase: '/api'
    }
  }
})
```

At runtime, Nuxt looks for matching variables. The name is `NUXT_`, then the key path in upper case with an underscore at each case change and nesting level:

| Key              | Variable               |
| ---------------- | ---------------------- |
| `apiSecret`      | `NUXT_API_SECRET`      |
| `public.apiBase` | `NUXT_PUBLIC_API_BASE` |

Three rules make or break this:

1. **The key must already exist.** Nuxt only overrides keys declared in `nuxt.config`, so arbitrary environment variables can't leak into your app's configuration. An undeclared `NUXT_STRIPE_KEY` is silently ignored.
2. **The config file runs once, at build time.** Writing `apiSecret: process.env.STRIPE_KEY` reads `STRIPE_KEY` during the build and bakes the result into the output. Changing `STRIPE_KEY` on the server later does nothing. The guide recommends variables that match the `runtimeConfig` structure instead.
3. **Values are converted.** Nuxt casts overrides with `destr`, so `true` becomes a boolean and numeric-looking strings become numbers. A hex color like `4848e0` is read as scientific notation and becomes the number `4848` unless you wrap it in literal double quotes.

## Private and public keys

Top-level keys are private. On the server, `useRuntimeConfig()` returns the whole object, read-only. In the browser it returns only `public` and Nuxt's internal `app` section. Public values are added to each page's payload, so treat anything under `public` as published. The guide also warns against rendering config keys into templates or passing them to `useState`, both of which can send private values to the client.

Runtime config is serialized before it's handed to Nitro, Nuxt's server engine. Functions, Sets and Maps don't survive that, so put such logic in a plugin or server middleware.

In server routes, pass the event: `useRuntimeConfig(event)` makes sure the per-request environment overrides apply.

## When a value doesn't show up

Most "my variable is ignored" reports in Nuxt come down to one of four causes, and you can check them in order without printing any secret:

1. **Is the key declared?** Open `nuxt.config` and find the key under `runtimeConfig` or `runtimeConfig.public`. If it isn't there, no environment variable can set it.
2. **Does the name match the key?** Convert the key path by hand: `public.stripePublishableKey` becomes `NUXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`. A missing underscore at a case change is enough to break it.
3. **Is the server reading a file you expect it to ignore?** In production it never reads `.env`, so a value that only exists in that file is simply absent. Compare with `nuxt preview`, which does load the file, to see whether that's the difference.
4. **Was the value baked in?** If `nuxt.config` copies from another variable with `process.env`, the build machine's value is what you get, regardless of the server.

To confirm what the server received, log the names of the runtime config keys at startup, or whether each is non-empty, never the values themselves. Logs travel further than you expect.

## Run Nuxt with values from Crunu

The production rule that Nuxt reads only real environment variables is exactly what `crunu run` provides. It decrypts a Crunu environment in memory and starts the server with those variables in its process environment, so `NUXT_API_SECRET` overrides `apiSecret` without any file on the machine.

1. Put the production variables, named with the `NUXT_` and `NUXT_PUBLIC_` rules, into a Crunu environment such as `web-app/production`, and add `NODE_ENV=production` to it.
2. Develop with `crunu run --env web-app/development -- npx nuxt dev`, which gives the dev server the same variables the CLI would read from `.env`.
3. Build in CI with `exec crunu run --env web-app/build -- npx nuxt build` if the build needs values at all, for example for a prerendered page.
4. On a Linux server with the agent, start `crunu run --env web-app/production --restart on-change -- node .output/server/index.mjs`.

`NODE_ENV` belongs in the environment because `crunu run` passes only a short allowlist from your shell, such as `PATH` and `HOME`, and Nuxt's deployment guide runs the server with `NODE_ENV=production` to avoid development-only warnings from libraries. The server's own settings, `NITRO_PORT` or `PORT` and `NITRO_HOST` or `HOST`, can sit in the same environment.

With `--restart on-change`, `crunu` restarts the Nitro server after a value changes, and the new `NUXT_` values apply. Prerendered pages and anything read in `nuxt.config` stay as built.

## One set of names for every stage

Because the `NUXT_` names follow mechanically from `runtimeConfig`, a team can use the exact same variable names in development, staging and production, and change only the values. That keeps a few things simple. The `.env.example` in the repository lists each `NUXT_` name once. Each Crunu environment for the project holds the same names with stage-specific values, and Crunu's environment comparison shows which names exist in one stage but not another, with values hidden until someone chooses to show them. A new key added to `runtimeConfig` then needs one new variable in each environment, and a review can check that it's there before the deploy instead of after the first error.

## Platforms that host Nuxt for you

On Netlify, Vercel and similar hosts, the platform holds the runtime variables and passes them to Nuxt's server functions. Crunu has no built-in sync into those stores. The honest setup there is to keep runtime values in the platform's own settings, and use `crunu run` around the build and around local development. The [Netlify page](https://crunu.com/environment-variables/netlify) describes that split, and the [Vercel integration](https://crunu.com/integrations/vercel) shows a pipeline recipe for pushing values into Vercel from Crunu.

## Related reading

- [Vite](https://crunu.com/environment-variables/vite), which Nuxt uses for client builds.
- [Next.js](https://crunu.com/environment-variables/nextjs) and [SvelteKit](https://crunu.com/environment-variables/sveltekit) for comparison.
- [How to share .env files with your team](https://crunu.com/guides/share-env-files-with-a-team).
- [crunu run](https://crunu.com/docs/cli/run) and [installing the agent](https://crunu.com/docs/getting-started/install-the-agent).

## FAQ

### Why is my NUXT_API_SECRET ignored in production?

Nuxt overrides only keys that exist in runtimeConfig in nuxt.config. Declare apiSecret there, even with an empty default, and NUXT_API_SECRET will replace it at runtime.

### Does nuxt preview read my .env file?

Yes. nuxt preview loads .env into process.env for convenience. The production server started with node .output/server/index.mjs does not.

### Can I change runtime config on a prerendered static site?

No. For a purely static site, the values are fixed when the pages are generated. Rebuild to change them.

### Should NODE_ENV be in the Crunu environment?

For production, yes. Nuxt's deployment guide starts the server with NODE_ENV set to production, and crunu run doesn't copy NODE_ENV from your shell by default.

## Sources

- [Nuxt: Runtime config](https://nuxt.com/docs/4.x/guide/going-further/runtime-config) (accessed 2026-10-30)
- [Nuxt: .env](https://nuxt.com/docs/4.x/directory-structure/env) (accessed 2026-10-30)
- [Nuxt: Deployment](https://nuxt.com/docs/4.x/getting-started/deployment) (accessed 2026-10-30)
