📄 SKILL.md

← Vault

name: lovable-vps-disaster-recovery

description: Restaurar projeto Lovable (React + Vite) em VPS quando o código fonte é perdido por rsync ou wipe


Lovable + VPS Disaster Recovery

Contexto

Projeto Lovable (vite_react_shadcn_ts) rodando em VPS via Docker/nginx. O código fonte pode ser perdido por rsync ou wipe, deixando só o dist/ compilado.

Workflow de Restauração Completa

1. Diagnóstico

`bash

Ver o que existe

ls /var/www/comercialrs/

ls /tmp/comercialrs/comercialrs-main/src/ # backup parcial pode existir

Se dist/ está incompleto (< 10KB index.html), precisa rebuild

wc -c /var/www/comercialrs/dist/index.html

`

2. Encontrar backup

`bash

find / -path /proc -prune -o -path /sys -prune -o -name "OnboardingTutorial.tsx" -print 2>/dev/null

Backup comum: /tmp/comercialrs/comercialrs-main/

`

3. Restaurar fonte + configs

`bash

Copiar src do backup

cp -r /tmp/comercialrs/comercialrs-main/src /var/www/comercialrs/src

Copiar configs essenciais

cp /tmp/comercialrs/comercialrs-main/{package.json,package-lock.json,vite.config.ts,tailwind.config.ts,tsconfig.json,components.json,postcss.config.js,index.html,eslint.config.js} /var/www/comercialrs/

Copiar .env (CRÍTICO - sem ele o build não Embeds variáveis)

cp /tmp/comercialrs/comercialrs-main/.env /var/www/comercialrs/.env

Copiar public se existir

cp -r /tmp/comercialrs/comercialrs-main/public /var/www/comercialrs/public 2>/dev/null && echo "Public copied"

`

4. Instalar dependências e rebuildar

`bash

cd /var/www/comercialrs

npm install

npm run build

Verificar novo hash dos assets em dist/index.html

`

5. Verificar se nginx serve do lugar certo

`bash

Geralmente nginx serve de /var/www/comercialrs/dist

Mas pode ser /var/www/rochasales/dist (site principal)

grep -A5 "comercialrs" /etc/nginx/sites-enabled/

cat /etc/nginx/sites-enabled/comercialrs.rochasalesseguros.com.br | grep "root"

`

6. Testar

`bash

curl -s -o /dev/null -w "%{http_code}" https://comercialrs.rochasalesseguros.com.br/

Deve retornar 200

`

Vite Build Produces Empty dist/ (index.html missing)

Problem: Running npm run build or vite build directly on VPS produces a dist/ folder with JS assets but NO index.html. The build appears to succeed (no error) but dist/index.html is missing.

Root Cause: The Lovable/TanStack Start project uses @lovable.dev/vite-tanstack-config (via lovable-tagger in vite.config.ts) which wraps Vite's HTML entry handling. When running vite build outside the Lovable CI pipeline, the custom plugin fails to inject/process the HTML entry, resulting in no dist/index.html.

Fix: Explicitly set both main and index entry points in rollupOptions.input:

`typescript

// vite.config.ts

import { defineConfig } from "vite";

import react from "@vitejs/plugin-react-swc";

import path from "path";

export default defineConfig({

plugins: [react()],

resolve: {

alias: { "@": path.resolve(__dirname, "./src") },

},

build: {

rollupOptions: {

input: {

main: "./src/main.tsx",

index: "./index.html",

}

}

},

});

`

Then build with:

`bash

cd /var/www/comercialrs

rm -rf dist

node ./node_modules/vite/bin/vite.js build

`

Verification: After build, check dist/index.html exists and contains

. If the file is missing, the rollupOptions.input fix above is needed.

Why this works: Lovable's CI pipeline handles HTML injection automatically, but standalone Vite needs explicit entry points. Adding index: "./index.html" alongside main: "./src/main.tsx" tells Rollup to process both.

Armadilhas

Browser Cache — Debug JS After Rebuild (Critical!)

Problem: After rebuilding (npm run build + systemctl restart), the browser serves old cached JS. New code with debug statements exists on the server but isn't loaded.

Fix — Hard Refresh sequence:

1. systemctl restart documentos (VPS)

2. User does Hard Refresh in browser:

- Chrome: F12 → right-click reload button → "Empty cache and hard reload"

- Firefox: Ctrl+Shift+F5

- Or append ?cb=1 to URL to bust cache

Verify DevTools is not caching: Network tab → check "Disable cache" while DevTools is open.

Why this matters: Vite content-hashes should prevent old JS, but browser disk cache overrides this. Always start JS debugging with Hard Refresh before assuming code didn't work.

Gmail OAuth — "Conectar Gmail" Did Nothing (2026-05-25)

Symptom: User clicks "Conectar Gmail" → nothing happens in console.

Actual behavior: Button DOES work. Popup opens to Google signin URL. User closes popup without completing auth → appears as "nothing happened."

Debug: Have user paste full URL from address bar after clicking. If it shows accounts.google.com/v3/signin/... with correct client_id and redirect_uri, the button is working — it's a UX issue (user expected to stay logged in or didn't notice the popup).

VPS rebuild with new debug statements:

`bash

cd /var/www/documentos/deploy-vps-nodejs/app

source ~/.nvm/nvm.sh && nvm use 20 && npm run build

systemctl restart documentos

Verify built JS has debug logs

grep 'DEBUG connectGmail' /var/www/documentos/deploy-vps-nodejs/app/dist/client/assets/admin-*.js

`

Key files:

  • - src/routes/admin.tsxconnectGmail(), getGmailAuthUrl()
  • - src/lib/google-token.tsgetGmailAuthUrl, getGmailTokensFromCode
  • - src/routes/api/public/gmail-oauth-callback.ts — OAuth callback
  • Armadilhas

  • - SEMPRE fazer backup do .env antes de qualquer rsync
  • - Nunca confiar que o backup está completo — verificar src/components, src/pages, src/lib
  • - Testar rebuild ANTES de mexer no que está funcionando
  • - Se dist/ foi wipado, nginx vai servir 404 — rebuild precisa acontecer antes de qualquer rsync que possa falhar
  • - Cache do browser → pode servir JS antigo depois do rebuild. Usar Hard Refresh ou ?cb=1
  • - vite build sem entry points → produz JS assets mas SEM index.html. Sempre verificar dist/index.html depois do build.

Lições Aprendidas

1. SEMPRE fazer backup do .env antes de qualquer rsync

2. Nunca confiar que o backup está completo — verificar src/components, src/pages, src/lib

3. Testar rebuild ANTES de mexer no que está funcionando

4. Se dist/ foi wipado, nginx vai servir 404 — rebuild precisa acontecer antes de qualquer rsync que possa falhar

5. Gmail OAuth "did nothing" = popup was actually opened — user closed it without completing auth. Check URL bar after clicking to confirm.

6. Hard Refresh é obrigatório quando se faz debug de JS em produção após rebuild.