Pular para o conteúdo
Gustavo Tutorial

Fluxo de trabalho

Esta trilha não é sobre linguagem: é sobre as ferramentas que ficam entre você e o código. Quem domina terminal, Git e DevTools trabalha mais rápido e, principalmente, com menos medo — porque tudo tem volta.

Revisão já conversamos sobre isso Novo ainda não vimos 7 partes · 42 tópicos

Nenhum tópico com esse filtro.

PARTE 1

O terminal

A janela preta que assusta e depois vira a ferramenta mais rápida que você tem. Não é sobre decorar comandos — são seis que resolvem 95% do dia. É sobre entender que o computador aceita ordem escrita, e que ordem escrita se repete, se guarda e se automatiza.

Por que sair do mouse

Novo

Você já usou o terminal sem saber: quando o Claude Code roda, é ali que ele está. Toda ferramenta séria de desenvolvimento — git, npm, Vercel, Astro — nasce como comando de terminal e só depois, às vezes, ganha uma interface gráfica.

A diferença prática é esta: no mouse, renomear 40 arquivos são 40 operações manuais. No terminal, é uma linha. E a linha você pode salvar, repetir no mês seguinte e mandar para outra pessoa.

O que trava a maioria: a ideia de que é preciso decorar. Não é. Ninguém decora — se consulta. O que você precisa entender de verdade são dois conceitos: onde você está e o que o comando faz com o que está ali. O resto é pesquisa.

Abrir o terminal — Windows, Mac e Linux

Novo

No Windows, use o PowerShell ou, melhor ainda, o Windows Terminal (grátis na Microsoft Store). Atalho: tecla Windows, digite "terminal", Enter. Se você instalar o Git, ganha também o Git Bash, que fala a mesma língua do Mac e do Linux — é o que eu recomendo para começar, porque todo tutorial que você achar na internet vai assumir essa sintaxe.

No Mac, é o Terminal (Cmd+Espaço, digite "terminal"). No Linux, Ctrl+Alt+T na maioria das distribuições.

Dentro do VS Code, qualquer sistema: Ctrl+' (ou Ctrl+Shift+P → "toggle terminal"). Esse é o que você mais vai usar, porque ele já abre na pasta do projeto aberto.

Atalho que vale ouro no Windows: abra a pasta do projeto no Explorador, clique na barra de endereço, apague o caminho, digite cmd e dê Enter. O terminal abre já naquela pasta. No Mac, clique com o botão direito na pasta → Serviços → "Novo Terminal na Pasta".

Onde eu estou e como eu ando

Novo

O terminal sempre está dentro de uma pasta. Todo comando age a partir dali. Se você entender só isso, metade da confusão some.

terminal
pwd              # "print working directory" — onde estou agora
ls               # lista o que tem aqui   (Windows PowerShell: dir)
ls -la           # lista tudo, inclusive arquivos ocultos, com detalhes

cd projetos      # entra na pasta "projetos"
cd ..            # sobe um nível
cd ../..         # sobe dois
cd ~             # vai para a sua pasta de usuário
cd -             # volta para a pasta anterior (o "voltar" do navegador)

Caminho relativo parte de onde você está: cd site/imagens. Caminho absoluto parte da raiz e funciona de qualquer lugar: cd /Users/gustavo/projetos/site no Mac, cd C:\Users\gustavo\projetos\site no Windows.

Pasta com espaço no nome quebra o comando, porque o espaço separa argumentos. Ou você põe aspas — cd "meus projetos" — ou você para de usar espaço em nome de pasta de projeto, que é o que todo mundo acaba fazendo.

Criar, copiar, mover, apagar

Novo
terminal
mkdir cliente-vanessa          # cria pasta
mkdir -p cliente/img/hero      # cria a árvore inteira de uma vez

touch index.html               # cria arquivo vazio (Git Bash, Mac, Linux)
New-Item index.html            # equivalente no PowerShell

cp index.html backup.html      # copia
cp -r site/ site-backup/       # copia pasta inteira (-r = recursivo)

mv antigo.html novo.html       # renomeia
mv index.html site/            # move para dentro de uma pasta

rm arquivo.html                # apaga arquivo
rm -r pasta/                   # apaga pasta inteira

code .                         # abre a pasta atual no VS Code
open .                         # abre no Finder (Mac)  |  explorer . no Windows

Repare que renomear e mover são o mesmo comando. Faz sentido: mover é mudar o caminho, renomear é mudar o final do caminho.

O que realmente economiza tempo

Novo

Quatro hábitos separam quem sofre no terminal de quem voa nele.

AtalhoO que faz
TabCompleta nome de arquivo ou pasta. Digite cd cli e dê Tab — ele completa sozinho. Use sempre; erro de digitação em nome de arquivo some.
↑ e ↓Navega pelos comandos que você já rodou. O comando de ontem ainda está lá.
Ctrl+RBusca no histórico. Aperte e digite "commit" — ele acha o último commit que você fez.
Ctrl+CAborta o que está rodando. Serve para sair de servidor local, de processo travado, de tudo.
Ctrl+LLimpa a tela (ou digite clear). Não apaga nada, só dá espaço.

E os curingas, que é onde a economia vira absurda:

terminal
ls *.html              # só os arquivos .html
cp *.jpg fotos/        # copia todos os jpg de uma vez
rm *.tmp               # apaga todos os temporários

# quantas linhas tem cada página do site?
wc -l *.html

