npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

next-standalone-env

v1.0.1

Published

Runtime environment variable resolution for Next.js standalone/Docker deployments. Allows the same Docker image to work across multiple environments.

Readme

next-standalone-env

Runtime environment variable resolution for Next.js standalone/Docker deployments

npm version License: MIT

The Problem

When Next.js builds in standalone mode (used for Docker deployments), environment variables like NEXTAUTH_URL are baked in at build time. This means:

  • ❌ You need separate Docker images for dev, staging, and production
  • ❌ You can't use the same image across environments
  • ❌ OAuth callbacks fail when URLs don't match
  • ❌ You have to rebuild for every environment change

The Solution

next-standalone-env patches environment variables at runtime when your container starts, allowing:

  • ✅ One Docker image for all environments
  • ✅ Runtime configuration via APP_ENV
  • ✅ Proper OAuth redirects in every environment
  • ✅ Build once, deploy everywhere

Installation

npm install next-standalone-env
# or
yarn add next-standalone-env
# or
pnpm add next-standalone-env

Quick Start

1. Simple Usage (Recommended)

Replace your Next.js standalone server with our runtime-aware server:

# In your Dockerfile
FROM node:20-alpine

# ... your build steps ...

# Copy the runtime server
COPY --from=builder /app/node_modules/next-standalone-env/server.js ./server.js

# Use our server instead of Next.js standalone server
CMD ["node", "server.js"]

Set your environment:

# Development
docker run -e APP_ENV=development your-image

# Production
docker run -e APP_ENV=production your-image

# Staging
docker run -e APP_ENV=staging your-image

2. Custom Configuration

Create runtime-env.config.js in your project root:

module.exports = {
  environments: {
    production: {
      vars: {
        NEXTAUTH_URL: 'https://app.example.com',
        NEXT_PUBLIC_API_URL: 'https://api.example.com'
      }
    },
    development: {
      vars: {
        NEXTAUTH_URL: 'https://dev.example.com',
        NEXT_PUBLIC_API_URL: 'https://api-dev.example.com'
      }
    },
    staging: {
      vars: {
        NEXTAUTH_URL: 'https://staging.example.com',
        NEXT_PUBLIC_API_URL: 'https://api-staging.example.com'
      }
    }
  },
  // Variables that can be overridden at runtime
  variables: ['NEXTAUTH_URL', 'NEXT_PUBLIC_API_URL', 'DATABASE_URL'],
  
  // The env var that determines which environment to use
  envSelector: 'APP_ENV', // or 'NODE_ENV', 'ENVIRONMENT', etc.
  
  // Enable debug logging
  debug: true
};

3. NextAuth Integration

Your NextAuth configuration works seamlessly:

// app/api/auth/[...nextauth]/route.js
import NextAuth from 'next-auth';
import AzureADProvider from 'next-auth/providers/azure-ad';

const handler = NextAuth({
  providers: [
    AzureADProvider({
      clientId: process.env.AZURE_AD_CLIENT_ID,
      clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
      tenantId: process.env.AZURE_AD_TENANT_ID,
    }),
  ],
  // NEXTAUTH_URL is now set correctly at runtime!
});

export { handler as GET, handler as POST };

Advanced Usage

Programmatic API

import { patchProcessEnv } from 'next-standalone-env';

// In your custom server
patchProcessEnv({
  environments: {
    production: {
      vars: { NEXTAUTH_URL: 'https://app.example.com' }
    },
    development: {
      vars: { NEXTAUTH_URL: 'https://dev.example.com' }
    }
  },
  variables: ['NEXTAUTH_URL'],
  debug: true
});

// Then start Next.js
const app = next({ /* ... */ });

Next.js Config Wrapper

// next.config.js
const { withRuntimeEnv } = require('next-standalone-env');

const nextConfig = {
  // your config
};

module.exports = withRuntimeEnv(nextConfig, {
  environments: { /* ... */ },
  variables: ['NEXTAUTH_URL', 'NEXT_PUBLIC_API_URL']
});

Runtime Overrides

Override any variable at runtime with the RUNTIME_ prefix:

# Override NEXTAUTH_URL regardless of APP_ENV
docker run \
  -e APP_ENV=production \
  -e RUNTIME_NEXTAUTH_URL=https://custom.example.com \
  your-image

