diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..52a58cb --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +node_modules +dist +dist-ssr +.git +.gitignore +README.md +.vscode +.idea +.DS_Store +*.local +.env +.env.* +.vite diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..53c1ed2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +# ============================ +# Stage 1 — Build (Vite + TypeScript) +# ============================ +FROM node:20-alpine AS builder + +WORKDIR /app + +COPY package.json package-lock.json* ./ +RUN npm ci + +COPY . . +RUN npm run build + +# ============================ +# Stage 2 — Serve (nginx) +# ============================ +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/deploy.sh b/deploy.sh new file mode 100755 index 0000000..c0f2419 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# ============================================ +# Rivus Lab Landing Page — Deploy automatizado +# ============================================ +# Build, push imagem, atualiza tag no compose, commit, push. +# Webhook do Gitea dispara redeploy no Portainer. +# ============================================ + +set -e + +REGISTRY="registry.rivuslab.com" +NAMESPACE="cauanneves" +IMAGE="rivuslab-site" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +echo -e "${BLUE}==========================================${NC}" +echo -e "${BLUE} Rivus Lab Site — Deploy${NC}" +echo -e "${BLUE}==========================================${NC}" + +if [ -n "$(git status --porcelain)" ]; then + echo -e "${RED}❌ Working directory tem mudanças não comitadas:${NC}" + git status --short + echo "" + echo "Commit ou stash antes de deployar." + exit 1 +fi + +GIT_SHA=$(git rev-parse --short HEAD) +TAG="${GIT_SHA}" +echo -e "${YELLOW}Tag de deploy: ${TAG}${NC}" +echo "" + +echo -e "${GREEN}▶ Building (${TAG})${NC}" +docker build \ + -t "${REGISTRY}/${NAMESPACE}/${IMAGE}:${TAG}" \ + -t "${REGISTRY}/${NAMESPACE}/${IMAGE}:latest" \ + . + +echo -e "${GREEN}▶ Pushing${NC}" +docker push "${REGISTRY}/${NAMESPACE}/${IMAGE}:${TAG}" +docker push "${REGISTRY}/${NAMESPACE}/${IMAGE}:latest" +echo "" + +echo -e "${GREEN}▶ Atualizando docker-compose.prod.yml${NC}" +sed -i "s|${REGISTRY}/${NAMESPACE}/${IMAGE}:[^\"[:space:]]*|${REGISTRY}/${NAMESPACE}/${IMAGE}:${TAG}|g" docker-compose.prod.yml + +if [ -z "$(git status --porcelain docker-compose.prod.yml)" ]; then + echo -e "${YELLOW}⚠ docker-compose.prod.yml não mudou. Nenhum push.${NC}" + exit 0 +fi + +git diff docker-compose.prod.yml +echo "" + +echo -e "${GREEN}▶ Commit + push${NC}" +git add docker-compose.prod.yml +git commit -m "Deploy ${TAG}" +git push + +echo "" +echo -e "${GREEN}✅ Deploy disparado!${NC}" +echo "Acompanhe em: https://portainer.rivuslab.com/#!/2/docker/stacks/rivuslab-site" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..e42667c --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,6 @@ +services: + site: + image: registry.rivuslab.com/cauanneves/rivuslab-site:1b46f99 + restart: unless-stopped + ports: + - "127.0.0.1:8095:80" diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..9f84ee7 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,30 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + # SPA routing — 404s caem no index.html (i18next/react-router lidam) + location / { + try_files $uri $uri/ /index.html; + } + + # Cache agressivo para assets versionados (Vite gera hash no nome) + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|webp|avif)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # index.html nunca cacheia (pega versão nova após deploy) + location = /index.html { + add_header Cache-Control "no-store, no-cache, must-revalidate"; + } + + # Healthcheck + location = /healthz { + access_log off; + return 200 "ok\n"; + add_header Content-Type text/plain; + } +} diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index eca49b6..65102e2 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -68,7 +68,7 @@ export function Footer({ isDark }: { isDark: boolean }) { contato@rivuslab.com -
  • +55 (00) 00000-0000
  • +
  • +55 (11) 99972-6609
  • diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 09f96d4..45e9063 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -119,7 +119,7 @@ "emailLabel": "Email", "email": "contact@rivuslab.com", "whatsappLabel": "WhatsApp", - "whatsapp": "+55 (00) 00000-0000", + "whatsapp": "+55 (11) 99972-6609", "ctaPrimary": "Send message" }, "footer": { diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json index 496fa0b..96c6c7b 100644 --- a/src/i18n/locales/es.json +++ b/src/i18n/locales/es.json @@ -119,7 +119,7 @@ "emailLabel": "Correo", "email": "contacto@rivuslab.com", "whatsappLabel": "WhatsApp", - "whatsapp": "+55 (00) 00000-0000", + "whatsapp": "+55 (11) 99972-6609", "ctaPrimary": "Enviar mensaje" }, "footer": { diff --git a/src/i18n/locales/pt.json b/src/i18n/locales/pt.json index d2d5e2f..daad091 100644 --- a/src/i18n/locales/pt.json +++ b/src/i18n/locales/pt.json @@ -119,7 +119,7 @@ "emailLabel": "E-mail", "email": "contato@rivuslab.com", "whatsappLabel": "WhatsApp", - "whatsapp": "+55 (00) 00000-0000", + "whatsapp": "+55 (11) 99972-6609", "ctaPrimary": "Enviar mensagem" }, "footer": {