# em quais arquivos aparece o telefone antigo do cliente?
grep -rl "3321-4455" .
Esse último — grep — é o que eu usei para conferir se o menu novo tinha entrado nas dez páginas do seu site. Ele procura um texto dentro dos arquivos, recursivamente, e lista onde achou. Em trabalho de cliente, é o comando que responde "onde mais esse telefone está escrito?" em dois segundos.

Encadear comandos

Novo

Três operadores, e você monta rotinas inteiras.

terminal
mkdir site && cd site        # só entra se conseguiu criar
git add . && git commit -m "hero pronta"   # só commita se o add deu certo

ls *.html | wc -l            # o "|" joga a saída de um na entrada do outro
                             # = "liste os html e conte quantas linhas saíram"

ls -la > lista.txt           # manda a saída para um arquivo (sobrescreve)
echo "nova linha" >> log.txt # acrescenta ao final do arquivo

O && é o mais útil no dia a dia, justamente porque ele para se algo falhar. Se o git add der erro, você não quer que o commit aconteça mesmo assim.

Os comandos que não têm volta

Novo

No terminal não existe lixeira. rm apaga de verdade, na hora, sem perguntar.

terminal
# SEMPRE veja antes de apagar
ls *.tmp          # confere o que vai sumir
rm *.tmp          # aí sim

rm -i arquivo     # -i pergunta antes de cada um

# nunca, em hipótese alguma:
rm -rf /          # apaga o sistema inteiro
rm -rf ~          # apaga sua pasta de usuário inteira
A regra que resolve: antes de qualquer rm com curinga, rode o mesmo padrão com ls. Se a lista que aparecer for exatamente o que você quer perder, troque ls por rm e rode. Leva três segundos e já salvou muita gente.

E aqui está o melhor argumento para a parte seguinte: se o projeto estiver no Git, apagar arquivo errado deixa de ser tragédia e vira um comando de recuperação. É por isso que Git vem logo depois do terminal, e não depois de mais nada.

PARTE 2

Git: o conceito antes do comando

Quase todo mundo aprende Git decorando comandos e fica anos sem entender o que está acontecendo. Vinte minutos de conceito aqui economizam meses de medo depois — porque quando você sabe o que cada área é, o comando certo se torna óbvio.

O problema que ele resolve

Novo

Você já viveu isto: index-final.html, index-final2.html, index-FINAL-agora-vai.html. E na hora de saber o que mudou entre um e outro, ninguém sabe.

Git responde quatro perguntas que a pasta de arquivos não responde:

PerguntaSem GitCom Git
O que eu mudei desde ontem?Você compara no olhogit diff
Quando isso quebrou?Não dá para sabergit log e você lê a história
Como volto pro que funcionava?RezaUm comando
Posso testar uma ideia sem risco?Copia a pasta inteiragit branch

Para o seu caso específico tem uma quinta: quando o Claude Code muda dez arquivos de uma vez, o Git é o que te mostra exatamente o que ele fez — e o que te devolve o estado anterior se ele fez besteira. Sem isso, você está aceitando mudança no escuro.

As três áreas — o modelo mental inteiro

Novo

Todo comando de Git move arquivo entre três lugares. Entenda os três e o resto se explica.

ÁreaO que éComo se chega nela
Diretório de trabalhoSua pasta, do jeito que está agora. É o que o VS Code mostra.Você edita e salva
Área de preparo (staging)A bandeja onde você separa o que vai no próximo commit. Nem tudo que mudou precisa ir junto.git add
RepositórioA história gravada. Imutável. Cada ponto é um commit.git commit

Por que existe a bandeja do meio? Porque numa tarde você mexe no menu, corrige um telefone e começa uma seção nova. Isso é três assuntos. Se virar um commit só, a história fica inútil — e daqui a um mês, quando o telefone estiver errado, você não consegue desfazer só aquilo.

Analogia que funciona: o diretório de trabalho é sua mesa bagunçada; o preparo é a caixa onde você separa o que vai pro correio; o commit é postar. Depois de postado, não volta — mas você tem o comprovante e sabe exatamente o que foi.

O que é um commit bom

Novo

Um commit é uma foto do projeto inteiro mais uma mensagem explicando por quê. A foto o Git tira sozinho; a mensagem é sua, e é ela que decide se a história vai servir para alguma coisa.

mensagens
# ruim — não diz nada que o diff já não diga
"alterações"
"update"
"ajustes finais"
"asdasd"

# bom — diz o QUÊ e, quando não é óbvio, o PORQUÊ
"hero da Vanessa: troca foto e encurta headline"
"corrige telefone no rodapé das 10 paginas"
"menu vira dropdown agrupado — 10 links na barra nao cabiam no mobile"
"revert: volta animação da hero, estava atrasando o LCP"

Duas regras de tamanho que resolvem quase tudo: um commit, um assunto; e se a mensagem precisa de "e", provavelmente são dois commits. "Corrige telefone e adiciona seção de FAQ" é dois.

Escreva no presente e no imperativo: "corrige", não "corrigido" nem "corrigindo". É convenção universal e existe por um motivo prático — a mensagem descreve o que o commit faz quando aplicado, o que faz sentido tanto ao aplicar quanto ao desfazer.

O que o Git não é

Novo

Três confusões que custam caro:

Git não é GitHub. Git é o programa que roda no seu computador e guarda a história localmente — funciona sem internet, para sempre. GitHub é um site que hospeda cópias desses repositórios. Existem outros (GitLab, Bitbucket, Codeberg). Você pode usar Git a vida toda sem nunca criar conta em lugar nenhum.

