Files
wh40k-points-comparator/Dockerfile
root 38bffa491c Initial commit: WH40K Points Comparator
- React + MUI DataGrid app with faction filter, search, change filter
- Biggest movers cards (drops/rises) scoped to current filter view
- Historical points graph modal (5 MFM versions: 1.14 → current)
- URL state sync (faction, dir, q params — shareable URLs)
- Grimdark favicon + OG embed image (Google Imagen)
- Multi-stage Dockerfile (node build → nginx serve)
- docker-compose.yml with Traefik + Cloudflare TLS
- Data pipeline: build_deduped_data.py merges PDF + live scrape
- Ynnari merged into Aeldari (shared codex)
- Mobile responsive: flex columns, no fixed pixel widths
- Color semantics: green=cheaper, red=costlier (consistent everywhere)
- 1,449 units across 31 factions
2026-06-18 02:42:29 +00:00

43 lines
1.1 KiB
Docker

# ── Build stage: React app ──
FROM node:20-alpine AS build
WORKDIR /app
COPY react-app/package.json react-app/package-lock.json* ./
RUN npm ci --silent || npm install --silent
COPY react-app/ ./
RUN npm run build
# ── Runtime stage: nginx ──
FROM nginx:alpine
# Copy built assets from build stage
COPY --from=build /app/dist/ /usr/share/nginx/html/
# SPA-friendly nginx config with CORS headers for module scripts
RUN printf 'server {\n\
listen 80;\n\
server_name _;\n\
root /usr/share/nginx/html;\n\
index index.html;\n\
\n\
gzip on;\n\
gzip_types text/plain text/css application/javascript application/json image/svg+xml;\n\
gzip_min_length 256;\n\
\n\
# CORS + cache for static assets\n\
location ~* \.(js|css|json|png|jpg|webp|svg|ico|woff2?)$ {\n\
expires 1h;\n\
add_header Cache-Control "public, max-age=3600";\n\
add_header Access-Control-Allow-Origin "*" always;\n\
}\n\
\n\
location / {\n\
add_header Access-Control-Allow-Origin "*" always;\n\
try_files $uri $uri/ /index.html;\n\
}\n\
}\n' > /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]