BrowserDevTools

Vite .env validator

Paste your .env and your .env.example: you get missing, extra and empty variables, duplicate keys with line numbers, the Vite-specific traps (a VITE_ prefixed secret is inlined into the client bundle), and a ready-to-commit env.d.ts.

Both files are parsed locally in this tab. Nothing is uploaded and there is no share link — a .env file should never leave your machine.

Findings

6 keys · 3 errors · 3 warnings
  • errorVITE_STRIPE_SECRET_KEY"VITE_STRIPE_SECRET_KEY" looks like a secret but carries the client prefix, so Vite inlines it into the client bundle. Anyone can read it.
  • errorVITE_STRIPE_SECRET_KEY"VITE_STRIPE_SECRET_KEY" is exposed to the client and its value looks like a real credential (Stripe/OpenAI-style key). Rotate it if this file is real.
  • errorVITE_SENTRY_DSNDefined in the example but missing here: "VITE_SENTRY_DSN" — the app will read undefined.
  • warnVITE_STRIPE_SECRET_KEYPresent here but not in the example: "VITE_STRIPE_SECRET_KEY" — remember to add it to .env.example for the next person.
  • warnAPI_TIMEOUTPresent here but not in the example: "API_TIMEOUT" — remember to add it to .env.example for the next person.
  • warnAPI_TIMEOUT"API_TIMEOUT" exists but has an empty value.
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly API_TIMEOUT?: string;
  readonly DATABASE_URL: string;
  readonly SESSION_SECRET: string;
  readonly VITE_ANALYTICS_ID: string;
  readonly VITE_API_URL: string;
  readonly VITE_STRIPE_SECRET_KEY?: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

Why a validator instead of another converter

Search for “.env to json” and you get a page of converters. They all do the same mechanical thing, and none of them answers the question you actually have during a deploy: is this file complete, and is anything in it dangerous?

So this tool is built the other way round — conversion is the by-product, checking is the product. It compares two files, applies the rules that are specific to Vite (what most Vue 3 projects run on), and hands back a typed env.d.ts so nobody has to hand-write one again.

Everything happens in your tab: the files are parsed locally, nothing is uploaded and no share link is created. That matters more than usual here, because a .env file is exactly the kind of file that should never leave your machine. Treat the output as a review aid: the validator knows syntax and Vite rules, it does not know your deployment.

FAQ

Is my .env uploaded?
No. Parsing, comparison and code generation run in your browser. There is no backend endpoint for the file content, no logging and no share link — check the Network panel if you want proof.
Why Vite and not plain dotenv?
Because the dangerous rules are Vite’s. Plain dotenv has no client/server split, so a leftover VITE_ prefix on a secret is harmless there and serious here. The parser still understands ordinary .env syntax: comments, quoted values and the export prefix.
Does it read my other .env files?
No. Vite layers .env, .env.local, .env.[mode] and .env.[mode].local in a specific order; this tool compares the two files you paste, so you can see what a deployment is missing without guessing which layer wins.
What counts as a secret?
A key whose name matches patterns such as SECRET, TOKEN, PASSWORD, PRIVATE, CREDENTIAL, API_KEY, DATABASE_URL or DSN, plus values that look like real credentials (JWT, sk-live-, ghp_, AKIA, long hex or base64). It is a review heuristic, not a security guarantee.
Can I use the output in CI?
The env.d.ts and .env.example are plain files you can commit. The checks themselves run in the browser; a blocking CI gate would need a dotenv linter in the pipeline — this tool is for the moment you are staring at a deploy that failed.