Git não é backup. Ele guarda a história do que você mandou ele guardar. Arquivo que nunca entrou num commit não existe para ele. E se o HD morrer, morre o repositório junto — a cópia no GitHub é que cumpre o papel de backup, e é por isso que push importa.

Git não é para arquivo grande. Ele foi feito para texto, onde consegue guardar só a diferença entre versões. Foto de 8 MB da obra do cliente entra inteira, e de novo inteira a cada versão. Imagem de site (comprimida, uns 200 KB) tudo bem. Vídeo, PSD, pasta de fotos brutas do fotógrafo — não.

Na prática, para você: o repositório guarda o site. As fotos originais do cliente ficam no Drive. O que vai para o Git é a versão já tratada e comprimida que entra na página.
PARTE 3

Git no dia a dia

Os comandos que você vai usar todo dia, na ordem em que aparecem num projeto real. São menos do que parece: sete resolvem a semana inteira.

Instalar e configurar — uma vez só

Novo

Baixe em git-scm.com. No Windows, aceite os padrões e marque a opção que instala o Git Bash. No Mac, rodar git --version no Terminal já oferece a instalação.

terminal
git --version                       # confirma que instalou

git config --global user.name "Gustavo"
git config --global user.email "seu@email.com"

git config --global init.defaultBranch main   # nome moderno do ramo principal
git config --global core.editor "code --wait" # usa o VS Code quando pedir texto
git config --list                             # confere tudo
Use o mesmo e-mail da sua conta do GitHub. É assim que o site liga os commits ao seu perfil — do contrário, seu trabalho aparece como se fosse de um desconhecido.

Começar um projeto

Novo
terminal
mkdir lp-vanessa && cd lp-vanessa
git init                    # cria a pasta oculta .git — é o repositório inteiro

# ou, para trazer um projeto que já existe no GitHub:
git clone https://github.com/JaumNf/gustavo-tutorial.git
cd gustavo-tutorial

O git init cria uma pasta .git escondida. Ela é o repositório: toda a história mora ali. Copiar a pasta do projeto copia a história junto; apagar a .git apaga a história e deixa só os arquivos atuais.

Para o seu site hoje: em vez de arrastar arquivo no navegador do GitHub, o certo é git clone do repositório uma vez, editar os arquivos na sua máquina, e mandar com push. Foi exatamente o passo que faltava quando você subiu a pasta inteira por engano e o site quebrou.

O ciclo — status, add, commit

Novo

Este é o Git inteiro do dia a dia. Você vai repetir isso dez vezes por dia e vai parar de pensar nele.

terminal
git status                  # o comando mais importante: o que mudou, o que está preparado

git add index.html          # prepara um arquivo
git add css/ js/            # prepara pastas inteiras
git add .                   # prepara tudo que mudou
git add -p                  # prepara pedaço por pedaço, perguntando (ótimo para separar assuntos)

git commit -m "hero: nova foto e headline mais curta"

git status                  # confirma: "working tree clean"

git status é o comando que responde "e agora?". Rode-o sempre que estiver em dúvida — ele inclusive sugere o próximo comando no texto da resposta.

Atalho que você vai usar: git commit -am "mensagem" faz add e commit de uma vez, mas só para arquivos que o Git já conhece. Arquivo novo continua precisando de git add. É a pegadinha número um de quem está começando: o arquivo novo simplesmente não entra e ninguém percebe.

.gitignore — o que nunca deve entrar

Novo

Um arquivo chamado .gitignore na raiz do projeto lista o que o Git deve fingir que não existe.

.gitignore
# dependências — se reinstalam, não se versionam
node_modules/

# segredos — a linha mais importante deste arquivo
.env
.env.local
*.key

# lixo de sistema
.DS_Store
Thumbs.db

# saída de build
dist/
.vercel/

# originais pesados do cliente
fotos-brutas/
*.psd
Aviso sério: .gitignore só funciona para arquivo que ainda não entrou. Se você commitou uma chave de API e depois ignorou o arquivo, a chave continua na história, visível para sempre — e se o repositório for público, considere a chave vazada e troque na hora. Crie o .gitignore antes do primeiro commit, sempre.

Ler a história — log e diff

Novo
terminal
git log                              # história completa (q sai)
git log --oneline                    # uma linha por commit — o que você mais usa
git log --oneline -10                # os dez últimos
git log --oneline --graph --all      # desenha os ramos
git log -p index.html                # história de UM arquivo, com as mudanças

git diff                             # o que mudei e ainda não preparei
git diff --staged                    # o que está preparado, prestes a virar commit
git diff HEAD~1                      # o que mudou desde o commit anterior

git diff é o hábito que mais protege você: leia o diff antes de todo commit. É onde você pega o console.log esquecido, o texto de teste que ficou na página e a linha que o Claude Code mudou sem avisar.

No VS Code isso é visual: clique no arquivo na aba de Controle de Código-Fonte e ele mostra lado a lado o que saiu (vermelho) e o que entrou (verde). Para revisar mudança grande, é mais rápido que o terminal.

Desfazer — os três casos

Novo

Aqui mora o medo, e ele acaba quando você percebe que são só três situações.

terminal
# 1 · estraguei o arquivo e ainda NÃO commitei
git restore index.html          # joga fora a alteração e volta ao último commit
git restore .                   # em todos os arquivos — cuidado, não tem volta

# 2 · preparei errado (fiz add do que não queria)
git restore --staged index.html # tira da bandeja, mantém a alteração

