Skip to content

Making Environment Variables Public

Transform existing environment variables into NEXT_PUBLIC_* prefixed versions without renaming.

The Problem

You have environment variables without the NEXT_PUBLIC_ prefix:

bash
API_URL=https://api.example.com
APP_NAME=MyApp
REGION=us-east-1

You want them available in the browser, but:

  • You don't want to rename them in your deployment config
  • Other services already use these names
  • You're migrating from another framework

The Solution

makeEnvPublic() creates prefixed copies automatically:

js
// next.config.js
const { makeEnvPublic } = require('next-dynenv')

// Creates NEXT_PUBLIC_API_URL from API_URL
makeEnvPublic('API_URL')

module.exports = {
    // your config
}

Now you have both:

  • API_URL - Original (server-side only)
  • NEXT_PUBLIC_API_URL - Copy (available in browser)

Basic Usage

Single Variable

js
// next.config.js
const { makeEnvPublic } = require('next-dynenv')

makeEnvPublic('API_URL')
// API_URL → NEXT_PUBLIC_API_URL

Multiple Variables

js
// next.config.js
const { makeEnvPublic } = require('next-dynenv')

makeEnvPublic(['API_URL', 'APP_NAME', 'VERSION'])
// API_URL → NEXT_PUBLIC_API_URL
// APP_NAME → NEXT_PUBLIC_APP_NAME
// VERSION → NEXT_PUBLIC_VERSION

Usage in Next.js Config

js
// next.config.js
const { makeEnvPublic } = require('next-dynenv')

// Make variables public BEFORE the config export
makeEnvPublic(['API_URL', 'APP_NAME', 'ANALYTICS_ID', 'FEATURE_FLAGS'])

/** @type {import('next').NextConfig} */
const nextConfig = {
    // your Next.js configuration
}

module.exports = nextConfig

With ESM Syntax

js
// next.config.mjs
import { makeEnvPublic } from 'next-dynenv'

makeEnvPublic(['API_URL', 'APP_NAME'])

/** @type {import('next').NextConfig} */
const nextConfig = {}

export default nextConfig

Controlling Logging

Default Logging

By default, makeEnvPublic logs events:

[next-dynenv] Prefixed environment variable 'API_URL'
[next-dynenv] Prefixed environment variable 'APP_NAME'

Silent Mode

js
makeEnvPublic('API_URL', { logLevel: 'silent' })

Production-Only Silence

js
makeEnvPublic(['API_URL', 'APP_NAME'], {
    logLevel: process.env.NODE_ENV === 'production' ? 'silent' : 'info',
})

Behavior Details

Missing Variables

If a variable doesn't exist, a warning is logged (but no error thrown):

js
// If MISSING_VAR is not in process.env
makeEnvPublic('MISSING_VAR')
// Warning: "Skipped prefixing environment variable 'MISSING_VAR'. Variable not in process.env"

Already Public Variables

If a variable already has the prefix, it's skipped:

js
makeEnvPublic('NEXT_PUBLIC_API_URL')
// Warning: "Environment variable 'NEXT_PUBLIC_API_URL' is already public"

Original Variables Preserved

The original variable remains available:

js
makeEnvPublic('API_URL')

// Both are now available:
process.env.API_URL // Original
process.env.NEXT_PUBLIC_API_URL // Copy (for browser)

Using with instrumentation.ts

For Next.js 13.2+, you can use the instrumentation file:

ts
// instrumentation.ts
import { makeEnvPublic } from 'next-dynenv'

export function register() {
    makeEnvPublic(['API_URL', 'APP_NAME', 'REGION'])
}

Complete Example

js
// next.config.js
const { makeEnvPublic } = require('next-dynenv')

// Environment variables to expose
const publicVars = ['API_URL', 'APP_NAME', 'VERSION', 'ANALYTICS_ID', 'FEATURE_AUTH', 'FEATURE_PAYMENTS']

// Make them public
makeEnvPublic(publicVars, {
    logLevel: process.env.NODE_ENV === 'production' ? 'silent' : 'info',
})

/** @type {import('next').NextConfig} */
const nextConfig = {
    reactStrictMode: true,
}

module.exports = nextConfig

Then in your components:

tsx
import { env } from 'next-dynenv'

// These now work in both server and client
const apiUrl = env('NEXT_PUBLIC_API_URL')
const appName = env('NEXT_PUBLIC_APP_NAME')

When to Use

Use makeEnvPublic() when:

  • Existing infrastructure - You have env vars already deployed without the prefix
  • Cross-service consistency - Multiple services share the same variable names
  • Migration path - Moving from another framework (like Create React App)
  • Deployment simplicity - You don't want to update every deployment config

Alternative Approach If you're starting fresh, consider using the NEXT_PUBLIC_ prefix directly in your

environment variables. It's more explicit and requires no transformation step. :::

Next Steps

Released under the MIT License.