O .gitignore desse projeto tem uma peça a mais
Na trilha em Blade, o .gitignore padrão do Laravel já resolvia praticamente tudo. Aqui, como o projeto ganhou um pipeline de front-end inteiro (Vue + Tailwind + Vite), duas entradas passam a importar de verdade:
.gitignore (trecho relevante desse projeto)
/vendor
/node_modules
.env
/public/hot
/public/build
/public/storage
/storage/*.log
/node_modules segue a mesma lógica do /vendor — reconstruível a partir de package.json/package-lock.json, então não faz sentido versionar centenas de megabytes de dependências. /public/hot é o arquivo temporário que só existe enquanto npm run dev está rodando (Aula D1) — nunca deveria ir pro Git de propósito nenhum. /public/build é o resultado do npm run build — e essa é a única decisão que realmente vale a pena parar pra pensar.
Versionar public/build ou gerar ele no deploy?Existem dois caminhos válidos, e vale escolher conscientemente:
• Gitignorar (o padrão do Laravel, e o que recomendamos) — o build é gerado no momento do deploy, seja rodando npm run build direto no servidor, seja numa esteira de CI/CD que builda e envia só o resultado. Mantém o repositório limpo e garante que o build sempre reflete o código-fonte atual.
• Versionar public/build — útil só em cenários bem simples, tipo uma hospedagem compartilhada sem Node.js nem CI/CD, onde você builda na sua máquina e sobe o projeto inteiro (build incluso) via FTP/git push direto. Funciona, mas exige lembrar de sempre rodar o build antes de cada commit — fácil de esquecer e publicar uma versão desatualizada do JS.
package-lock.json, ao contrário de node_modules/, deve ser versionado — ele trava as versões exatas de cada dependência JavaScript, exatamente como o composer.lock faz do lado do PHP.
O mapa de pastas — tudo que você construiu, organizado
Depois de F1 até O4, o projeto acumulou bastante estrutura nova dentro de resources/. Vale ver o quadro completo de uma vez:
resources/ (visão geral)
resources/
css/
app.css → só o "@import tailwindcss" (Aula 27)
js/
app.js → ponto de entrada: registra Inertia, Vue e o Service Worker (F2, O1)
db.js → configuração do Dexie/IndexedDB (O2)
sync.js → funções de sincronização offline (O2, O3, O4)
Pages/ → uma pasta por recurso, um arquivo por tela — nome bate com Inertia::render()
Auth/
Login.vue (Aula 9)
Usuarios/
Index.vue (Aula 3, 6, 7, 14, 15, 27)
Criar.vue (Aula 5, 24)
Components/ → pedaços reutilizáveis, importados em várias Pages
Badge.vue (F4)
SinoNotificacoes.vue (Aula 22, 26)
StatusSincronizacao.vue (O4)
Layouts/ → moldes compartilhados
AppLayout.vue (F5)
composables/ → lógica reativa reutilizável (funções use*)
useSincronizacao.js (O4)
views/
app.blade.php → a ÚNICA view Blade do projeto inteiro (F2)
Repare que resources/views/ praticamente esvaziou — sobrou só o app.blade.php, a "casca" que carrega o Vue (Aula F2). Todo o resto que antes seria uma view Blade virou um arquivo .vue dentro de Pages/. Isso é o resumo visual da própria proposta dessa trilha: o Laravel continua dono das pastas app/, routes/, database/ exatamente como na trilha em Blade — só a camada de tela migrou de resources/views/ pra resources/js/Pages/.
O checklist completo de deploy, do zero
Juntando o que a trilha em Blade já ensinou (composer, .env, migrations, cache) com o que é específico desse stack (npm, build):
Precisa instalar o Node.js no servidor? Use o NVMDiferente do PHP, que a maioria dos servidores já vem com alguma versão instalada, o Node.js muitas vezes precisa ser instalado do zero — e a versão que vem por padrão em pacotes do sistema (
apt install nodejs, por exemplo) costuma ser antiga demais pras dependências desse projeto (Vite, Tailwind via Vite,
vite-plugin-pwa). O jeito mais confiável de instalar — e trocar de versão depois, se precisar — é o
NVM (Node Version Manager):
terminal (no servidor, ou na máquina onde for rodar o build)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install 22
curl ... | bash baixa e roda o instalador do NVM, que se registra no seu shell.
source ~/.bashrc recarrega o arquivo de configuração do terminal na sessão atual, sem precisar desconectar e reconectar — só depois disso o comando
nvm passa a existir.
nvm install 22 instala o Node.js 22 (recente o suficiente pras dependências desse projeto) e já deixa ela ativa na sessão. Feito isso, o
npm ci e o
npm run build do checklist abaixo já encontram a versão certa.
Erro de "dubious ownership" no git?Se um git clone/git pull no servidor recusar rodar citando dubious ownership, é uma proteção do Git contra pastas cujo dono não é o mesmo usuário rodando o comando — comum em painéis (aaPanel, cPanel, Plesk). Resolve com git config --global --add safe.directory /caminho/do/projeto, uma vez por servidor. A trilha em Blade (Aula D1) detalha esse cenário e também o que fazer quando o git pull reclama de mudanças locais no servidor.
terminal — primeiro deploy, na ordem
git clone https://github.com/sua-conta/painel-usuarios.git
cd painel-usuarios
composer install --optimize-autoloader --no-dev
npm ci
cp .env.example .env
php artisan key:generate
# editar .env: banco de dados, EVOLUTION_API_*, etc.
npm run build
php artisan storage:link
chmod -R 775 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
php artisan migrate --force --seed
php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
npm ci (diferente de npm install) instala exatamente as versões travadas no package-lock.json — mais previsível que npm install pra um ambiente de produção, que não deveria decidir versões novas sozinho. npm install continua tendo seu lugar: use ele (em vez do npm ci) quando o package.json mudou e o package-lock.json precisa ser atualizado também — pro fluxo normal de deploy, com o lock file já commitado, npm ci é a escolha mais segura. Repare a ordem: o .env precisa existir antes do npm run build, porque variáveis com prefixo VITE_ (como as do Reverb, na Aula 26) são lidas do .env no momento do build, não em tempo de execução — se você buildar antes de configurar o .env, essas variáveis ficam vazias no JavaScript compilado, e é preciso buildar de novo depois de corrigir. optimize:clear, logo antes dos três comandos de cache, limpa qualquer cache antigo que possa ter sobrado de um deploy anterior — evita "cache em cima de cache" com valor desatualizado.
Se o servidor for gerenciado por um painel tipo aaPanel/cPanel/Plesk, os comandos php artisan ... desse checklist também podem precisar do caminho completo até o binário do PHP (algo como /www/server/php/83/bin/php artisan migrate) — a trilha em Blade (Aula D1) explica o motivo com mais detalhe.
Um detalhe de sintaxe que vale notar em scripts de deploy por aí: às vezes você vê comandos encadeados com ;, tipo npm install ; npm run build. Repare que ; roda o próximo comando não importa o que aconteceu com o anterior — diferente de && (o que usamos nos exemplos dessa aula), que só segue pro próximo comando se o anterior tiver dado certo. Pra deploy, && costuma ser mais seguro: se o npm install falhar (dependência quebrada, rede caiu no meio), você não quer que o npm run build rode em cima de um node_modules incompleto, só pra falhar de um jeito mais confuso mais adiante.
Pra uma atualização normal, num servidor que já está no ar, o checklist encurta bastante — mesma lógica da trilha em Blade, só acrescentando o build:
terminal — atualização
git pull origin main
composer install --optimize-autoloader --no-dev
npm ci
npm run build
php artisan migrate --force
php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
Mão na massa
Confira o .gitignore do seu projeto e confirme que as seis linhas do exemplo estão lá (o Laravel já inclui a maioria por padrão desde a instalação — só vale checar). Simule um primeiro deploy: faça backup do seu .env, apague vendor/, node_modules/ e public/build/, e siga o checklist completo do zero. Confirme, no final, que o sistema volta a funcionar — incluindo o suporte offline (Aula O1), já que ele depende do Service Worker gerado pelo build.