# 3 · commitei e me arrependi
git commit --amend -m "mensagem certa"   # corrige o ÚLTIMO commit (só se ainda não deu push)
git revert abc1234                       # cria um commit novo que desfaz aquele — seguro
git reset --soft HEAD~1                  # desfaz o commit, mantém as alterações preparadas
git reset --hard HEAD~1                  # desfaz o commit E joga as alterações fora
A regra que evita desastre: se o commit já foi para o GitHub, use revert. Ele desfaz criando história nova, e ninguém mais perde trabalho. reset --hard e --amend reescrevem a história — ótimos enquanto é só seu, problemáticos depois que outra pessoa (ou a Vercel) já leu aquilo.

Recuperar uma versão antiga

Novo

O cenário real: o cliente diz que a página de ontem estava melhor.

terminal
git log --oneline               # ache o código do commit, ex: 9f3a1c2

# só olhar como o site estava naquele dia:
git checkout 9f3a1c2            # o projeto inteiro volta no tempo
git switch -                    # e volta para o presente

# trazer UM arquivo daquela versão para o presente:
git restore --source=9f3a1c2 index.html

# apagou um arquivo sem querer e já commitou?
git restore --source=HEAD~1 arquivo-que-sumiu.html
E o comando que salva quando tudo parece perdido: git reflog. Ele lista todo movimento que você fez no repositório, inclusive os que o log não mostra mais depois de um reset. Ache o código ali e volte para ele. Enquanto o commit existiu em algum momento, ele quase nunca some de verdade nos primeiros dias.
PARTE 4

Branch, GitHub e deploy automático

Onde o Git deixa de ser só história e vira método de trabalho: testar sem risco, publicar sem arrastar arquivo, e voltar atrás com o site no ar.

Branch — testar sem medo

Novo

Um branch é uma linha paralela da história. Você sai do principal, faz o que quiser, e ou junta de volta ou joga fora. Nada do que acontece ali afeta o site no ar.

terminal
git switch -c hero-nova       # cria e entra no branch (antes: git checkout -b)
# ... trabalha, commita à vontade ...

git switch main               # volta para o principal
git merge hero-nova           # traz as mudanças para cá
git branch -d hero-nova       # apaga o branch, já cumpriu o papel

git branch                    # lista os que existem
git branch -D hero-nova       # apaga mesmo sem ter juntado (a ideia não prestou)
Quando usar, no seu trabalho: toda vez que você for testar algo que pode não dar certo — uma hero diferente, uma animação nova, uma reorganização grande. E toda vez que for pedir ao Claude Code uma mudança ampla: cria o branch, deixa ele trabalhar, revisa o diff, e junta só se prestar. Se não prestar, git branch -D e não sobrou rastro.

Conflito — o que é e como sair

Novo

Conflito acontece quando dois branches mudaram a mesma linha do mesmo arquivo e o Git não tem como adivinhar qual vale. Ele para, marca o trecho e pede que você decida.

no arquivo
<<<<<<< HEAD
<h1>Arquitetura que cabe no seu prazo</h1>
=======
<h1>Projetos de interiores em Campo Grande</h1>
>>>>>>> hero-nova

Em cima, o que está no branch atual. Embaixo, o que vem do outro. Você apaga as três linhas de marcação e deixa o texto que quer ficar — pode ser um dos dois, pode ser uma mistura. Depois:

terminal
git add index.html
git commit                      # finaliza o merge

git merge --abort               # ou desiste e volta tudo como estava
O VS Code mostra isso com botões — "Aceitar atual", "Aceitar entrada", "Aceitar ambos". Use. Editar marcação de conflito na mão é como quase todo mundo já deixou um >>>>>>> escapar para dentro do site publicado.

GitHub — mandar e trazer

Novo
terminal
git remote -v                              # quais servidores este projeto conhece
git remote add origin https://github.com/JaumNf/gustavo-tutorial.git

git push -u origin main    # manda pela primeira vez e guarda o destino
git push                   # daí em diante, só isso

git pull                   # traz o que mudou no servidor para cá
git fetch                  # só verifica, sem mexer nos seus arquivos

origin é só um apelido para o endereço do servidor — o nome padrão, nada mágico. main é o branch.

Senha não funciona mais. O GitHub não aceita senha de conta no push desde 2021. Você usa um Personal Access Token (Settings → Developer settings → Tokens) no lugar da senha, ou configura chave SSH. O jeito mais simples hoje é instalar o gh (GitHub CLI) e rodar gh auth login — ele resolve tudo sozinho.

Push vira deploy

Novo

É aqui que tudo se junta. Com o repositório ligado à Vercel — que é como o seu site já está hoje — publicar deixa de ser uma tarefa:

terminal
git add .
git commit -m "trilha de fluxo de trabalho"
git push

# pronto. A Vercel detecta, constrói e publica sozinha em ~30 segundos.

E tem o bônus que quase ninguém usa: todo branch ganha uma URL de pré-visualização própria. Você faz git push -u origin hero-nova e a Vercel publica aquele branch num endereço separado. Isso resolve um problema real do seu ofício — mandar para o cliente ver a proposta nova sem tocar no site que está no ar.

E quando quebra em produção: no painel da Vercel, em Deployments, qualquer versão anterior tem a opção "Promote to Production". O site volta ao estado bom em segundos, enquanto você investiga com calma. Isso só existe porque cada deploy está amarrado a um commit.

O erro que você já cometeu

Revisão

Vale registrar porque é o erro mais comum de quem sobe arquivo pelo navegador: você arrastou a pasta gustavo-tutorial-site/ para o GitHub. Os arquivos foram parar em /gustavo-tutorial-site/index.html, e a Vercel serve a raiz — então o site respondeu 404.

