Simple Next.js environment variable validation
Sometimes I push code to production, only to realize that I forgot to configure a new environment variable on AWS or Vercel. Not ideal. So I looked into how to set up environment variable validation using Zod, and found this interesting YouTube video by Matt Pocock.
> next dev --turbo --port 3000
⚠️ Environment variables validation failed
- NEXT_PUBLIC_GRAPHQL_API_URL: Required
I wanted to keep things simple and created a src/env.ts
file that contains my Zod validation schema:
export const schema = z.object({
NEXT_PUBLIC_SOME_BOOLEAN_VARIABLE: z.enum(['true', 'false']),
NEXT_PUBLIC_SOME_URL_VARIABLE: z.string().url(),
});
declare global {
namespace NodeJS {
interface ProcessEnv extends z.infer<typeof schema> {}
}
}
That last part adds type-hinting to your process.env
using the defined Zod schema, so you have autocompletion in your IDE as a bonus.
Then, to make sure the validation runs at build time, add this to your next.config.ts
:
import { schema } from './src/env';
// Validate environment variables
schema.parse(process.env);
Or if you want a bit nicer console output, use this function instead:
import { z } from 'zod';
export const validateEnv = (schema: z.ZodObject<any, any, any, any>) => {
try {
schema.parse(process.env);
} catch (error) {
if (error instanceof z.ZodError) {
console.log(
' \x1b[1m\x1b[31m⚠\x1b[0m Environment variables validation failed\n'
);
error.errors.forEach((err) => {
console.error(
` - \x1b[31m${err.path.join('.')}\x1b[0m: ${err.message}`
);
});
} else {
console.error(
' \x1b[31m⚠\x1b[0m Unexpected error during environment validation:',
error
);
}
console.log();
process.exit(1);
}
};
I also came across this t3-env package on GitHub. But personally, I preferred keeping my existing process.env
references without going through a wrapper.
If you’ve found another way to handle this, let me know on Bluesky!