We've all been there. You push to production, the server crashes, and after 20 minutes of debugging you realize DATABASE_URL was never set. Or you've got a .env file with 30 variables and no idea which ones your app actually uses anymore.
I got tired of it, so I built envguard — a zero-dependency environment variable validator and codebase analyzer for Node.js.
What it does
envguard has three main jobs:
1. Validate & coerce at startup — define a schema, and envguard throws a single combined error listing all broken variables before your server even boots.
2. Analyze your codebase — scan your entire project to find variables that are defined in .env but never used in code (dead weight), and variables used in code but missing from .env (silent bugs).
3. Dev Dashboard — a local UI that visualizes your env health in real-time, including type mismatches against an optional schema file.
How it works
The architecture is pretty straightforward — three core modules:
-
guard.js— validates env vars against a schema at runtime, coercing types ("3000"→3000,"true"→true) and throwing one combined error if anything's wrong. -
scanner.js— recursively walks your project files using three regex patterns to catch every usage style: dot notation (process.env.VAR), bracket notation (process.env['VAR']), and destructuring (const { VAR } = process.env). It also strips comments first so you don't get false positives. -
server.js— a lightweight Nodehttpserver that runs the scanner on every poll and serves the dashboard UI.
No dependencies. Just native Node.js all the way down.
Usage
npm install @rohansm14/envguard
If anything's wrong, you get one clear error at boot — not a mystery crash at runtime.
CLI scan:
npx envguard
This prints a report of unused and missing variables across your whole codebase.
Dev dashboard:
npx envguard dev-ui
Opens http://localhost:3000 with live polling, type mismatch detection, and status badges for every variable.
What I learned building this
Regex is trickier than it looks. Handling all three usage patterns (dot, bracket, destructuring) while also stripping comments to avoid false positives took a few iterations. The destructuring regex in particular — parsing aliases like const { DB_URL: db } = process.env — was the most fiddly part.
Proxies are powerful but need careful handling. The guard() result is a ES6 Proxy that throws on access to undefined validated keys. Getting that to play nicely with things like toJSON, then, and Symbol properties (which Node and various frameworks probe for) required a bunch of edge case handling.
One combined error > many errors. Throwing all validation failures at once instead of stopping at the first one was a deliberate DX choice — and honestly the thing I'm happiest about. Nothing's worse than fixing one env error, restarting, and hitting another.
The code is open source on GitHub. If you've ever lost time to a broken env config, give it a try — would love feedback!

Top comments (0)