This guide explains how to run the application in development mode with hot reload enabled and proper SPA routing.
In production mode (docker-compose.yml), the frontend is built once and served as static files. Changes to frontend code require rebuilding the container.
When using React Router with BrowserRouter, refreshing the page on routes like /scenarios or /analytics should work. The backend has been configured with a catch-all route to serve index.html for all non-API routes.
Windows:
.\start-dev.batLinux/Mac:
./start-dev.shOr manually:
docker-compose -f docker-compose.development.yml up --build-
Frontend (Port 3000)
- Runs Vite dev server with Hot Module Replacement (HMR)
- File changes automatically reflect in browser
- Source code is mounted from
./webapp/frontend - Fast refresh for React components
-
Backend (Port 5000)
- Flask runs with
--debugflag - Auto-reloads on Python file changes
- Source code is mounted from
./webapp/backend
- Flask runs with
-
Volumes
- Frontend and backend source code are mounted
node_modulesuses an anonymous volume to avoid conflictsdatadirectory is shared for case study access
- Frontend: Separate container running Vite dev server
- Backend: Separate container running Flask in debug mode
- Hot Reload: ✅ Enabled for both frontend and backend
- Build Time: Faster (no build step)
- Use Case: Active development
- Frontend: Built and served as static files from single container
- Backend: Runs Flask in production mode from same container
- Hot Reload: ❌ Disabled
- Build Time: Slower (React build required)
- Use Case: Deployment, testing final build
- Frontend: http://localhost:3000 (Vite dev server)
- Backend API: http://localhost:5000 (Flask)
- GloWPa: http://localhost:8080
- Frontend: http://localhost:3000 (Flask serving static React build)
- Backend API: http://localhost:5000 (Flask)
- GloWPa: http://localhost:8080
# All services
docker-compose -f docker-compose.development.yml logs -f
# Specific service
docker-compose -f docker-compose.development.yml logs -f frontend
docker-compose -f docker-compose.development.yml logs -f backenddocker-compose -f docker-compose.development.yml down# If you change package.json or requirements.txt
docker-compose -f docker-compose.development.yml up --builddocker-compose -f docker-compose.development.yml down -v
docker-compose -f docker-compose.development.yml up --buildThe configuration uses CHOKIDAR_USEPOLLING=true and Vite's usePolling: true to enable file watching in Docker on Windows. If it still doesn't work:
-
Check that volumes are mounted correctly:
docker-compose -f docker-compose.development.yml ps
-
Verify file changes are detected:
docker-compose -f docker-compose.development.yml logs -f frontend
-
Try increasing the polling interval in
vite.config.js:watch: { usePolling: true, interval: 2000, // Increase from 1000 to 2000ms }
If you still get 404 errors when refreshing pages:
- Development Mode: Vite dev server handles routing automatically
- Production Mode: Flask's catch-all route serves
index.htmlfor all non-API routes
To verify the catch-all route is working, check Flask logs:
docker logs webapp-containerYou should see debug messages like:
[DEBUG] Catch-all route hit with path: 'scenarios'
[DEBUG] File doesn't exist, serving index.html for SPA routing
If ports 3000, 5000, or 8080 are already in use:
- Stop conflicting services
- Or modify ports in
docker-compose.development.yml:ports: - "3001:3000" # Use 3001 instead of 3000
webapp/
├── backend/
│ └── app.py # Flask backend (mounted in dev mode)
├── frontend/
│ ├── src/ # React source (mounted in dev mode)
│ ├── package.json
│ └── vite.config.js # Vite configuration with polling
├── Dockerfile # Production build
├── Dockerfile.dev.backend # Backend dev container
├── Dockerfile.dev.frontend # Frontend dev container
└── requirements.txt
- Use Development Mode for Coding: Always use
docker-compose.development.ymlwhen actively developing - Use Production Mode for Testing: Test with
docker-compose.ymlbefore deploying - Browser DevTools: React DevTools and Redux DevTools work in development mode
- Console Logs: Check browser console and container logs for debugging
- Code changes in
webapp/frontend/srcwill automatically reload in browser - Python changes in
webapp/backendwill automatically restart Flask - Case study data is preserved between restarts (mounted volume)