Vite exposes only environment variables that start with VITE_ to your client code, and it bundles their values into the build. Variables without the prefix stay out. That protects accidental leaks, but it means VITE_ values are public, so they must never hold API keys or other secrets.
How the prefix works
Vite puts env variables on import.meta.env as strings. The documentation says variables prefixed with VITE_ are exposed in client-side source code after bundling. Its own example makes the point: a VITE_SOME_KEY value is readable in the browser, while DB_PASSWORD from the same file comes back undefined.
The docs also advise avoiding the prefix to prevent accidentally leaking variables. The prefix is the safety catch. Flipping it on a sensitive value removes it.
The explicit warning
Vite states that VITE_ variables should not contain sensitive information such as API keys, because the values are bundled into your source code at build time. For production it points to a backend server or serverless or edge functions to protect secrets.
In practice that means the browser calls your function, and the function holds the key. The browser never sees the credential, and you can rate limit, log and revoke at the function.
Files and what git should ignore
Vite loads several files from the environment directory. A plain .env loads in all cases. .env.local loads in all cases and is ignored by git. Mode files such as .env.production load only in that mode, and their .local variants are git-ignored too.
The docs say .env.*.local files are local only and can contain sensitive variables, and they recommend adding *.local to your .gitignore. Do that on day one.
A subtle point follows from this. The committed .env and .env.production files are for non-sensitive defaults. Real secrets belong in the deployment environment or a secrets service, not in any file the repository tracks.
Precedence can surprise you
Variables that already exist in the environment when Vite starts have the highest priority and are not overwritten by .env files. A mode file beats the generic one. Variables set only in .env or .env.local still apply.
This matters for security in one way: a value you believe comes from production configuration may be silently overridden, or silently missing, depending on what exists in the build environment. Print the resolved non-secret values in the build log for the mode you ship, and check them.
Env files are read at start. Restart the dev server after edits.
Everything is a string
Vite parses values as strings, including booleans. A flag written as false in an env file is the string "false", and a naive truthiness check treats it as on. If a feature or a security toggle is driven by an env variable, convert it explicitly and fail the build on values you do not recognize.
A short review checklist
- Every VITE_ name is something you would print on your homepage.
*.localis in.gitignore.- Secrets are read by a server or edge function, not the browser bundle.
- Booleans are parsed, not compared as strings.
- The build log shows which mode and which public values were used.
Quick check
Does Vite hide variables without the VITE_ prefix?
Yes from client code. They are not exposed in the browser bundle, but they can still be read by build tooling and server-side code, so keep them out of the repository.
Is it safe to put an API key in VITE_ if the key is restricted?
The docs advise against sensitive values. A restricted key is still public, so treat it as visible and limit what it can do.
Sources
Last reviewed: 19 October 2026.