diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..01d7625 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +dist +.env +.env.local +.git diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a691cfe --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +# In development, Vite proxies /api to this URL. +# In production, Nginx handles the proxy — leave blank or omit. +VITE_API_URL=http://localhost:3000 diff --git a/.gitignore b/.gitignore index a547bf3..d63abad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.env +.env.local + # Logs logs *.log diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..07f9adb --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,26 @@ +when: + branch: main + event: [push, manual] + +steps: + - name: build + image: docker:cli + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - docker build -t yugioh-frontend:latest . + + - name: deploy + image: docker:cli + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - docker stop yugioh-frontend || true + - docker rm yugioh-frontend || true + - docker network create yugioh || true + - docker run -d + --name yugioh-frontend + --restart unless-stopped + --network yugioh + -p 8041:80 + yugioh-frontend:latest diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..42b7b20 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:20-alpine AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM nginx:alpine +COPY --from=builder /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..9e44107 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,19 @@ +server { + listen 80; + root /usr/share/nginx/html; + index index.html; + + # Proxy API calls to the yugioh-api container (strips /api prefix) + location /api/ { + proxy_pass http://yugioh-api:3000/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + # SPA fallback + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/vite.config.js b/vite.config.js index 8b0f57b..e01617c 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,7 +1,18 @@ -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' -// https://vite.dev/config/ -export default defineConfig({ - plugins: [react()], +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd(), '') + return { + plugins: [react()], + server: { + proxy: { + '/api': { + target: env.VITE_API_URL || 'http://localhost:3000', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, '') + } + } + } + } })