Browser
Seed a PortableSource from the config your bundler injects, with no filesystem in the browser.
In the browser there is no filesystem and no process.env. Your bundler inlines configuration at build time, and you seed a PortableSource from it, then read with the same typed API as everywhere else.
Import from envapt. The package export conditions resolve a node-free portable build in the browser automatically, so the same import works in local dev and in the bundle.
The filesystem-only config APIs have nothing to do in the browser, so they warn and no-op by default. Readers work as normal. See Compatibility for fileApiMode and Errors for the codes.
import { } from 'envapt';
.('FEATURE_BETA', false); // readers work
. = '/tmp'; // warns once and no-ops in the browserSeed from your bundler
Bundlers replace build-time env references with string literals: Vite exposes them on import.meta.env, webpack through DefinePlugin. Pass that object to PortableSource, then read the values typed.
import { Envapter, PortableSource, Converters } from 'envapt';
Envapter.useSource(new PortableSource(import.meta.env));
const apiUrl = Envapter.getUsing('VITE_API_URL', Converters.Url); // URL, not a raw string
const beta = Envapter.getBoolean('VITE_ENABLE_BETA', false); // booleanimport.meta.env.VITE_API_URL is a string; Envapter.getUsing('VITE_API_URL', Converters.Url) returns a URL, and getBoolean returns a boolean. PortableSource snapshots the object and JSON-stringifies non-string values, so you can read Vite's boolean DEV and PROD flags too.
Anything you seed into a browser PortableSource ships in your client bundle. Pass public configuration only,
never a secret or a server-side key.
Environment detection
Envapter.environment and the isProduction / isDevelopment / isTest helpers also read MODE, which Vite sets to development, production, or your --mode value. Because you bind import.meta.env, they work with no extra wiring. See Environment.
No filesystem
PortableSource snapshots its object at construction, so mutating that object afterward does not change what envapt reads. There is no .env cascade in the browser, and reading before you bind a source throws NoSourceBound. See Sources.
Decorators
The default @Envapt accessor decorators work in the browser build, the legacy envapt/legacy form needs a compile step.
For the providers and the contract see Sources.