Runtime Config & Environment Variables
Exposing environment variables to your app safely, with a clear line between server-only secrets and public values.
読了時間 2 分
Every real app needs values that differ between environments — an API base URL, a database connection string, a public analytics ID. Nuxt's runtimeConfig is the mechanism for this, and its most important feature is that it draws a hard line between values that stay on the server and values that are safe to send to the browser.
Declaring runtime config
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
// private — server-only by default
databaseUrl: process.env.DATABASE_URL,
apiSecretKey: process.env.API_SECRET_KEY,
// public — exposed to the client
public: {
apiBaseUrl: process.env.API_BASE_URL || "https://api.example.com",
analyticsId: process.env.ANALYTICS_ID,
},
},
});Anything outside the public key is available only in server code — API routes under server/, or server-only parts of the request lifecycle. Anything inside public is bundled into the client-side JavaScript and visible to anyone who opens dev tools, exactly like any other value shipped to the browser.
Reading it back
// server/api/orders.ts
export default defineEventHandler((event) => {
const config = useRuntimeConfig(event);
// config.databaseUrl is available here — this code never runs in the browser
return db.connect(config.databaseUrl).orders.findAll();
});<script setup>
const config = useRuntimeConfig();
// config.public.apiBaseUrl is fine to use here
// config.databaseUrl would be undefined — it never reached the client
</script>useRuntimeConfig() is auto-imported everywhere, but which keys actually have values depends entirely on where the code runs — that's the whole point of the split.
Why this split exists
It's tempting to think an environment variable not referenced in your Vue template is automatically "safe" on the server. It isn't — with a plain .env file and no framework enforcing a boundary, a single careless console.log(config) or an object spread into a client-fetched response can leak a secret into the browser bundle without anyone noticing until it's already shipped. Nuxt's public/private split makes that mistake structural rather than a matter of discipline: a value has to be deliberately placed under public before it can ever reach client code.
Overriding at runtime without a rebuild
Values default from process.env at build time, but every key can also be overridden at runtime using a matching NUXT_ prefixed environment variable — NUXT_DATABASE_URL or NUXT_PUBLIC_API_BASE_URL — without touching nuxt.config.ts or rebuilding. This is what makes it practical to deploy the same build to staging and production and only change environment variables between them, rather than rebuilding per environment.