diff --git a/Dockerfile b/Dockerfile
index 55964ba..1e4ef54 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,16 +4,12 @@ WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm install
COPY . .
-ARG VITE_API_BASE=/api
-ARG VITE_WIZARD_PORT=18080
-ENV VITE_API_BASE=$VITE_API_BASE
-ENV VITE_WIZARD_PORT=$VITE_WIZARD_PORT
+# API and wizard are proxied via nginx — no VITE_ env vars needed
RUN npm run build
-# Production stage — lightweight static server, no nginx
-FROM node:20-alpine
-RUN npm install -g serve@14
-WORKDIR /app
-COPY --from=build /app/dist ./dist
+# Production stage — nginx with reverse proxy
+FROM nginx:alpine
+COPY --from=build /app/dist /usr/share/nginx/html
+COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 3000
-CMD ["serve", "-s", "dist", "-l", "3000"]
+CMD ["nginx", "-g", "daemon off;"]
diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000..6822e7f
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,29 @@
+server {
+ listen 3000;
+ root /usr/share/nginx/html;
+ index index.html;
+
+ # Backend API proxy
+ location /api/ {
+ proxy_pass http://backend:8000/;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_connect_timeout 5s;
+ proxy_read_timeout 30s;
+ }
+
+ # Wizard API proxy (setup phase only)
+ location /wizard/ {
+ proxy_pass http://wizard:8080/;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_connect_timeout 5s;
+ proxy_read_timeout 10s;
+ }
+
+ # SPA fallback — only for non-API, non-asset routes
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+}
diff --git a/src/App.tsx b/src/App.tsx
index f3674ed..f528814 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -15,8 +15,6 @@ import MilestoneDetailPage from '@/pages/MilestoneDetailPage'
import NotificationsPage from '@/pages/NotificationsPage'
import api from '@/services/api'
-const WIZARD_PORT = Number(import.meta.env.VITE_WIZARD_PORT) || 18080
-
type AppState = 'checking' | 'setup' | 'ready'
export default function App() {
@@ -41,7 +39,7 @@ export default function App() {
// Backend not ready — show setup wizard
if (appState === 'setup') {
- return