Frontend Environment Variables
The DeployStack frontend uses a sophisticated environment variable system that seamlessly works across development and production environments. This system supports both Vite's build-time variables and Docker runtime variables for maximum flexibility.
Overview
The frontend environment system consists of two layers:
- Development Environment: Uses Vite's built-in environment variable support with
.envfiles - Production Environment: Uses Docker runtime variables that are injected at container startup
This dual approach ensures that:
- Developers can work with standard
.envfiles during development - Production deployments can inject variables at runtime without rebuilding the application
- The same codebase works seamlessly in both environments
Environment Variable Types
Vite Environment Variables (Development)
During development, Vite processes environment variables that start with VITE_ prefix:
# .env
VITE_DEPLOYSTACK_BACKEND_URL=http://localhost:3000
VITE_APP_TITLE=DeployStackRuntime Environment Variables (Production)
In production Docker containers, variables are injected at runtime via the env-config.sh script:
# Docker run example
docker run -e VITE_DEPLOYSTACK_BACKEND_URL="https://api.deploystack.io" \
-e VITE_APP_TITLE="DeployStack Production" \
deploystack/frontend:latestCurrent Environment Variables
Core Application Variables
| Variable | Description | Default Value | Required |
|---|---|---|---|
VITE_DEPLOYSTACK_BACKEND_URL | Backend API base URL | http://localhost:3000 | Yes |
VITE_APP_TITLE | Application title displayed in UI | DeployStack | Yes |
Development Setup
Environment Files
Create environment files in the services/frontend directory:
.env (Base Configuration)
# Base environment variables
VITE_DEPLOYSTACK_BACKEND_URL=http://localhost:3000
VITE_APP_TITLE=DeployStack.env.local (Local Overrides)
# Local development environment variables
# This file is gitignored and used for local customization
VITE_DEPLOYSTACK_BACKEND_URL=http://localhost:3000
VITE_APP_TITLE=DeployStack (Development)Environment File Priority
Vite loads environment files in this order (higher priority overrides lower):
.env.local(highest priority, gitignored).env.development.local.env.development.env(lowest priority)
Development Example
# Navigate to frontend directory
cd services/frontend
# Create your local environment file
cp .env .env.local
# Edit .env.local with your local settings
echo "VITE_APP_TITLE=DeployStack (My Local Dev)" >> .env.local
# Start development server
npm run devProduction Deployment
Docker Environment Variables
The production Docker container uses the env-config.sh script to generate runtime environment variables:
# Production deployment
docker run -d -p 8080:80 \
-e VITE_DEPLOYSTACK_BACKEND_URL="https://api.deploystack.io" \
-e VITE_APP_TITLE="DeployStack Production" \
deploystack/frontend:latestDocker Compose Example
version: '3.8'
services:
frontend:
image: deploystack/frontend:latest
ports:
- "8080:80"
environment:
- VITE_DEPLOYSTACK_BACKEND_URL=https://api.deploystack.io
- VITE_APP_TITLE=DeployStack ProductionUsing Environment Variables in Code
Accessing Variables
Use the utility functions from @/utils/env for consistent access:
import { getEnv, getAllEnv } from '@/utils/env'
// Get a specific environment variable
const backendUrl = getEnv('VITE_DEPLOYSTACK_BACKEND_URL')
const appTitle = getEnv('VITE_APP_TITLE')
// Get all environment variables (useful for debugging)
const allEnvVars = getAllEnv()
console.log('All environment variables:', allEnvVars)Component Usage Example
<script setup lang="ts">
import { getEnv } from '@/utils/env'
// Access environment variables
const backendUrl = getEnv('VITE_DEPLOYSTACK_BACKEND_URL')
const appTitle = getEnv('VITE_APP_TITLE')
// Use in API calls
const apiClient = new ApiClient(backendUrl)
</script>
<template>
<div>
<h1>{{ appTitle }}</h1>
<p>Connected to: {{ backendUrl }}</p>
</div>
</template>Service Layer Example
// services/apiService.ts
import { getEnv } from '@/utils/env'
export class ApiService {
private static baseUrl = getEnv('VITE_DEPLOYSTACK_BACKEND_URL')
static async get(endpoint: string) {
const response = await fetch(`${this.baseUrl}${endpoint}`)
return response.json()
}
static async post(endpoint: string, data: any) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
return response.json()
}
}Adding New Environment Variables
Step 1: Update TypeScript Definitions
Add the new variable to env.d.ts:
interface ImportMetaEnv {
readonly VITE_DEPLOYSTACK_BACKEND_URL: string
readonly VITE_APP_TITLE: string
readonly VITE_NEW_VARIABLE: string // Add your new variable
}Step 2: Add to Environment Files
Add to your .env file:
# .env
VITE_DEPLOYSTACK_BACKEND_URL=http://localhost:3000
VITE_APP_TITLE=DeployStack
VITE_NEW_VARIABLE=default_valueStep 3: Update Docker Configuration (if needed)
For non-VITE_ prefixed variables, update env-config.sh:
# Add specific non-VITE_ variables you want to expose
for var in CUSTOM_VAR OTHER_VAR NEW_CUSTOM_VAR; do
if [ ! -z "$(eval echo \$$var)" ]; then
echo " \"$var\": \"$(eval echo \$$var | sed 's/"/\\"/g')\"," >> /usr/share/nginx/html/runtime-env.js
fi
doneStep 4: Use in Code
import { getEnv } from '@/utils/env'
const newValue = getEnv('VITE_NEW_VARIABLE')Environment Variable Naming Conventions
Development (Vite) Variables
- Must start with
VITE_prefix to be accessible in the browser - Use
SCREAMING_SNAKE_CASEformat - Be descriptive and specific
✅ Good
VITE_DEPLOYSTACK_BACKEND_URL=http://localhost:3000
VITE_APP_TITLE=DeployStack
VITE_ENABLE_DEBUG_MODE=true
❌ Bad
API_URL=http://localhost:3000 # Missing VITE_ prefix
vite_app_title=DeployStack # Wrong case
VITE_URL=http://localhost:3000 # Not descriptiveProduction Runtime Variables
- Can include both
VITE_prefixed and custom variables VITE_variables are automatically processed- Custom variables need to be explicitly added to
env-config.sh
Best Practices
Security
- Never expose sensitive data in environment variables accessible to the browser
- Use backend proxy for sensitive API keys and secrets
- Validate environment variables before using them
// Good: Validate environment variables
const backendUrl = getEnv('VITE_DEPLOYSTACK_BACKEND_URL')
if (!backendUrl) {
throw new Error('VITE_DEPLOYSTACK_BACKEND_URL is required')
}Performance
- Cache environment variables instead of calling
getEnv()repeatedly - Use computed properties in Vue components for reactive environment values
<script setup lang="ts">
import { computed } from 'vue'
import { getEnv } from '@/utils/env'
// Cache the value
const appTitle = computed(() => getEnv('VITE_APP_TITLE'))
</script>Development
- Use
.env.localfor personal development settings - Document all environment variables in this guide
- Provide sensible defaults in
.envfile - Test both development and production environment setups
Troubleshooting
Common Issues
Variable Not Accessible in Browser
Problem: Environment variable is undefined in the browser
Solution: Ensure the variable name starts with VITE_
# ❌ Won't work
API_URL=http://localhost:3000
# ✅ Will work
VITE_API_URL=http://localhost:3000Variable Not Updated in Production
Problem: Environment variable changes don't reflect in production
Solutions:
- Restart the Docker container
- Check if the variable is properly passed to the container
- Verify
env-config.shprocesses the variable correctly
TypeScript Errors
Problem: TypeScript complains about unknown environment variables
Solution: Update env.d.ts with the new variable definition
interface ImportMetaEnv {
readonly VITE_DEPLOYSTACK_BACKEND_URL: string
readonly VITE_APP_TITLE: string
readonly VITE_YOUR_NEW_VARIABLE: string // Add this
}Development vs Production Differences
Problem: Different behavior between development and production
Solutions:
- Use the same variable names in both environments
- Test with Docker locally:
docker build -t test . && docker run -e VITE_VAR=value test - Use
getAllEnv()to debug variable values
Validation Utility
Create a validation utility for critical environment variables:
// utils/envValidation.ts
import { getEnv } from './env'
export function validateEnvironment() {
const required = [
'VITE_DEPLOYSTACK_BACKEND_URL',
'VITE_APP_TITLE'
]
const missing = required.filter(key => !getEnv(key))
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`)
}
}
// Use in main.ts
import { validateEnvironment } from '@/utils/envValidation'
validateEnvironment()Related Documentation
- Frontend Development Guide - Main frontend development guide
- Deploy DeployStack - Deploy DeployStack with Docker Compose
Custom Components
Complete guide for creating, managing, and extending custom UI components in the DeployStack frontend, including best practices for integrating with shadcn/vue.
Event Bus
Complete guide to using the global event bus system for cross-component communication in the DeployStack frontend.