Env in HTML
@mongez/vite registers a transformIndexHtml hook that replaces <prefix><KEY><suffix>-style tokens in every emitted HTML file with the corresponding env value.
How it works
- Vite calls the hook with the raw HTML string of each
*.htmlit’s about to emit. - The hook iterates over every key in the
@mongez/dotenvenv store and runs:html = html.replace(new RegExp(`${prefix}${key}${suffix}`, "g"), value); - Keys that have no token in the HTML pass through silently. Tokens that don’t match any key are left in the output unchanged.
Defaults
| Option | Default |
|---|---|
htmlEnvPrefix | "__" (double underscore) |
htmlEnvSuffix | "__" (double underscore) |
Usage
<!DOCTYPE html><html lang="__APP_DEFAULT_LOCALE__" dir="__APP_DEFAULT_DIRECTION__"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="__APP_FAV_ICON__" /> <meta name="theme-color" content="__APP_PRIMARY_COLOR__" /> <meta name="description" content="__APP_DESCRIPTION__" /> <title>__APP_NAME__</title> </head> <body> <div id="root"></div> <script type="module" src="/src/main.tsx"></script> </body></html>APP_NAME="My App"APP_DEFAULT_LOCALE=enAPP_DEFAULT_DIRECTION=ltrAPP_FAV_ICON=/favicon.svgAPP_PRIMARY_COLOR=#0066ffAPP_DESCRIPTION="A web app"After vite build, dist/index.html’s <title> is My App, <html lang> is en, etc.
Custom delimiters
mongezVite({ htmlEnvPrefix: "{{", htmlEnvSuffix: "}}",});<title>{{APP_NAME}}</title>The prefix/suffix are spliced directly into a RegExp constructor, so regex metacharacters like {, }, (, ) need to either be regex-safe or you accept that they’re interpreted as regex. Plain __, {{...}} (with \{\{...\}\} if you write them as a config value), and <!--KEY--> shapes all work — pick something that won’t appear naturally in your HTML.
Type coercion in HTML
Env values are coerced to typed primitives during load (number / boolean / null / string). Substitution stringifies them implicitly:
APP_PORT=3000DEBUG=true<meta name="port" content="__APP_PORT__" /><meta name="debug" content="__DEBUG__" />Result:
<meta name="port" content="3000" /><meta name="debug" content="true" />Gotchas
- Tokens for unknown keys are left intact. This is by design — there’s no warning when a token doesn’t match. If you see
__APP_NAME__in your shipped HTML, the env variable wasn’t loaded. - URL attribute parsers don’t like
%or$. Vite’s HTML transform parses<link href>and<script src>as URLs before our hook runs. If you use%KEY%or$KEY$as delimiters, those characters fail URL parsing on tag attributes. Stick to__KEY__,{{KEY}}, or<!--KEY-->. - The hook runs on every emitted HTML file. If your build emits multiple HTML entry points, env tokens are replaced in each.
- No escaping. If your env value contains
<or&, it’s spliced verbatim into the HTML. Don’t put untrusted input through this transform.