One of Zephyr's most powerful capabilities is the ability to override application configuration on a per-deployment-environment basis. This means the same built application can dynamically adapt its behavior - consuming different versions of remote dependencies and using different environment variable values - depending on which environment URL serves it.
The features described on this page are currently in Beta, which means we are still improving and polishing every step of the implementation.
Environment-level overrides enable two key capabilities:
Both features work through the same underlying system: Zephyr captures configuration at build time in a manifest, then dynamically applies environment-specific overrides at runtime based on which environment serves your application.
Behind the scenes, Zephyr generates a zephyr-manifest.json file at build time that records:
zephyr:dependencies configurationZE_PUBLIC_ from your build environmentThis manifest enables runtime override capabilities - you don't need to interact with this file directly, but it's what makes environment-level customization possible without rebuilding your application.
Key benefit: Build once, deploy everywhere with environment-specific configuration.
When you build your application, Zephyr resolves your remote dependencies based on the version selectors in your zephyr:dependencies configuration. However, at the environment level, you can override these declarations to point to different versions, tags, or environments of your remotes without rebuilding.
Build-time: Your application is built with remote dependency declarations from package.json:
Environment-level: Each deployment environment can override which version of each remote to load:
| Environment | header Override | cart Override |
|---|---|---|
| Development | @latest | @beta |
| Staging | @beta | 2.1.0-rc.1 |
| Production | @stable | 2.0.5 |
Runtime: When your application is served from an environment URL, Zephyr dynamically resolves remotes based on that environment's override configuration.
The override system operates through three components:
To configure remote dependency overrides for an environment:
1.2.3)latest, beta)staging, production)
Each remote can have a different override strategy. For example, you might override ui-components to use @latest while keeping payment-processor locked to a specific version for stability.
Let's say you have a host application that depends on three remotes: header, cart, and analytics.
Build-time configuration (package.json):
Environment-level overrides:
| Environment | header Override | cart Override | analytics Override |
|---|---|---|---|
| Development | @latest | @beta | @development |
| Staging | @beta | 2.1.0-rc.1 | @staging |
| Production | @stable | 2.0.5 | @production |
What happens:
The same built application adapts its remote dependencies based on which environment serves it. No rebuild required to test different integration scenarios.
1. Integration Testing with Beta Features
Your staging environment can consume beta versions of remotes to test new features before they reach production:
2. Gradual Remote Rollouts
Roll out new versions of remotes progressively:
header@3.0.0header@3.0.0header@3.0.0Each environment tests the new version before the next environment adopts it.
3. Debugging Production Issues
If you suspect a remote is causing issues, quickly override production to use a previous version without rebuilding:
When an environment has a remote override configured, the resolution order is:
zephyr:dependenciesThis means environment overrides always take precedence over the build-time configuration, giving you full control at serve time.
Zephyr provides a powerful system for managing environment variables that can be overridden on a per-environment basis at runtime. By prefixing environment variables with ZE_PUBLIC_ in your build configuration, Zephyr captures them at build time and makes them available for environment-specific overrides.
Build-time: You prefix variables with ZE_PUBLIC_ in your local .env file:
Environment-level: Each deployment environment can override these values:
| Environment | ZE_PUBLIC_API_URL | ZE_PUBLIC_FEATURE_FLAGS |
|---|---|---|
| Development | https://api.dev.example.com | beta-ui,new-checkout,analytics |
| Staging | https://api.staging.example.com | new-checkout,analytics |
| Production | https://api.example.com | analytics |
Runtime: When served from an environment URL, your application receives that environment's variable values.
The system operates through three stages:
ZE_PUBLIC_ and captures their valueszephyr-manifest.json file (generated automatically)This means you can build your application once and deploy it to multiple environments, with each environment using its own configuration values without requiring a rebuild.
To make an environment variable manageable by Zephyr, prefix it with ZE_PUBLIC_ in your local .env file or build environment:
When Zephyr builds your application, it captures the values of all ZE_PUBLIC_ variables and makes them available for environment-level overrides.
The ZE_PUBLIC_ prefix is required for Zephyr to identify and manage these variables. In your application code, you'll reference them with the full name including the prefix (e.g., process.env.ZE_PUBLIC_API_URL).
After building your application, you can override the values of ZE_PUBLIC_ variables for each environment through the Zephyr dashboard:
ZE_PUBLIC_ variable, you can set an environment-specific override valueWhen your application is served from that environment's URL, it will use the overridden values instead of the build-time values.
Let's say you're building an e-commerce application that needs to connect to different API endpoints in different environments.
Local .env file (build-time configuration):
Environment-level overrides:
| Environment | ZE_PUBLIC_API_URL | ZE_PUBLIC_STRIPE_KEY | ZE_PUBLIC_ANALYTICS_ID |
|---|---|---|---|
| Development | https://api.dev.example.com | pk_test_51ABC123xyz | UA-00000000-1 |
| Staging | https://api.staging.example.com | pk_test_51DEF456xyz | UA-11111111-1 |
| Production | https://api.example.com | pk_live_51GHI789xyz | UA-22222222-1 |
In your application code:
Use the environment variables exactly as you normally would - no special imports or configuration needed:
Zephyr's bundler integration handles all the complexity behind the scenes through an importmap injected into your HTML. Simply prefix your variables with ZE_PUBLIC_ and access them normally in your code.
What happens:
The same built application adapts its configuration dynamically based on which environment URL serves it. No rebuild required.
Public vs Secret Variables:
The ZE_PUBLIC_ prefix indicates that these variables may be exposed to the client-side code. This is important to understand:
Variables prefixed with ZE_PUBLIC_ are intended for client-side use and may be visible in your bundled application code. Never store sensitive secrets in these variables. For sensitive data, use Zephyr's secure environment variables (without the prefix) which are only available server-side.
For truly sensitive values that should never be exposed client-side, use regular environment variables without the ZE_PUBLIC_ prefix. These can still be managed per-environment in the Zephyr dashboard but won't be included in the client bundle.
1. Environment-Specific API Endpoints
Point to different backend services per environment without rebuilding:
2. Feature Flags and Toggles
Enable different features in different environments:
3. Third-Party Service Configuration
Use different accounts or keys for external services:
4. CDN and Asset Management
Point to different CDN endpoints or asset locations:
Remote dependency overrides and environment variable overrides work seamlessly together to provide complete environment-level customization:
Together, they enable powerful deployment strategies:
Example: Staging environment for integration testing
The same built application adapts both its module dependencies and configuration based on which environment serves it.
Environment-level overrides integrate seamlessly with Zephyr's other features:
This creates a powerful composition model where your application's behavior is defined at build time but can be customized at deployment time without rebuilding.
@latest or @beta to automatically pick up remote updatesVariable Organization:
Group related variables with consistent prefixing:
Environment Settings:
Before applying overrides to production:
Maintain documentation for your team that includes:
ZE_PUBLIC_ variables your application uses and their purposeYou don't need to use all features at once. Start by overriding one or two variables or remotes in non-production environments, then gradually expand as you become comfortable with the system.