Environment Variable Priority

  1. RUNTIME_* prefixed variables (highest priority)
  2. Environment-specific configuration based on APP_ENV
  3. Existing environment variables
  4. Defaults

Docker Example

# Build stage
FROM node:20-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./
RUN npm ci

# Copy source
COPY . .

# Build Next.js
RUN npm run build

# Production stage
FROM node:20-alpine AS runner

WORKDIR /app

# Install next-standalone-env
RUN npm install next-standalone-env

# Copy built application
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public

# Copy runtime config (optional)
COPY runtime-env.config.js ./

# Use runtime-aware server
CMD ["npx", "next-standalone-env/server"]

Kubernetes Example

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nextjs-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: your-image:latest
        env:
        - name: APP_ENV
          value: "development"  # or "production", "staging"
        - name: NODE_ENV
          value: "production"   # Always production for Next.js
        # Secrets still work normally
        - name: AZURE_AD_CLIENT_SECRET
          valueFrom:
            secretKeyRef:
              name: auth-secrets
              key: client-secret

How It Works

  1. Build Time: Next.js builds with default/production values
  2. Container Start: Our server runs before Next.js
  3. Runtime Patch: Environment variables are updated based on APP_ENV
  4. Next.js Start: Next.js starts with the correct runtime values

Common Use Cases

Multi-tenant SaaS

{
  environments: {
    'customer-a': {
      vars: {
        NEXTAUTH_URL: 'https://a.example.com',
        TENANT_ID: 'customer-a'
      }
    },
    'customer-b': {
      vars: {
        NEXTAUTH_URL: 'https://b.example.com',
        TENANT_ID: 'customer-b'
      }
    }
  }
}

Feature Flags

{
  environments: {
    'production': {
      vars: {
        FEATURE_NEW_UI: 'false'
      }
    },
    'canary': {
      vars: {
        FEATURE_NEW_UI: 'true'
      }
    }
  }
}

Regional Deployments

{
  environments: {
    'us-east': {
      vars: {
        API_ENDPOINT: 'https://us-east.api.example.com',
        REGION: 'us-east-1'
      }
    },
    'eu-west': {
      vars: {
        API_ENDPOINT: 'https://eu-west.api.example.com',
        REGION: 'eu-west-1'
      }
    }
  }
}

Debugging

Enable debug mode to see what's happening:

docker run -e DEBUG=true -e APP_ENV=development your-image

Output:

[next-standalone-env] Starting server with environment: development
[next-standalone-env] Setting NEXTAUTH_URL=https://dev.example.com (was: https://prod.example.com)
[next-standalone-env] Server ready on http://0.0.0.0:3000
[next-standalone-env] NextAuth URL: https://dev.example.com
[next-standalone-env] Environment: development

Migration Guide

From Multiple Dockerfiles

Before:

# Dockerfile.dev
ENV NEXTAUTH_URL=https://dev.example.com
# ... build ...

# Dockerfile.prod
ENV NEXTAUTH_URL=https://prod.example.com
# ... build ...

After:

# Single Dockerfile
# No environment-specific variables!
# ... build ...
CMD ["npx", "next-standalone-env/server"]

From Build Arguments

Before:

docker build --build-arg NEXTAUTH_URL=https://dev.example.com -t app:dev .
docker build --build-arg NEXTAUTH_URL=https://prod.example.com -t app:prod .

After:

docker build -t app:latest .
docker run -e APP_ENV=development app:latest
docker run -e APP_ENV=production app:latest

FAQ

Does this work with Vercel/Netlify?

No, this is specifically for self-hosted Next.js deployments using standalone output mode.

Does it work with all environment variables?

It works with any environment variable. However, NEXT_PUBLIC_* variables that are inlined during build may still need rebuilding for changes.

Is there a performance impact?

Minimal. Environment resolution happens once at server startup, not per request.

Can I use this with PM2/cluster mode?

Yes, the environment is patched before Next.js starts, so it works with any process manager.

Contributing

Contributions welcome! Please feel free to submit a Pull Request.

License

MIT © Vinnie Espo

Related Projects

Support

If this package helps you, please consider:

  • ⭐ Starring the repo
  • 🐛 Reporting issues
  • 🔀 Contributing improvements
  • 📢 Sharing with others who might need it