← Back to list

dotenv-gad: Environment variable validation library

Environment variables are essential but often misunderstood and actually can be the source of late-night debugging sessions. How many times…

Kasiimlyee · 2026-02-16 10:37 · 0 claps · 3.6 min read
#nodejs #dotenv #environment #typescript
Open on Medium ↗
Wiki topics: 💻 · Programming 🌐 · Web Development 📚 · Books & Reading

dotenv-gad: Environment variable validation library

Environment variables are essential but often misunderstood and actually can be the source of late-night debugging sessions. How many times have you gotten to a feature and only to realize that a required config variable was missing in production? Or worse you discover that your development .env file had a typo that went unnoticed for weeks.

Enter dotenv-gad, a TypeScript solution that transforms environment variable management from a manual, error-prone process into something safe, predictable.

The Problem We’ve All Faced

Traditional environment variable management boils down to this:

  1. Create a .env file
  2. Hope developers remember what variables are needed
  3. Pray no one makes a typo
  4. Cross your fingers in production

The result? runtime errors, missing configurations, and the eternal question: “Is this variable supposed to be a string or a number?”

With dotenv-gad, you get a schema which is a single source of truth.

The dotenv-gad Approach: Schema Configuration

At its core, dotenv-gad introduces you to define your environment variables as a schema, not as magical strings scattered throughout your codebase.

Here is how it works:

import { defineSchema } from "dotenv-gad";

export default defineSchema({
  PORT: {
    type: "number",
    default: 3000,
    docs: "Port to run the server on",
  },
  DATABASE_URL: {
    type: "string",
    required: true,
    sensitive: true,
  },
  API_KEY: {
    type: "string",
    sensitive: true,
    validate: (val) => val.startsWith('sk_'),
    error: 'API key must start with "sk_"'
  },
});

Then, instead of crossing your fingers, you validate:

import { loadEnv } from "dotenv-gad";
import schema from "./env.schema";

const env = loadEnv(schema);
// env is fully typed, validated, and guaranteed to have required vars
console.log(`Server running on port ${env.PORT}`);

What just happened? Your environment variables are type-safe (TypeScript knows PORT is a number) Missing required variables throw an error immediately Invalid formats are caught before runtime Your IDE provides autocomplete for environment variables

Feature Deep Dive: More Than Just Validation

  1. Comprehensive Type Safety

dotenv-gad understands complex types out of the box:

{
  API_URL: { type: 'url' },          // Validates URL format
  EMAIL: { type: 'email' },          // Validates email format
  CONFIG: { type: 'json' },          // Parses and validates JSON
  TAGS: {
    type: 'array',
    items: { type: 'string' }
  },
  FEATURES: {
    type: 'array',
    transform: (val) => val.split(',') // Auto-transform comma-separated strings
  }
}
  1. Environment Specific Rules

Different environments, different needs:

{
  DEBUG: {
    type: 'boolean',
    env: {
      development: { default: true },
      production: { default: false }
    }
  }
}
  1. Grouped Environments

Stop prefixing everything manually. dotenv-gad groups related variables automatically:

const schema = defineSchema({
  DATABASE: {
    type: 'object',
    envPrefix: 'DATABASE_',
    properties: {
      HOST: { type: 'string', required: true },
      PORT: { type: 'number', default: 5432 },
      PASSWORD: { type: 'string', sensitive: true }
    }
  }
});
//Given
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_PASSWORD=supersecret
//you get
{
  DATABASE: {
    HOST: 'localhost',
    PORT: 5432,
    PASSWORD: 'supersecret'
  }
}
  1. Secret Management

Mark sensitive variables and dotenv-gad automatically excludes them from .env.example:

{
  API_KEY: {
    type: 'string',
    sensitive: true,  // Won't appear in .env.example
    validate: (val) => val.startsWith('sk_')
  }
}
  1. Schema Composition

Build complex configs from simple pieces:

import { composeSchema } from "dotenv-gad";

const dbSchema = { /* database vars */ };
const appSchema = { /* app vars */ };
const authSchema = { /* auth vars */ };

const fullSchema = composeSchema(dbSchema, appSchema, authSchema);

The CLI: Environment Configuration as Code

dotenv-gad ships with a powerful CLI that automates common tasks:

# Validate your .env against the schema
npx dotenv-gad check
# Generate a .env.example file
npx dotenv-gad sync
# Generate TypeScript type definitions
npx dotenv-gad types
# Auto-fix common environment issues
npx dotenv-gad fix
# Generate documentation
npx dotenv-gad docs

Error Reporting:

When validation fails, the error messages are helpful:

Environment validation failed:
  - DATABASE_URL: Missing required environment variable
  - PORT: Must be a number (received: "abc")
  - API_KEY: API key must start with "sk_" (received: "invalid")

By default, sensitive values are masked. But for local debugging, you can reveal them:

const env = loadEnv(schema, { 
  includeRaw: true,
  includeSensitive: true // Use with caution!
});

Framework Integration.

Express.js

import express from "express";
import { loadEnv } from "dotenv-gad";
import schema from "./env.schema";

const env = loadEnv(schema);
const app = express();

app.listen(env.PORT, () => {
  console.log(`Server running on port ${env.PORT}`);
});

Next.js

import { loadEnv } from "dotenv-gad";
import schema from "./env.schema";

const env = loadEnv(schema);

module.exports = {
  env: {
    API_URL: env.API_URL,
  },
};

Vite

Vite has its own environment variable system, but integrating dotenv-gad ensures your variables are validated and type-safe before Vite uses them

// vite.config.ts
import { defineConfig } from "vite";
import dotenvGad from "dotenv-gad/vite";

export default defineConfig({
  plugins: [
    dotenvGad({
      schemaPath: "./env.schema.ts",
      // clientPrefix: "VITE_",   // default — keys matching this prefix are exposed
      // publicKeys: [],          // additional non-prefixed keys to expose
      // generatedTypes: true,    // generate .d.ts for IntelliSense
    }),
  ],
});

Then use it in your application

import { env } from "dotenv-gad/client";

console.log(env.VITE_API_URL); // Full type safety

Why This Matters

  1. Fail Fast: Discover config issues on startup, not in production
  2. Self-Documenting: The schema is your documentation
  3. Type Safety: Your IDE knows about environment variables
  4. Composable: Build configs from reusable pieces
  5. Secure by Default: Sensitive data is never accidentally exposed
  6. CI/CD Friendly: CLI tools integrate seamlessly with automation

dotenv-gad establishes a contract between your application and its environment. Every developer on your team knows exactly what configuration is needed, what format it expects, and whether it’s optional or required.

Getting Started

npm install dotenv-gad

Visit the docs for comprehensive examples and check out the GitHub repo to contribute.


메타데이터
post_id
1bd19b6d632d
slug
dotenv-gad-environment-variable-validation-library-1bd19b6d632d
url
https://medium.com/@kasiimlyee/dotenv-gad-environment-variable-validation-library-1bd19b6d632d
canonical_url
https://medium.com/@kasiimlyee/dotenv-gad-environment-variable-validation-library-1bd19b6d632d
author_url
https://medium.com/@kasiimlyee
status
ok
fetched_at
2026-07-13 06:23:13