Skip to main content

Environment Configuration Guide

Overview

The frontend uses environment-specific configuration to connect to different backends in development vs production.

How It Works

Development (Local)

  • File: .env (not committed to git)
  • Backend: http://localhost:8080
  • Vite Proxy: Automatically proxies /api/* requests to backend
  • Hot Reload: ✅ Enabled

Production (Deployed)

  • File: .env.production (committed to git)
  • Backend: Relative /api (proxied to https://api.retailgrid.io)
  • Serving: Cloud Run frontend (nginx) serves static assets
  • Proxy: Nginx forwards /api/* to the backend

Environment Files

.env.local (Local Development - NOT in git)

VITE_API_URL=
Purpose: Local development with local backend via Vite proxy Created by: Each developer (default behavior if not created) Usage: For local backend, either don’t create this file or leave VITE_API_URL empty

.env.cloud (Cloud Backend Template - IN git)

VITE_API_URL=https://api.retailgrid.io
Purpose: Template for connecting to cloud backend from local development Usage: cp .env.cloud .env.local to connect to production backend When to use: Testing frontend changes against production backend without running backend locally

.env.example (Template - IN git)

VITE_API_URL=
Purpose: Template showing available environment variables Usage: Reference for creating .env.local with custom configuration

.env.production (Production - IN git)

VITE_API_URL=
Purpose: Production environment configuration Result: Production builds use same-origin /api (proxied to https://api.retailgrid.io)

How Vite Handles Environment Variables

Variable Naming

  • Must start with VITE_ to be exposed to frontend code
  • Example: VITE_API_URL, VITE_APP_NAME
  • Non-VITE variables are only available during build, not in browser

Upload mode (direct-to-GCS resumable)

The upload page supports direct-to-GCS resumable uploads (recommended for Cloud Run) and can be toggled per environment:
  • Production builds (import.meta.env.PROD === true): always use direct-to-GCS resumable uploads
  • Local dev: default to legacy backend multipart upload (simpler), unless you opt-in:
VITE_FORCE_RESUMABLE_UPLOAD=true
When VITE_FORCE_RESUMABLE_UPLOAD=true, local dev will use the same resumable flow as production, but you must also:
  • Run backend with real GCS enabled (USE_LOCAL_STORAGE=false) and valid credentials
  • Ensure the uploads bucket has CORS allowing http://localhost:3000 for PUT + Content-Range headers

Access in Code

// ✅ Correct
const apiUrl = import.meta.env.VITE_API_URL;

// ❌ Wrong (Node.js style - doesn't work in Vite)
const apiUrl = process.env.VITE_API_URL;

Build-time vs Runtime

  • Environment variables are baked into the build at compile time
  • Changing .env after build has no effect
  • Must rebuild: npm run build

Current Setup (Best Practices)

✅ What We’re Doing Right

  1. Vite Proxy for Development
    • Proxies /api, /upload, /input to backend
    • No CORS issues during development
    • Works seamlessly with npm run dev
  2. Relative URLs in Production
    • API client uses baseURL: '/api'
    • No hardcoded backend URLs
    • Works when frontend + backend are on same domain
  3. Environment-Specific Configuration
    • .env for local development (git-ignored)
    • .env.production for production (committed)
    • .env.example as template (committed)
  4. Fallback to Sensible Defaults
    target: process.env.VITE_API_URL || 'http://localhost:8080'
    

Configuration Flow

Development Mode (npm run dev)

┌─────────────────────────────────────────────┐
│  Browser                                     │
│  http://localhost:3000                      │
└────────────────┬────────────────────────────┘

                 │ Request: /api/sessions

┌─────────────────────────────────────────────┐
│  Vite Dev Server (Port 3000)                │
│  - Serves React app with HMR                │
│  - Reads .env file                          │
│  - Proxies /api/* to backend                │
└────────────────┬────────────────────────────┘

                 │ Proxied to: http://localhost:8080/api/sessions

┌─────────────────────────────────────────────┐
│  Flask Backend (Port 8080)                  │
│  - Handles API requests                     │
│  - Returns JSON response                    │
└─────────────────────────────────────────────┘

Production Mode (npm run build)

┌─────────────────────────────────────────────┐
│  Browser                                     │
│  https://yourdomain.com/app                 │
└────────────────┬────────────────────────────┘

                 │ Request: /api/sessions (relative)

┌─────────────────────────────────────────────┐
│  Flask Backend (Same Server)                │
│  - Serves built React app at /app           │
│  - Handles API at /api                      │
│  - Single server, no CORS                   │
└─────────────────────────────────────────────┘

Common Scenarios

Scenario 1: Local Development with Local Backend (Default)

Use case: Running both frontend and backend locally Solution: Just run the dev server (no .env.local needed)
npm run dev
Vite proxy will forward requests to http://localhost:8080

Scenario 2: Local Development with Cloud Backend

Use case: Testing frontend changes against production backend Solution: Copy cloud environment template
cp .env.cloud .env.local
npm run dev
Frontend will connect to https://api.retailgrid.io When to switch back to local backend:
rm .env.local
npm run dev

Scenario 3: Backend on Different Port Locally

Problem: Your backend runs on port 5001 instead of 8080 Solution: Create/update .env.local
echo "VITE_API_URL=http://localhost:5001" > .env.local
npm run dev

Scenario 4: Backend on Different Domain (Staging)

Problem: Testing against staging backend at https://staging-api.example.com Solution: Create .env.local with staging URL
echo "VITE_API_URL=https://staging-api.example.com" > .env.local
npm run dev

Scenario 5: Production Deployment

Problem: Deploying to production Solution: Just build normally
npm run build
The build will use .env.production which points to the cloud backend.

Scenario 6: Docker Development

Problem: Backend is in Docker at http://backend:8080 Solution: Update .env.local
echo "VITE_API_URL=http://localhost:8080" > .env.local
Make sure Docker exposes port 8080 to host.

Debugging

Check Current Environment Variables

Add this temporarily to any component:
console.log('API URL:', import.meta.env.VITE_API_URL);
console.log('Mode:', import.meta.env.MODE);
console.log('All env:', import.meta.env);

Check Proxy Configuration

In browser DevTools Network tab:
  • Request URL should show http://localhost:3000/api/... (dev server)
  • Proxied to: http://localhost:8080/api/... (backend)

Check Build Output

After build, check dist/assets/index-*.js:
grep -o "VITE_API_URL" frontend/dist/assets/index-*.js
Should be empty in production build (using relative URLs).

Best Practices Summary

  1. Never commit .env - Add to .gitignore
  2. Always commit .env.example - For other developers
  3. Use relative URLs in production - No hardcoded backend URLs
  4. Use Vite proxy in development - Avoids CORS issues
  5. Prefix with VITE_ - Only way to access in frontend code
  6. Restart dev server - After changing .env
  7. Rebuild for production - After changing .env.production
  8. Use sensible defaults - Fallback if env var not set
  9. Document in .env.example - Help other developers

Quick Reference

EnvironmentFileBackend URLCommand
Local Dev (Local Backend).env.local (empty or not created)http://localhost:8080 (via proxy)npm run dev
Local Dev (Cloud Backend).env.local (copied from .env.cloud)https://api.retailgrid.iocp .env.cloud .env.local && npm run dev
Production.env.production/api (proxied to https://api.retailgrid.io)npm run build

Setup for New Developers

Option 1: Local Backend (Default)

# 1. Clone repo
git clone <repo>

# 2. Install dependencies
cd frontend
npm install

# 3. Start development (no .env.local needed)
npm run dev
Done! Frontend connects to backend at http://localhost:8080 via Vite proxy

Option 2: Cloud Backend

# 1. Clone repo
git clone <repo>

# 2. Install dependencies
cd frontend
npm install

# 3. Copy cloud backend template
cp .env.cloud .env.local

# 4. Start development
npm run dev
Done! Frontend connects to cloud backend at https://api.retailgrid.io