How do I load environment variables in Nitro?
how do i load env vars? dotenv? or nitro has auto support for it
Here's the full picture:
##Nitro has built-in support for environment variables — no need to manually install or configure dotenv.
There are two distinct mechanisms:
###1. .env file loading (build-time / dev / preview)
Nitro uses c12 under the hood, which has built-in dotenv support. The behavior depends on the mode:
-
In development (
dev: true), Nitro automatically loads.envand.env.localfiles from your project root.
Source:src/config/loader.tsline 81:const _dotenv = opts.dotenv ?? (configOverrides.dev && { fileName: [".env", ".env.local"] }); -
In preview mode (
nitro preview), it loads.env.preview,.env.production, and.env(in that priority order).
Source:src/preview.tslines 111–115:const env = await loadDotenv({ cwd: root, fileName: [".env.preview", ".env.production", ".env"], }); -
In production,
.envfiles are NOT loaded. You're expected to set environment variables through your platform (Vercel, Cloudflare, etc.).
###2. Runtime config + env variable mapping (runtime)
This is the main way to use env vars at runtime. Nitro automatically maps process.env variables to your runtime config keys using a naming convention.
Source: src/runtime/internal/runtime-config.ts:
function getRuntimeConfig() {
const env = globalThis.process?.env || {};
applyEnv(runtimeConfig, {
prefix: "NITRO_",
altPrefix: runtimeConfig.nitro?.envPrefix ?? env?.NITRO_ENV_PREFIX ?? "_",
envExpansion: Boolean(runtimeConfig.nitro?.envExpansion ?? env?.NITRO_ENV_EXPANSION ?? false),
});
return runtimeConfig;
}
How it works:
- Define keys in your
runtimeConfiginnitro.config.ts. - At runtime, Nitro checks for env vars with the
NITRO_prefix (or a customaltPrefixviaNITRO_ENV_PREFIX). - The key is converted to
UPPER_SNAKE_CASE.
Example:
// nitro.config.ts
export default defineNitroConfig({
runtimeConfig: {
secretKey: "default-value", // → overridden by NITRO_SECRET_KEY
database: {
host: "localhost", // → overridden by NITRO_DATABASE_HOST
},
},
});
Then in your handler:
const config = useRuntimeConfig();
console.log(config.secretKey); // reads NITRO_SECRET_KEY or falls back to "default-value"
console.log(config.database.host); // reads NITRO_DATABASE_HOST or falls back to "localhost"
###3. Env expansion (experimental)
You can enable {{VAR_NAME}} expansion inside runtime config string values:
// nitro.config.ts
export default defineNitroConfig({
experimental: { envExpansion: true },
runtimeConfig: {
dbUrl: "postgres://{{DB_HOST}}:{{DB_PORT}}/mydb",
},
});
This replaces {{DB_HOST}} with process.env.DB_HOST at runtime (source).
###TL;DR
| Mode | .env files loaded | Mechanism |
|---|---|---|
| Dev | .env, .env.local | Automatic via c12 |
| Preview | .env.preview, .env.production, .env | Automatic via c12 |
| Production | ❌ None | Set env vars on your platform |
At runtime (all modes), env vars prefixed with NITRO_ automatically override matching runtimeConfig keys. No dotenv package needed — it's all built in. (dotenv is listed as an optional peer dependency, only used if c12 needs it internally.)
END OF POST