Environment Setup
Configure environment variables and settings for different deployment environments
Environment Variables
WI-CARPOOL uses environment variables to configure different aspects of the application for various deployment environments.
Environment Variables (.env)
# API Configuration
VITE_API_BASE_URL=http://localhost:3000/api
VITE_API_TIMEOUT=30000
# Google Maps Configuration
VITE_GOOGLE_MAPS_API_KEY=your_google_maps_api_key_here
# Firebase Configuration (if using Firebase)
VITE_FIREBASE_API_KEY=your_firebase_api_key
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
# Payment Integration
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_key
VITE_PAYPAL_CLIENT_ID=your_paypal_client_id
# Application Configuration
VITE_APP_NAME=WI-CARPOOL
VITE_APP_VERSION=1.0.0
VITE_APP_ENVIRONMENT=development
# Feature Flags
VITE_ENABLE_ANALYTICS=true
VITE_ENABLE_PUSH_NOTIFICATIONS=true
VITE_ENABLE_GEOLOCATION=true
# CDN and Asset URLs
VITE_CDN_URL=https://cdn.example.com
VITE_UPLOAD_URL=https://upload.example.com
Environment-Specific Configurations
Development Environment
.env.development
# Development specific settings
VITE_API_BASE_URL=http://localhost:3000/api
VITE_APP_ENVIRONMENT=development
VITE_ENABLE_DEBUG_TOOLS=true
VITE_LOG_LEVEL=debug
# Use development versions of services
VITE_GOOGLE_MAPS_API_KEY=development_api_key
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_development_key
# Local storage and caching
VITE_ENABLE_SERVICE_WORKER=false
VITE_CACHE_DURATION=300
Production Environment
.env.production
# Production specific settings
VITE_API_BASE_URL=https://api.wicarpool.com
VITE_APP_ENVIRONMENT=production
VITE_ENABLE_DEBUG_TOOLS=false
VITE_LOG_LEVEL=error
# Production service keys
VITE_GOOGLE_MAPS_API_KEY=production_api_key
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_production_key
# Performance optimizations
VITE_ENABLE_SERVICE_WORKER=true
VITE_CACHE_DURATION=3600
# Security settings
VITE_ENABLE_CSP=true
VITE_SECURE_COOKIES=true
Staging Environment
.env.staging
# Staging specific settings
VITE_API_BASE_URL=https://staging-api.wicarpool.com
VITE_APP_ENVIRONMENT=staging
VITE_ENABLE_DEBUG_TOOLS=true
VITE_LOG_LEVEL=info
# Staging service keys
VITE_GOOGLE_MAPS_API_KEY=staging_api_key
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_staging_key
# Testing configurations
VITE_ENABLE_E2E_HELPERS=true
[email protected]
Configuration Management
Configuration Provider
Environment Configuration Hook
// src/hooks/useConfig.ts
import { useMemo } from 'react'
interface AppConfig {
apiBaseUrl: string
environment: 'development' | 'staging' | 'production'
googleMapsApiKey: string
stripePublishableKey: string
enableAnalytics: boolean
enablePushNotifications: boolean
logLevel: 'debug' | 'info' | 'warn' | 'error'
}
export function useConfig(): AppConfig {
return useMemo(() => ({
apiBaseUrl: import.meta.env.VITE_API_BASE_URL,
environment: import.meta.env.VITE_APP_ENVIRONMENT,
googleMapsApiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY,
stripePublishableKey: import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY,
enableAnalytics: import.meta.env.VITE_ENABLE_ANALYTICS === 'true',
enablePushNotifications: import.meta.env.VITE_ENABLE_PUSH_NOTIFICATIONS === 'true',
logLevel: import.meta.env.VITE_LOG_LEVEL || 'info',
}), [])
}
// Usage in components
function MyComponent() {
const config = useConfig()
if (config.environment === 'development') {
console.log('Running in development mode')
}
return <div>App Environment: {config.environment}</div>
}
Runtime Configuration
Dynamic Configuration Loading
// src/config/runtime.ts
interface RuntimeConfig {
features: {
chat: boolean
payments: boolean
notifications: boolean
}
limits: {
maxFileSize: number
maxImages: number
searchRadius: number
}
api: {
timeout: number
retries: number
}
}
class ConfigManager {
private config: RuntimeConfig | null = null
async loadConfig(): Promise<RuntimeConfig> {
if (this.config) return this.config
try {
const response = await fetch('/config.json')
this.config = await response.json()
return this.config
} catch (error) {
console.warn('Failed to load runtime config, using defaults')
return this.getDefaultConfig()
}
}
private getDefaultConfig(): RuntimeConfig {
return {
features: {
chat: true,
payments: true,
notifications: true,
},
limits: {
maxFileSize: 5 * 1024 * 1024, // 5MB
maxImages: 5,
searchRadius: 50, // km
},
api: {
timeout: 30000,
retries: 3,
},
}
}
}
export const configManager = new ConfigManager()
Security Best Practices
Environment Variable Security
- Never commit sensitive keys to version control
- Use different API keys for different environments
- Rotate API keys regularly
- Validate environment variables at runtime
Configuration Validation
Environment Validation
// src/config/validation.ts
import { z } from 'zod'
const envSchema = z.object({
VITE_API_BASE_URL: z.string().url(),
VITE_GOOGLE_MAPS_API_KEY: z.string().min(1),
VITE_APP_ENVIRONMENT: z.enum(['development', 'staging', 'production']),
VITE_ENABLE_ANALYTICS: z.string().optional(),
VITE_ENABLE_PUSH_NOTIFICATIONS: z.string().optional(),
})
export function validateEnvironment() {
const result = envSchema.safeParse(import.meta.env)
if (!result.success) {
console.error('Invalid environment configuration:', result.error.format())
throw new Error('Environment validation failed')
}
return result.data
}
// Call this during app initialization
validateEnvironment()
Build Configuration
Vite Configuration
vite.config.ts Environment Setup
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react-swc'
import path from 'path'
export default defineConfig(({ command, mode }) => {
// Load environment variables
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
define: {
// Make environment available to the app
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
__BUILD_TIME__: JSON.stringify(new Date().toISOString()),
},
server: {
host: '::',
port: 8080,
proxy: {
'/api': {
target: env.VITE_API_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
build: {
sourcemap: mode !== 'production',
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
ui: ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
},
},
},
},
}
})
Local Development Setup
Development Scripts
package.json Scripts
{
"scripts": {
"dev": "vite",
"dev:staging": "vite --mode staging",
"build": "tsc && vite build",
"build:staging": "tsc && vite build --mode staging",
"build:production": "tsc && vite build --mode production",
"preview": "vite preview",
"preview:staging": "vite preview --mode staging",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"env:check": "node scripts/check-env.js",
"env:copy": "cp .env.example .env"
}
}
Environment Setup Script
scripts/setup-env.js
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
async function setupEnvironment() {
console.log('š WI-CARPOOL Environment Setup\n')
const envPath = path.join(process.cwd(), '.env')
if (fs.existsSync(envPath)) {
console.log('ā ļø .env file already exists')
const answer = await question('Do you want to overwrite it? (y/N): ')
if (answer.toLowerCase() !== 'y') {
console.log('Setup cancelled')
process.exit(0)
}
}
const config = {}
config.VITE_API_BASE_URL = await question('API Base URL (http://localhost:3000/api): ') || 'http://localhost:3000/api'
config.VITE_GOOGLE_MAPS_API_KEY = await question('Google Maps API Key: ')
config.VITE_APP_ENVIRONMENT = await question('Environment (development): ') || 'development'
const envContent = Object.entries(config)
.map(([key, value]) => `${key}=${value}`)
.join('\n')
fs.writeFileSync(envPath, envContent)
console.log('\nā
Environment file created successfully!')
console.log('š§ Run "npm run dev" to start the development server')
rl.close()
}
function question(prompt) {
return new Promise((resolve) => {
rl.question(prompt, resolve)
})
}
setupEnvironment().catch(console.error)
Troubleshooting
Common Issues
- Environment variables not loading: Ensure variables start with VITE_ prefix
- API calls failing: Check VITE_API_BASE_URL is correctly set
- Maps not working: Verify Google Maps API key and enabled services
- Build errors: Validate all required environment variables are set
Environment Debugging
Debug Environment Variables
// Add this to your main.tsx for debugging
if (import.meta.env.DEV) {
console.log('Environment Variables:', {
API_BASE_URL: import.meta.env.VITE_API_BASE_URL,
ENVIRONMENT: import.meta.env.VITE_APP_ENVIRONMENT,
GOOGLE_MAPS_KEY: import.meta.env.VITE_GOOGLE_MAPS_API_KEY ? 'ā Set' : 'ā Missing',
})
}