📄 SKILL.md

← Vault

name: cloudflare-workers-vps-deploy

description: Deploy TanStack Start / Lovable Cloudflare Worker builds to Node.js VPS

category: devops


Cloudflare Workers (TanStack Start/Lovable) → Deploy em VPS Node.js

Contexto

Apps criados no Lovable/exportados como Cloudflare Workers não funcionam com node index.js ou PM2 diretamente. O build gera um worker-entry-XXX.js (Cloudflare Worker), não um server.js padrão.

Como identificar

`bash

Build gera dist/server/assets/worker-entry-*.js (Worker bundler, não Node)

ls dist/server/assets/worker-entry-*.js # arquivo grande (~700KB+)

cat wrangler.jsonc # mostra Cloudflare Worker config

`

Soluções

Opção 1: Rebuild para Node.js Adapter (se source disponível)

`bash

Mudar vite.config para usar Node adapter em vez de Cloudflare

Exemplo com @tanstack/start:

npm install @tanstack/start-server

`

Opção 2: Servir como SPA estática (se app usa Supabase/etc Cloud)

`bash

Capturar index.html do dev server

bun run dev &

sleep 5

curl -s http://localhost:5173 > dist/client/index.html

pkill -f "vite dev"

Criar servidor estático simples em Node.js

cat > serve.mjs << 'EOF'

import { createServer } from 'node:http';

import { readFileSync, existsSync } from 'node:fs';

import { join, extname } from 'node:path';

const DIST = '/caminho/app/dist/client';

const PORT = 3010;

createServer((req, res) => {

let url = req.url.split('?')[0];

let filePath = join(DIST, url === '/' ? 'index.html' : url);

if (!existsSync(filePath)) filePath = join(DIST, 'index.html');

const ext = extname(filePath);

const ct = {'.js':'application/javascript','.css':'text/css','.html':'text/html'}[ext] || 'application/octet-stream';

try {

const content = readFileSync(filePath);

res.writeHead(200, {'Content-Type': ct});

res.end(content);

} catch { res.writeHead(404); res.end('Not found'); }

}).listen(PORT, () => console.log(Running on ${PORT}));

EOF

node serve.mjs

`

Opção 3: wrangler dev (para testar local)

`bash

npx wrangler dev --port 3010

`

Sinais de alerta na análise do zip

Nota importante

Se o app conecta em Supabase/banco externo Cloud (não local), a Opção 2 (SPA estática) funciona — o backend é todo remoto.