O diagnóstico foi comparar duas URLs: /estilo.css deu 404 e /gustavo-tutorial-site/estilo.css deu 200. Isso localiza o problema em dez segundos e serve para qualquer site quebrado.

terminal
# com Git, o mesmo erro não acontece — você trabalha DENTRO da pasta certa:
cd gustavo-tutorial     # o clone do repositório
cp ~/Downloads/gustavo-tutorial-site/*.html .
cp ~/Downloads/gustavo-tutorial-site/*.css .
cp ~/Downloads/gustavo-tutorial-site/*.js .
git status              # confere: os arquivos estão na raiz
git add . && git commit -m "laboratorio de movimento" && git push
Repare que o git status antes do commit teria mostrado o caminho errado imediatamente. É o mesmo princípio do ls antes do rm: olhar antes de confirmar.

Git com o Claude Code

Novo

Esta é a parte que muda mais o seu dia, porque o problema de trabalhar com IA em código é exatamente o problema que o Git resolve: como eu sei o que mudou e como eu volto?

HábitoPor quê
Commit antes de pedirCria o ponto de retorno. Sem ele, "desfaz isso" vira arqueologia.
Branch para mudança grandeReestruturação, seção nova, refatoração. Se não prestar, apaga o branch inteiro.
git diff antes de aceitarÉ a revisão de verdade. Ler o resumo da IA não é revisar — ler o diff é.
Um commit por etapa entregueCasa com fatiar o trabalho: cada pedaço aprovado vira um commit.
Nunca add . no escuroCom IA mexendo em vários arquivos, git status primeiro, sempre.

O ciclo completo fica assim:

terminal
git switch -c secao-faq          # ponto de partida limpo
# ... pede a seção ao Claude Code ...
git status                       # o que ele tocou?
git diff                         # o que exatamente ele escreveu?
git add . && git commit -m "faq: quatro perguntas com acordeão"
git switch main && git merge secao-faq && git push
Isso conversa direto com a trilha Trabalhando com IA: lá você aprende a fatiar o pedido; aqui, cada fatia aprovada vira um commit. As duas juntas é que dão o controle — pedido pequeno, commit pequeno, volta fácil.
PARTE 5

DevTools: inspecionar e editar ao vivo

As ferramentas do desenvolvedor vêm dentro do navegador, de graça, e são onde você resolve problema de CSS em minuto em vez de hora. A maioria das pessoas usa 5% delas — aqui estão os 30% que importam.

Abrir e se situar

Novo

F12, ou Ctrl+Shift+I (Cmd+Option+I no Mac). Mas o jeito que economiza mais tempo é outro: botão direito no elemento → Inspecionar. Isso abre já com aquele elemento selecionado.

AbaPara quê
ElementsO HTML e o CSS como o navegador realmente entendeu. Onde você passa 60% do tempo.
ConsoleErros de JavaScript e testes rápidos de código.
NetworkTudo que a página baixou, quanto pesou e quanto demorou.
LighthouseNota automática de performance, acessibilidade e SEO.
ApplicationlocalStorage, cookies, service worker.
Ctrl+Shift+P dentro das DevTools abre uma busca de comandos, igual à do VS Code. Digite "screenshot" e você tira print da página inteira, inclusive a parte que não cabe na tela — útil para mandar proposta ao cliente.

Elements — editar o site do cliente ao vivo

NovoCSS

No painel Elements, o lado esquerdo é o HTML e o direito é o CSS aplicado àquele elemento. Tudo é editável, e a página responde na hora. Nada disso é salvo — recarregou, voltou ao normal.

AçãoComo
Mudar um valor de CSSClique no número e use ↑ ↓. Com Shift, anda de 10 em 10.
Testar uma propriedadeClique no espaço em branco da regra e digite. Ele autocompleta.
Desligar uma regraCaixinha ao lado dela. Ótimo para descobrir qual linha está causando o problema.
Editar o texto da páginaDuplo clique no texto dentro do HTML.
Ver o valor finalAba Computed — mostra o que venceu, depois de toda a cascata.
Achar de onde veioO nome do arquivo e a linha aparecem à direita de cada regra. Clique e ele te leva lá.
O uso comercial disso: abra o site atual do cliente, mude a cor do botão e o texto da chamada ao vivo, tire um print e mande. Você acabou de mostrar a melhoria no site dele, sem ter feito nada ainda. Funciona melhor que qualquer portfólio.

Forçar estados — hover, focus, dark mode

NovoCSS

Como você estiliza :hover se o estilo some quando você tira o mouse para ir até as DevTools? Você força o estado.

No painel Styles, o botão :hov abre caixas para :hover, :active, :focus, :focus-visible e :visited. Marque e o elemento fica travado naquele estado enquanto você ajusta.

Logo ao lado, o ícone de pincel (Rendering, ou Ctrl+Shift+P → "rendering") tem as simulações que mais importam para o seu trabalho:

SimulaçãoTesta
prefers-color-schemeTema escuro sem mexer no sistema
prefers-reduced-motionSe suas animações realmente desligam
Deficiências de visãoComo o daltônico vê seu contraste de botão
Paint flashingPisca em verde o que o navegador redesenhou — expõe animação cara
O simulador de daltonismo é o teste de dez segundos que evita o erro clássico: verde e vermelho como "disponível" e "indisponível". Para 8% dos homens, os dois são a mesma cor.

Caçar o problema de layout

NovoCSS

Os três problemas de layout que mais aparecem e onde exatamente olhar:

"Por que tem espaço em branco aqui?" — passe o mouse sobre os elementos no painel Elements. O navegador pinta o box model por cima da página: azul é o conteúdo, verde é o padding, laranja é a margem. O culpado costuma estar na faixa laranja.

"Por que a página rola para o lado no celular?" — cole isto no Console e o elemento culpado fica com borda vermelha:

console
document.querySelectorAll('body *').forEach(el => {
  if (el.getBoundingClientRect().right > window.innerWidth) {
    el.style.outline = '2px solid red';
    console.log(el);
  }
});

"Meu grid/flex não está fazendo o que eu quero" — ao lado do elemento aparece um selo grid ou flex. Clique: o navegador desenha as linhas, numera as colunas e mostra os espaçamentos sobre a página.

Ver o código-fonte de verdade

Novo

Uma distinção que confunde muita gente: Ctrl+U mostra o HTML que veio do servidor. O painel Elements mostra o DOM depois de todo o JavaScript ter rodado. Num site feito em React, o primeiro vem quase vazio e o segundo está cheio.

Isso tem consequência direta no seu trabalho: o Google, quando rastreia, começa pelo primeiro. É a razão técnica de HTML puro ter vantagem em SEO — o conteúdo já está lá, sem depender de nada rodar.

Teste prático em site de concorrente: Ctrl+U e procure pelo texto da chamada principal. Se achar, é HTML servido pronto. Se não achar, o conteúdo depende de JavaScript — e você acabou de descobrir uma fraqueza de SEO que pode virar argumento na sua proposta.
PARTE 6

DevTools: Console, Network e celular

A parte que responde "por que está lento" e "por que quebra só no iPhone do cliente". É também onde você para de adivinhar e passa a medir.

Console — ler o erro em vez de temer

NovoJS

Quando algo de JavaScript quebra, a página simplesmente para de fazer aquilo — sem aviso na tela. O Console é o único lugar onde o erro aparece. Primeira coisa a fazer quando "não está funcionando": abrir o Console.

erros comuns
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
→ o querySelector não achou o elemento. Erro de digitação na classe,
  ou o script rodou antes do HTML existir.

Uncaught ReferenceError: gsap is not defined
→ a biblioteca não carregou. Veja a aba Network: o arquivo veio?

Failed to load resource: 404 (Not Found)
→ caminho de arquivo errado. Foi exatamente o seu erro da pasta no GitHub.

Refused to load ... violates Content Security Policy
→ o servidor bloqueou um script externo.

E o Console também é um laboratório: qualquer JavaScript roda ali, na página aberta, na hora.

console
$0                          // o elemento selecionado no painel Elements
$$('a')                     // atalho para querySelectorAll
$$('img').filter(i => !i.alt)          // toda imagem sem texto alternativo
$$('a').filter(a => !a.href)           // todo link quebrado
document.querySelectorAll('h1').length // tem mais de um h1? (problema de SEO)
Essas três últimas linhas são uma auditoria de acessibilidade e SEO em dez segundos, em qualquer site — inclusive no do cliente, antes da reunião.

Network — descobrir o que pesa

Novo

Abra a aba Network e recarregue com ela aberta (senão vem vazia). Cada linha é um arquivo que a página pediu.

Ordene pela coluna Size, do maior para o menor. Em nove de dez sites lentos, as três primeiras linhas são imagens — e a conversa sobre performance acaba ali. No rodapé o navegador soma tudo: requests e transferred.

ReferênciaPeso total da página
Excelenteabaixo de 500 KB
Bomaté 1 MB
Ruim no 4Gacima de 2 MB
Vergonhaacima de 5 MB — e é mais comum do que parece

Os filtros no topo (Doc, CSS, JS, Img, Font) isolam por tipo. E a coluna Waterfall mostra a ordem: o que está segurando o resto aparece como uma barra longa antes das outras.

O teste que muda a conversa com o cliente: no seletor de velocidade, escolha "Slow 4G" e recarregue. É isso que a cliente dele sente ao abrir a página no ônibus. Quando você mostra essa tela, ninguém mais discute se vale comprimir as fotos.

Modo dispositivo — e o que ele não resolve

Novo

Ctrl+Shift+M liga o modo dispositivo: a página passa a ser renderizada numa largura de celular, com toque simulado.

Use larguras reais, não as do menu apenas: 360px (Android popular), 390px (iPhone atual), 430px (iPhone grande), 768px (tablet). Se funciona em 360, funciona em quase tudo.

O que ele mente: é o Chrome do seu computador fingindo ser um celular. Ele não reproduz o Safari do iPhone (que tem regras próprias), nem o desempenho real de um aparelho de entrada, nem a barra do navegador comendo altura da tela, nem como o teclado virtual empurra o layout quando o campo recebe foco. Aprovar layout só por aqui é o que faz o cliente abrir no próprio celular e achar quebrado.

Depurar no celular de verdade

Novo

Dá para abrir as DevTools do computador apontando para a página que está rodando no aparelho. É o que resolve o "só no meu iPhone que quebra".

Android + Chrome: no celular, Configurações → Sobre o telefone → toque 7 vezes em "Número da versão" para liberar as opções de desenvolvedor; ative a Depuração USB. Conecte o cabo, aceite o aviso, e no computador abra chrome://inspect. A aba aberta no celular aparece na lista com um botão inspect.

iPhone + Safari: no iPhone, Ajustes → Apps → Safari → Avançado → Inspetor da Web. No Mac, Safari → Ajustes → Avançado → "Mostrar recursos para desenvolvedores". Conecte o cabo e o aparelho aparece no menu Desenvolvedor do Safari.

Sem Mac e precisa testar iPhone? Duas saídas honestas: peça a alguém com iPhone para abrir e mandar print e vídeo da tela, ou use um serviço de teste em aparelho real na nuvem (BrowserStack e LambdaTest têm plano gratuito limitado). Torcer para dar certo não é uma das opções — o Safari do iOS é onde mais aparece diferença, e boa parte dos clientes de serviço local usa iPhone.

Lighthouse — a nota e o que fazer com ela

Novo

A aba Lighthouse roda uma auditoria automática e devolve quatro notas: Performance, Acessibilidade, Boas práticas e SEO. Marque "Mobile" — é o que o Google usa para ranquear.

Duas ressalvas para você não se enganar com o número:

Rode em aba anônima. Extensões do Chrome entram na conta e derrubam a nota de uma página que está ótima.

É laboratório, não realidade. Lighthouse simula um aparelho e uma rede. O dado que o Google realmente usa vem dos usuários de verdade e aparece no PageSpeed Insights (pagespeed.web.dev), na seção de dados de campo — que só existe depois que o site tem tráfego.

Onde olhar primeiro: ignore a nota e desça até "Opportunities" e "Diagnostics". Ali está a lista do que consertar, ordenada por quanto tempo cada item economiza. Normalmente as duas primeiras linhas são imagem, e resolver só elas já sobe a nota dezenas de pontos. Nota 100 não é meta — nota acima de 90 no celular com a página fazendo o que precisa fazer é.

Cache — o "mas eu já corrigi isso"

Novo

Você corrige, publica, abre e a versão antiga continua lá. Não está louco: o navegador guardou o CSS antigo.

SituaçãoSolução
Testando você mesmoCom as DevTools abertas, botão direito no recarregar → "Limpar cache e atualizar forçado". Ou marque Disable cache na aba Network e deixe as DevTools abertas enquanto trabalha.
O cliente é que está vendo antigoNão peça para ele limpar cache — metade não vai conseguir. Mande o link com um parâmetro: site.com.br/?v=2. É outro endereço para o navegador.
Para nunca mais acontecerVersione o arquivo: estilo.css?v=3 no <link>. Mudou o CSS, muda o número. A Vercel e as hospedagens modernas já fazem isso sozinhas no build.
Antes de passar meia hora atrás de um bug, faça o recarregamento forçado. Uma parte desconfortavelmente grande dos "bugs" é cache — inclusive os que você jura que não são.
PARTE 7

Reuso sem build

O menu deste site está escrito por inteiro em dez arquivos HTML. Mudar um link significa mudar dez vezes — e esse é o preço do HTML puro em site multi-página. Existem cinco saídas, cada uma com um custo diferente. A pior é a que a maioria escolhe sem pensar.

O problema, com número

Novo

Quando este site ganhou a trilha de Movimento, o menu precisou de um link novo. Dez arquivos. Quando virou dropdown agrupado, foram dez blocos de HTML substituídos. Numa das vezes o trafego.html ficou de fora e ninguém percebeu na hora — porque conferir dez arquivos no olho é exatamente o tipo de tarefa em que o olho falha.

Esse é o único problema real do HTML puro em site de várias páginas. Não é performance, não é SEO, não é capacidade: é repetição de trecho comum — cabeçalho, menu, rodapé, scripts.

Quando isso não é problema: landing page de uma página só. Que é justamente o seu produto principal. Toda a discussão desta parte só começa a valer a partir do terceiro ou quarto arquivo HTML no mesmo projeto — antes disso, resolver é mais caro que conviver.

Saída 1 — copiar, com um script que garante

Novo

O HTML continua repetido, mas você nunca edita as dez cópias na mão: um script faz a substituição em todos os arquivos e você confere o resultado.

menu.py
import glob, re

NOVO = open('menu.html', encoding='utf-8').read()

for arquivo in glob.glob('*.html'):
    h = open(arquivo, encoding='utf-8').read()
    # troca tudo entre <nav class="navmenu"> e </nav>
    h = re.sub(r'<nav class="navmenu".*?</nav>', NOVO, h, flags=re.S)
    open(arquivo, 'w', encoding='utf-8').write(h)
    print(arquivo, 'ok')

É feio e funciona. Foi assim que o menu deste site foi trocado nas dez páginas, e é assim que se corrige um telefone errado em vinte arquivos de um site antigo.

GanhaPerde
HTML servido pronto, SEO perfeito, zero dependência, funciona em qualquer hospedagemPrecisa rodar o script; se esquecer, as páginas divergem em silêncio
Sempre feche com uma verificação, não com confiança: grep -L "movimento.html" *.html lista os arquivos que não têm o link novo. Se a saída vier vazia, entrou em todos.

Saída 2 — carregar o pedaço com fetch

NovoJS

O menu vira um arquivo só, e cada página o busca ao carregar.

html + js
<!-- em toda página -->
<div data-incluir="parciais/menu.html"></div>

<script>
document.querySelectorAll('[data-incluir]').forEach(async (el) => {
  const r = await fetch(el.dataset.incluir);
  el.innerHTML = await r.text();
  // marca a página atual depois que o menu existe
  const aqui = location.pathname.split('/').pop() || 'index.html';
  el.querySelector(`a[href="${aqui}"]`)?.classList.add('is-atual');
});
</script>
Não use isso para conteúdo que precisa ranquear. O HTML servido chega vazio; o menu só existe depois do JavaScript. Para um menu, o dano de SEO é pequeno — o Google executa JavaScript hoje, ainda que com atraso. Para texto de venda, título ou descrição, é sabotagem: você está escondendo do buscador exatamente o que ele precisa ler. Some ainda o flash de página sem menu, e o fato de que não funciona abrindo o arquivo direto do disco (file:// bloqueia fetch) — você precisa de um servidor local mesmo para testar.

Saída 3 — template para o que se repete na página

NovoHTML

<template> é HTML que o navegador lê mas não mostra, e que você clona quantas vezes quiser. Não resolve o menu entre páginas — resolve o card que se repete dentro de uma página, a partir de uma lista de dados.

html + js
<template id="tpl-servico">
  <article class="servico">
    <h3></h3>
    <p></p>
    <a class="cta">Pedir orçamento</a>
  </article>
</template>
<div id="servicos"></div>

<script>
const SERVICOS = [
  { titulo: 'Reforma completa',  texto: 'Do projeto à entrega da obra.' },
  { titulo: 'Interiores',        texto: 'Marcenaria, iluminação e acabamento.' },
  { titulo: 'Consultoria',       texto: 'Uma visita, um diagnóstico, um caminho.' },
];

const tpl = document.querySelector('#tpl-servico');
const destino = document.querySelector('#servicos');

SERVICOS.forEach(s => {
  const no = tpl.content.cloneNode(true);
  no.querySelector('h3').textContent = s.titulo;
  no.querySelector('p').textContent  = s.texto;
  no.querySelector('.cta').href =
    'https://wa.me/5567999999999?text=' + encodeURIComponent('Quero saber sobre ' + s.titulo);
  destino.appendChild(no);
});
</script>

Repare no textContent em vez de innerHTML: com textContent, texto que vem de fora nunca vira código. É a defesa contra XSS embutida no hábito.

Vale quando a lista é longa ou muda com frequência — catálogo de serviços, perguntas frequentes, depoimentos. Para três cards fixos, escrever os três em HTML é mais simples e melhor para SEO.

Saída 4 — Web Component

NovoJS

É o recurso nativo do navegador para criar sua própria tag. Sem framework, sem build.

js
class BotaoZap extends HTMLElement {
  connectedCallback() {
    const texto = this.getAttribute('texto') || 'Falar no WhatsApp';
    const msg   = this.getAttribute('mensagem') || 'Olá! Vim pelo site.';
    this.innerHTML = `<a class="cta" target="_blank" rel="noopener"
        href="https://wa.me/5567999999999?text=${encodeURIComponent(msg)}">${texto}</a>`;
  }
}
customElements.define('botao-zap', BotaoZap);
html
<botao-zap texto="Quero um orçamento"
           mensagem="Vi a página de reforma e quero um orçamento"></botao-zap>
Onde faz sentido: elemento que aparece muitas vezes com variação pequena, e cujo conteúdo não precisa ser lido pelo Google — botão, modal, carrossel, player. Para cabeçalho e rodapé, cai no mesmo problema do fetch: depende de JavaScript para existir. E evite o Shadow DOM aqui, senão o CSS do seu site não entra dentro do componente e você perde os tokens.

Saída 5 — aceitar um build mínimo

Novo

É a resposta certa para a maioria dos sites com mais de cinco páginas, e a que dá mais preguiça de aceitar — porque parece que você está abandonando o HTML puro. Não está: o resultado publicado continua sendo HTML, CSS e JS estáticos. A diferença é que o computador monta as páginas antes de publicar, em vez de o navegador montar depois.

com Astro
---
import Menu from '../componentes/Menu.astro';
---
<html lang="pt-BR">
<head><title>Movimento</title></head>
<body>
  <Menu atual="movimento" />
  <main>...</main>
</body>
</html>

O menu passa a existir em um arquivo. npm run build gera as dez páginas com o HTML completo dentro. SEO idêntico ao do HTML escrito na mão, porque é HTML escrito na mão — só que escrito uma vez.

O custo honesto: passa a existir node_modules, package.json e uma versão de Node que envelhece. Daqui a três anos, abrir esse projeto pode exigir meia hora de conserto antes de mudar uma vírgula — enquanto um HTML puro abre e edita para sempre. Por isso a regra: site que o cliente vai mexer ou que você vai manter por anos, HTML puro; site com muitas páginas que você atualiza toda semana, build.

A tabela de decisão

Novo
SituaçãoSaídaPor quê
Landing page, 1 arquivoNenhumaNão existe repetição para resolver
2 a 4 páginasCopiar + scriptMais barato que qualquer abstração
5+ páginas, você mantémBuild mínimo (Astro, Eleventy)Um arquivo de menu, HTML completo no fim
Cards repetidos de uma lista<template>Nativo, sem dependência
Botão/modal/carrossel recorrenteWeb ComponentVira uma tag sua, reaproveitável entre projetos
Trecho que não precisa ranquearfetchSimples, desde que o Google não precise ler
Cabeçalho, rodapé, texto de vendaNunca por JavaScriptÉ o que o buscador tem que encontrar no HTML servido
Este site, em particular: dez páginas, mantido toda semana — pela tabela, já passou da hora de um build. Ele continua em HTML puro de propósito, porque é material de estudo sobre HTML puro e precisa poder ser aberto e lido arquivo por arquivo. É um caso em que a decisão certa tecnicamente perde para a decisão certa no contexto — e saber diferenciar as duas é metade do ofício.