Skip to content

Instantly share code, notes, and snippets.

@stefan-girlich
Last active October 11, 2024 20:20
Show Gist options
  • Save stefan-girlich/4974d9d57bcbad35a973ba02774eb999 to your computer and use it in GitHub Desktop.
Save stefan-girlich/4974d9d57bcbad35a973ba02774eb999 to your computer and use it in GitHub Desktop.
use Envalid to validate and expose Next.js client-side and server-side variables
import { cleanEnv, Spec, str, ValidatorSpec } from 'envalid'
// https://github.com/af/envalid
/**
* This module is the single source of truth for application environment configuration.
* When imported as a TypeScript module, it provides runtime access to validated environment variables.
* When executed as a script, it may cover the following use cases:
* - validate current environment
* - load current environment beforehand (when CLI flag --force-load-env is used)
* - print empty environment configuration as .env-compatible string (when CLI flag --print-env is used)
* - print valid environment configuration as .env-compatible string (when CLI flag --print-env is used)
* This module detects if it is executed in a client-side environment and excludes server-only variables, see:
* https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser
*/
const FORCE_LOAD_CLI_FLAG = '--force-load-env'
const PRINT_ENV_CLI_FLAG = '--print-env'
const printEnvCliFlagProvided = process.argv?.includes(PRINT_ENV_CLI_FLAG)
const forceLoadCliFlagProvided = process.argv?.includes(FORCE_LOAD_CLI_FLAG)
if (forceLoadCliFlagProvided) {
console.info('Force-loading environment ...')
const { loadEnvConfig } = require('@next/env')
loadEnvConfig(process.cwd())
}
// ========== environment definition and validation ==========
const isServer = typeof window === 'undefined'
const envVars = {
NEXT_PUBLIC_CLIENT_VAR: process.env.NEXT_PUBLIC_CLIENT_VAR,
SERVER_VAR: process.env.SERVERSIDE_VAR,
}
type EnvKey = keyof typeof envVars
const optionalVarOpts: Spec<string> = { default: undefined }
const serverVarOpts = isServer ? undefined : optionalVarOpts
const envConfig: Record<EnvKey, ValidatorSpec<string>> = {
NEXT_PUBLIC_CLIENT_VAR: str(),
SERVER_VAR: str(serverVarOpts),
}
if (printEnvCliFlagProvided) {
console.info('Printing empty .env configuration ...')
const emptyEnvConfigString = Object.keys(envConfig)
.reduce((acc, curr) => [...acc, `${curr}=`], [])
.join('\n')
console.info(`${emptyEnvConfigString}\n`)
}
const env = cleanEnv(envVars, envConfig)
if (printEnvCliFlagProvided && forceLoadCliFlagProvided) {
console.info('Printing current valid .env configuration ...')
const validEnvConfigString = Object.entries(env)
.reduce((acc, [key, value]) => [...acc, `${key}=${value}`], [])
.join('\n')
console.info(`${validEnvConfigString}\n`)
}
export default env
@iamgideonidoko
Copy link

This is solid. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment