# Environment Variable Precedence and API Configuration **Date:** August 4, 2025 **Author:** Matthew Raymer ## Overview This document explains the order of precedence for environment variables in the TimeSafari project, how `.env` files are used, and the API configuration scheme for different environments. ## Order of Precedence (Highest to Lowest) ### 1. Shell Script Overrides (Highest Priority) Shell scripts can override environment variables for platform-specific needs: ```bash # scripts/common.sh - setup_build_env() if [ "$BUILD_MODE" = "development" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000" fi ``` ### 2. Platform-Specific Overrides (High Priority) Platform-specific build scripts can override for mobile development: ```bash # scripts/build-android.sh if [ "$BUILD_MODE" = "development" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000" fi ``` ### 3. Environment-Specific .env Files (Medium Priority) Environment-specific `.env` files provide environment-specific defaults: ```bash # .env.development, .env.test, .env.production VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 ``` ### 4. Fallback .env File (Low Priority) General `.env` file provides project-wide defaults: ```bash # .env (if exists) VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 ``` ### 5. app.ts Constants (Lowest Priority - Fallback) Hardcoded constants in `src/constants/app.ts` provide safety nets: ```typescript export const DEFAULT_ENDORSER_API_SERVER = import.meta.env.VITE_DEFAULT_ENDORSER_API_SERVER || AppString.PROD_ENDORSER_API_SERVER; ``` ## Build Process Flow ### 1. Shell Scripts Set Base Values ```bash # scripts/common.sh setup_build_env() { if [ "$BUILD_MODE" = "development" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000" fi } ``` ### 2. Platform-Specific Overrides ```bash # scripts/build-android.sh if [ "$BUILD_MODE" = "development" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000" fi ``` ### 3. Load .env Files ```bash # scripts/build-web.sh local env_file=".env.$BUILD_MODE" # .env.development, .env.test, .env.production if [ -f "$env_file" ]; then load_env_file "$env_file" fi # Fallback to .env if [ -f ".env" ]; then load_env_file ".env" fi ``` ### 4. Vite Processes Environment ```typescript // vite.config.common.mts dotenv.config(); // Loads .env files ``` ### 5. Application Uses Values ```typescript // src/constants/app.ts export const DEFAULT_ENDORSER_API_SERVER = import.meta.env.VITE_DEFAULT_ENDORSER_API_SERVER || AppString.PROD_ENDORSER_API_SERVER; ``` ## API Configuration Scheme ### Environment Configuration Summary | Environment | Endorser API (Claims) | Partner API | Image API | |-------------|----------------------|-------------|-----------| | **Development** | `http://localhost:3000` | `http://localhost:3000` | `https://image-api.timesafari.app` | | **Test** | `https://test-api.endorser.ch` | `https://test-partner-api.endorser.ch` | `https://image-api.timesafari.app` | | **Production** | `https://api.endorser.ch` | `https://partner-api.endorser.ch` | `https://image-api.timesafari.app` | ### Mobile Development Overrides #### Android Development - **Emulator**: `http://10.0.2.2:3000` (Android emulator default) - **Physical Device**: `http://{CUSTOM_IP}:3000` (Custom IP for physical device) #### iOS Development - **Simulator**: `http://localhost:3000` (iOS simulator default) - **Physical Device**: `http://{CUSTOM_IP}:3000` (Custom IP for physical device) ## .env File Structure ### .env.development ```bash # ========================================== # DEVELOPMENT ENVIRONMENT CONFIGURATION # ========================================== # API Server Configuration: # - Endorser API (Claims): Local development server # - Partner API: Local development server (aligned with claims) # - Image API: Test server (shared for development) # ========================================== # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. # iOS doesn't like spaces in the app title. TIME_SAFARI_APP_TITLE="TimeSafari_Dev" VITE_APP_SERVER=http://localhost:8080 # This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F # API Servers (Development - Local) VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 # Image API (Test server for development) VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app # Push Server (disabled for localhost) #VITE_DEFAULT_PUSH_SERVER... can't be set up with localhost domain # Feature Flags VITE_PASSKEYS_ENABLED=true ``` ### .env.test ```bash # ========================================== # TEST ENVIRONMENT CONFIGURATION # ========================================== # API Server Configuration: # - Endorser API (Claims): Test server # - Partner API: Test server (aligned with claims) # - Image API: Test server # ========================================== # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. # iOS doesn't like spaces in the app title. TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app # This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F # API Servers (Test Environment) VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch # Image API (Test server) VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app # Push Server (Test) VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app # Feature Flags VITE_PASSKEYS_ENABLED=true ``` ### .env.production ```bash # ========================================== # PRODUCTION ENVIRONMENT CONFIGURATION # ========================================== # API Server Configuration: # - Endorser API (Claims): Production server # - Partner API: Production server (aligned with claims) # - Image API: Production server # ========================================== # Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. # App Server VITE_APP_SERVER=https://timesafari.app # This is the claim ID for actions in the BVC project. VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01GXYPFF7FA03NXKPYY142PY4H # API Servers (Production Environment) VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch # Image API (Production server) VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app # Push Server (Production) VITE_DEFAULT_PUSH_SERVER=https://timesafari.app ``` ## Key Principles ### 1. API Alignment - **Partner API** values follow the same pattern as **Claim API** (Endorser API) - Both APIs use the same environment-specific endpoints - This ensures consistency across the application ### 2. Platform Flexibility - Shell scripts can override for platform-specific needs - Android emulator uses `10.0.2.2:3000` - iOS simulator uses `localhost:3000` - Physical devices use custom IP addresses ### 3. Environment Isolation - Each environment has its own `.env` file - Test environment uses test APIs - Development environment uses local APIs - Production environment uses production APIs ### 4. Safety Nets - Hardcoded constants in `app.ts` provide fallbacks - Multiple layers of configuration prevent failures - Clear precedence order ensures predictable behavior ## Usage Examples ### Development Build ```bash # Uses .env.development + shell script overrides npm run build:web -- --mode development ``` ### Test Build ```bash # Uses .env.test + shell script overrides npm run build:web -- --mode test ``` ### Production Build ```bash # Uses .env.production + shell script overrides npm run build:web -- --mode production ``` ### Android Development ```bash # Uses .env.development + Android-specific overrides ./scripts/build-android.sh --dev ``` ### iOS Development ```bash # Uses .env.development + iOS-specific overrides ./scripts/build-ios.sh --dev ``` ## Troubleshooting ### Environment Variable Debugging ```bash # Show current environment variables ./scripts/build-web.sh --env # Check specific variable echo $VITE_DEFAULT_ENDORSER_API_SERVER ``` ### Common Issues 1. **Wrong API Server**: Check if shell script overrides are correct 2. **Missing .env File**: Ensure environment-specific .env file exists 3. **Platform-Specific Issues**: Verify platform overrides in build scripts 4. **Vite Not Loading**: Check if `dotenv.config()` is called ### Validation ```bash # Validate environment configuration npm run test-env ``` ## Best Practices 1. **Always use environment-specific .env files** for different environments 2. **Keep shell script overrides minimal** and platform-specific 3. **Document API alignment** in .env file headers 4. **Use hardcoded fallbacks** in `app.ts` for safety 5. **Test all environments** before deployment 6. **Validate configuration** with test scripts ## Related Documentation - [Build System Overview](../build-system/README.md) - [Android Custom API IP](../platforms/android-custom-api-ip.md) - [API Configuration](../api-configuration.md) - [Environment Setup](../environment-setup.md)