Browse Source

Document environment variable precedence and API configuration scheme

Add comprehensive documentation explaining the order of precedence for
environment variables in TimeSafari project. Covers shell script overrides,
platform-specific configurations, .env file usage, and API alignment between
claim and partner APIs. Includes troubleshooting guide and best practices
for maintaining consistent environment configuration across development,
test, and production environments.
get-get-hash
Matthew Raymer 1 week ago
parent
commit
974d33b322
  1. 338
      docs/build-system/environment-variable-precedence.md
  2. 3
      docs/build-system/platforms/android-custom-api-ip.md
  3. 4
      scripts/build-android.sh
  4. 3
      scripts/build-ios.sh
  5. 10
      scripts/common.sh

338
docs/build-system/environment-variable-precedence.md

@ -0,0 +1,338 @@
# 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)

3
docs/build-system/platforms/android-custom-api-ip.md

@ -144,14 +144,17 @@ The build system handles API server configuration as follows:
```bash ```bash
# Development mode with Android emulator default (10.0.2.2) # Development mode with Android emulator default (10.0.2.2)
export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000"
export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000"
npm run build:capacitor -- --mode development npm run build:capacitor -- --mode development
# Development mode with iOS simulator default (localhost) # Development mode with iOS simulator default (localhost)
export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000"
export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000"
npm run build:capacitor -- --mode development npm run build:capacitor -- --mode development
# Development mode with custom IP # Development mode with custom IP
export VITE_DEFAULT_ENDORSER_API_SERVER="http://192.168.1.100:3000" export VITE_DEFAULT_ENDORSER_API_SERVER="http://192.168.1.100:3000"
export VITE_DEFAULT_PARTNER_API_SERVER="http://192.168.1.100:3000"
npm run build:capacitor -- --mode development npm run build:capacitor -- --mode development
``` ```

4
scripts/build-android.sh

@ -186,15 +186,17 @@ log_info "Build type: $BUILD_TYPE"
# Setup environment for Capacitor build # Setup environment for Capacitor build
setup_build_env "capacitor" setup_build_env "capacitor"
# Override API server for Android development # Override API servers for Android development
if [ "$BUILD_MODE" = "development" ]; then if [ "$BUILD_MODE" = "development" ]; then
if [ -n "$CUSTOM_API_IP" ]; then if [ -n "$CUSTOM_API_IP" ]; then
# Use custom IP for physical device development # Use custom IP for physical device development
export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000" export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000"
export VITE_DEFAULT_PARTNER_API_SERVER="http://${CUSTOM_API_IP}:3000"
log_info "Android development mode: Using custom IP ${CUSTOM_API_IP} for physical device" log_info "Android development mode: Using custom IP ${CUSTOM_API_IP} for physical device"
else else
# Use Android emulator IP (10.0.2.2) for Android development # Use Android emulator IP (10.0.2.2) for Android development
export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000"
export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000"
log_debug "Android development mode: Using 10.0.2.2 for emulator" log_debug "Android development mode: Using 10.0.2.2 for emulator"
fi fi
fi fi

3
scripts/build-ios.sh

@ -313,10 +313,11 @@ log_info "Build type: $BUILD_TYPE"
# Setup environment for Capacitor build # Setup environment for Capacitor build
setup_build_env "capacitor" setup_build_env "capacitor"
# Override API server for iOS development when custom IP is specified # Override API servers for iOS development when custom IP is specified
if [ "$BUILD_MODE" = "development" ] && [ -n "$CUSTOM_API_IP" ]; then if [ "$BUILD_MODE" = "development" ] && [ -n "$CUSTOM_API_IP" ]; then
# Use custom IP for physical device development # Use custom IP for physical device development
export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000" export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000"
export VITE_DEFAULT_PARTNER_API_SERVER="http://${CUSTOM_API_IP}:3000"
log_info "iOS development mode: Using custom IP ${CUSTOM_API_IP} for physical device" log_info "iOS development mode: Using custom IP ${CUSTOM_API_IP} for physical device"
fi fi

10
scripts/common.sh

@ -200,19 +200,19 @@ setup_build_env() {
# For Capacitor development, use localhost by default # For Capacitor development, use localhost by default
# Android builds will override this in build-android.sh # Android builds will override this in build-android.sh
export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000"
log_debug "Development mode: Using localhost for Endorser API, production for Image/Partner APIs" export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000"
log_debug "Development mode: Using localhost for Endorser and Partner APIs"
export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app" export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app"
export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch"
elif [ "$BUILD_MODE" = "test" ]; then elif [ "$BUILD_MODE" = "test" ]; then
export VITE_DEFAULT_ENDORSER_API_SERVER="https://test-api.endorser.ch" export VITE_DEFAULT_ENDORSER_API_SERVER="https://test-api.endorser.ch"
export VITE_DEFAULT_PARTNER_API_SERVER="https://test-partner-api.endorser.ch"
log_debug "Test mode: Using test Endorser and Partner APIs"
export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app" export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app"
export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch"
log_debug "Test mode: Using test Endorser API, production for Image/Partner APIs"
elif [ "$BUILD_MODE" = "production" ]; then elif [ "$BUILD_MODE" = "production" ]; then
export VITE_DEFAULT_ENDORSER_API_SERVER="https://api.endorser.ch" export VITE_DEFAULT_ENDORSER_API_SERVER="https://api.endorser.ch"
export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app"
export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch" export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch"
log_debug "Production mode: Using production API servers" log_debug "Production mode: Using production API servers"
export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app"
fi fi
# Log environment setup # Log environment setup

Loading…
Cancel
Save