Configuração profissional no Next.js: ESLint + Prettier + Husky do zero

O pesadelo de uma sexta-feira à noite
Lembro bem da sexta-feira passada. Eu já estava prestes a desligar o computador e ir para casa quando vi uma mensagem do líder técnico no Slack: “Seu PR tem muitos problemas de formatação. Você pode arrumar isso antes de enviar novamente?” Abri o GitHub e encontrei uma tela cheia de diffs em vermelho, tudo porque alguns trechos usavam aspas duplas e outros tinham recuos inconsistentes.
Para ser sincero, bateu uma sensação enorme de impotência. Eu tinha quase certeza de que havia executado npm run lint antes do commit. Então por que ainda havia problemas? Para piorar, outro colega passou pela mesma situação. A lógica do código dele estava perfeita, mas a formatação era diferente da minha, e o merge acabou gerando vários conflitos sem qualquer valor.
Você já passou por isso? O código funciona bem, mas problemas de formatação fazem o PR ir e voltar na revisão, desperdiçando o tempo de todo mundo. Naquele momento, pensei: não existe uma solução definitiva que deixe a máquina cuidar automaticamente dessas tarefas repetitivas?
Existe: a combinação ESLint + Prettier + Husky.
Por que precisamos dessas três ferramentas?
Confesso que, quando ouvi esses três nomes pela primeira vez, também achei que parecia complicado demais. Depois de algum tempo usando as ferramentas, porém, não quis mais voltar atrás. Veja o valor de cada uma.
ESLint: o guardião da qualidade do código
Muita gente pensa que o ESLint serve apenas para verificar a formatação. Na verdade, sua função mais importante é detectar possíveis problemas no código.
Por exemplo, o Next.js recomenda o componente <Image> no lugar da tag HTML <img>, pois o primeiro oferece otimização automática. Se você escrever <img> sem perceber, o ESLint exibirá imediatamente um erro como este:
Error: Do not use <img>. Use Image from 'next/image' instead.
Esse tipo de aviso evita armadilhas de desempenho ainda durante o desenvolvimento. É muito mais eficiente do que descobrir, depois do lançamento, que as imagens carregam devagar e só então tentar otimizá-las.
O Next.js 15 habilita o ESLint por padrão, mas é preciso configurá-lo corretamente para aproveitar todo o seu potencial.
Prettier: a solução definitiva para formatação
O ESLint se concentra na lógica e na qualidade do código, enquanto o Prettier cuida da formatação. Cada ferramenta tem uma função clara, e não devemos misturá-las.
Antes, nosso time discutia com frequência por causa da formatação: algumas pessoas preferiam aspas simples, outras aspas duplas; algumas usavam recuo de 2 espaços, outras de 4. Cada code review acabava desviando para esses detalhes pouco importantes, o que era uma grande perda de tempo.
Depois de configurar o Prettier, esses problemas desapareceram. Basta definir as regras com o time no início do projeto — por exemplo, usar sempre aspas simples e recuo de 2 espaços — e o Prettier passa a formatar todo o código automaticamente. Configure uma vez e aproveite por muito tempo.
Husky: a peça-chave da automação
Por melhor que uma ferramenta seja, se depender de execução manual, alguém acabará esquecendo.
Isso já aconteceu comigo várias vezes: durante o desenvolvimento local, esqueci de executar npm run lint e fiz o commit diretamente. O pipeline de CI falhou e bloqueou o deploy de todo o time. É o tipo de constrangimento que ninguém quer repetir.
O Husky serve justamente para executar verificações automaticamente antes do commit. Na etapa de pre-commit do Git, ele intercepta o commit e roda ESLint e Prettier primeiro. O commit só é permitido quando o código está de acordo com as regras.
Em conjunto com o lint-staged, o Husky verifica apenas os arquivos modificados, em vez de analisar o projeto inteiro. Por isso, a execução é muito rápida e o hook de pre-commit não atrasa o fluxo de desenvolvimento.
A força das três ferramentas juntas
Com as três ferramentas combinadas, o fluxo funciona assim:
- O ESLint define regras de qualidade do código, como proibir
vare exigirconstoulet - O Prettier padroniza a formatação, como usar aspas simples em todas as strings
- O Husky executa as verificações automaticamente antes do commit, evitando esquecimentos
Os benefícios para o time são claros:
- O PR review deixa de perder tempo com formatação e se concentra na lógica de negócio
- Os conflitos de merge diminuem, pois a formatação é uniforme
- A taxa de falhas na CI cai, já que o código é verificado antes do commit
Processo completo de configuração
Agora vamos à prática. Vou orientar você passo a passo na configuração dessa cadeia de ferramentas, evitando os problemas mais comuns.
Etapa 1: inicialize um projeto Next.js
Se você já tem um projeto, pode pular esta etapa. Para um projeto novo, execute:
npx create-next-app@latest my-app
cd my-app
Durante a criação, selecione TypeScript e ESLint. O Next.js 15 habilita o ESLint por padrão, o que já economiza algum trabalho.
Etapa 2: instale as dependências
Execute o comando abaixo. Eu uso pnpm, mas você também pode usar npm ou yarn:
pnpm add -D eslint eslint-config-next prettier eslint-config-prettier husky lint-staged
Veja rapidamente a função de cada pacote:
eslint: núcleo do ESLinteslint-config-next: configuração oficial do ESLint para Next.js, incluindo regras específicas do frameworkprettier: núcleo do Prettiereslint-config-prettier: desativa regras de formatação do ESLint que entram em conflito com o Prettierhusky: gerenciador de Git hookslint-staged: executa verificações apenas nos arquivos em staging
Atenção: não instale eslint-plugin-prettier. Muitos tutoriais recomendam esse pacote, mas ele executa o Prettier como uma regra do ESLint e pode causar problemas de desempenho. A abordagem correta é executar ESLint e Prettier separadamente.
Etapa 3: configure o ESLint
Esta é a etapa em que mais surgem problemas, principalmente porque a migração do Next.js 15 para o ESLint 9 mudou o formato de configuração.
Use o formato Flat Config do ESLint 9 (recomendado)
Crie o arquivo eslint.config.mjs na raiz do projeto:
// eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc';
import nextPlugin from '@next/eslint-plugin-next';
const compat = new FlatCompat();
export default [
...compat.extends('next/core-web-vitals'),
{
plugins: {
'@next/next': nextPlugin,
},
rules: {
'@next/next/no-img-element': 'error',
'react/no-unescaped-entities': 'off',
// Adicione suas próprias regras aqui
},
},
{
ignores: ['.next/', 'node_modules/', 'out/'],
},
];
Pontos importantes:
- O ESLint 9 não usa mais
.eslintrc.json; ele adota o formato flat config emeslint.config.mjs - Se, depois de atualizar para o Next.js 15, você encontrar o erro “The Next.js plugin was not detected”, provavelmente o formato da configuração está incorreto
- O Next.js 16 removerá o comando
next lint, então vale a pena se adaptar ao novo formato desde já
Alternativa temporária em caso de incompatibilidade
Se você ainda não quiser lidar com o flat config, pode definir uma variável de ambiente e voltar ao formato de configuração do ESLint 8:
ESLINT_USE_FLAT_CONFIG=false
Depois, continue usando .eslintrc.json:
{
"extends": ["next/core-web-vitals", "prettier"],
"rules": {
"@next/next/no-img-element": "error"
}
}
Ainda assim, recomendo migrar para o flat config o quanto antes, pois essa é a direção futura da ferramenta.
Etapa 4: configure o Prettier
Crie .prettierrc.json na raiz do projeto:
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"tabWidth": 2,
"printWidth": 80,
"arrowParens": "avoid"
}
Essas são as configurações que eu prefiro, mas você pode ajustá-las às práticas do seu time:
singleQuote: true: prefiro aspas simples, pois acho o código mais limpoprintWidth: 80: limita cada linha a 80 caracteres, o que funciona bem ao exibir várias janelas do editor lado a ladotrailingComma: 'es5': adiciona vírgula ao último item de objetos e arrays, deixando o Git diff mais limpo
Crie também .prettierignore para informar ao Prettier quais arquivos devem ser ignorados:
.next
out
node_modules
public
*.lock
Integração com o VSCode (opcional, mas recomendada)
Se você usa VSCode, crie .vscode/settings.json para formatar o código automaticamente ao salvar:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
Assim, sempre que você pressionar Ctrl + S para salvar um arquivo, o Prettier formatará o código automaticamente. É muito prático.
Etapa 5: configure Husky + lint-staged
Esta é a parte mais valiosa de todo o processo e a que mais melhora a colaboração no time.
Inicialize o Husky
Execute:
pnpm dlx husky init
Esse comando cria automaticamente a pasta .husky/ e adiciona o script prepare ao package.json:
{
"scripts": {
"prepare": "husky install"
}
}
O script prepare garante que os hooks do Husky sejam instalados automaticamente quando os integrantes do time executarem pnpm install. Assim, quem entrar no projeto não precisará de nenhuma etapa extra: basta clonar o repositório e aproveitar as verificações automáticas.
Configure o hook de pre-commit
Edite o arquivo .husky/pre-commit:
pnpm lint-staged
É só isso. Toda vez que você executar git commit, o Husky rodará pnpm lint-staged primeiro.
Configure o lint-staged
Crie .lintstagedrc.mjs na raiz do projeto:
export default {
'*.{js,jsx,ts,tsx}': [
'eslint --fix',
'prettier --write',
],
'*.{json,md,css}': [
'prettier --write',
],
};
Essa configuração faz o seguinte:
- Para arquivos
.js,.jsx,.tse.tsx, executa primeiroeslint --fix, que corrige problemas automaticamente, e depoisprettier --write, que aplica a formatação - Para arquivos
.json,.mde.css, executa apenasprettier --write
Dicas de otimização de desempenho:
- Verifique apenas arquivos em staging: o lint-staged filtra automaticamente os arquivos adicionados com
git add, sem analisar o projeto inteiro - Evite verificações globais: nunca execute
pnpm lintno pre-commit, pois ele verifica o projeto inteiro e pode ser lento - Pule os testes: use o pre-commit apenas para formatação e verificações básicas de qualidade; deixe os testes mais complexos para a CI
- Ignore a verificação em uma emergência: se você realmente precisar pular as verificações, por exemplo para uma correção urgente em produção, use
git commit --no-verify
Solução de problemas comuns
O Husky não funciona no Windows
Se você usa Windows, verifique se o Git está configurado para usar o Git Bash, e não o CMD ou PowerShell. Confira também se o arquivo .husky/pre-commit tem permissão de execução:
chmod +x .husky/pre-commit
O hook demora demais para executar
Se o hook de pre-commit levar mais de 10 segundos, confira a configuração do lint-staged e verifique se ela não está analisando o projeto inteiro por engano. Em condições normais, o lint-staged leva de 2 a 3 segundos para verificar apenas alguns arquivos.
Valide a configuração
Depois de concluir a configuração, vamos verificar se tudo funciona.
Etapas do teste
- Modifique qualquer arquivo e introduza intencionalmente um problema de formatação, como trocar aspas simples por duplas ou remover alguns pontos e vírgulas
- Execute
git add . - Execute
git commit -m "test" - Observe a saída do terminal
Como reconhecer que deu certo
Se a configuração estiver correta, você verá uma saída parecida com esta:
✔ Preparing lint-staged...
✔ Running tasks for staged files...
✔ Applying modifications from tasks...
✔ Cleaning up temporary files...
Abra o arquivo modificado e você verá que os problemas de formatação foram corrigidos automaticamente. Esse é o poder da automação.
Se algo falhar
- Confirme se o arquivo
.husky/pre-commitexiste e se o conteúdo está correto - Confirme se
.lintstagedrc.mjsestá na raiz do projeto - Tente executar
pnpm lint-stagedmanualmente e observe se aparece alguma mensagem de erro
Configuração avançada
A configuração básica já atende à maioria das necessidades, mas você pode adotar as opções abaixo se quiser um controle de qualidade mais rigoroso.
Adicione o commitlint para padronizar mensagens de commit
Além da formatação do código, também é importante padronizar as mensagens de commit. O commitlint garante que todo o time siga o mesmo formato, como Conventional Commits.
Instale as dependências:
pnpm add -D @commitlint/cli @commitlint/config-conventional
Crie commitlint.config.mjs:
export default {
extends: ['@commitlint/config-conventional'],
};
Adicione o hook de commit-msg:
echo "pnpm commitlint --edit \$1" > .husky/commit-msg
Agora, se a mensagem do commit não seguir o padrão, como git commit -m "fix bug" em vez de git commit -m "fix: bug", o commit será bloqueado.
Adicione a verificação de tipos do TypeScript
Se quiser executar automaticamente a verificação de tipos do TypeScript antes do commit, altere .lintstagedrc.mjs:
export default {
'*.{ts,tsx}': [
() => 'tsc --noEmit', // Verificação de tipos
'eslint --fix',
'prettier --write',
],
'*.{js,jsx}': [
'eslint --fix',
'prettier --write',
],
'*.{json,md,css}': [
'prettier --write',
],
};
Atenção: tsc --noEmit verifica os tipos do projeto inteiro e pode ser lento. Se o projeto for grande, isso pode atrasar o hook de pre-commit. Pessoalmente, recomendo deixar a verificação de tipos para a CI e usar o pre-commit apenas para formatação e verificações básicas.
Configuração para Monorepo
Se o seu projeto for um Monorepo, por exemplo com pnpm workspace ou Turborepo, a configuração é um pouco mais complexa:
- Instale Husky e lint-staged na raiz
- Crie um
.lintstagedrc.mjsindependente em cada package - Evite que a configuração “vaze” para outros packages
Consulte a documentação oficial do lint-staged para ver os detalhes da configuração.
Problemas comuns e soluções
Alguns problemas podem surgir durante a configuração. Veja abaixo as armadilhas mais frequentes e como resolvê-las.
P1: o que fazer quando as regras do ESLint e do Prettier entram em conflito?
Sintoma: o ESLint informa que a formatação de uma linha está incorreta, mas, depois que o Prettier a formata, ela volta ao estado anterior.
Solução:
Confirme que eslint-config-prettier está instalado e que prettier aparece por último nos extends da configuração do ESLint:
export default [
...compat.extends('next/core-web-vitals'),
...compat.extends('prettier'), // Deve ficar por último
];
O eslint-config-prettier desativa todas as regras do ESLint que entram em conflito com o Prettier. Assim, o Prettier fica responsável pela formatação e o ESLint pela qualidade do código.
P2: o ESLint exibe o erro “plugin not detected” depois da atualização para o Next.js 15
Sintoma: ao executar pnpm lint, aparece o seguinte erro:
Error: The Next.js plugin was not detected in your ESLint configuration.
Solução:
Isso normalmente acontece porque o formato flat config do ESLint 9 está incorreto. Confira se eslint.config.mjs importa corretamente @next/eslint-plugin-next:
import nextPlugin from '@next/eslint-plugin-next';
export default [
{
plugins: {
'@next/next': nextPlugin,
},
},
];
Se ainda não conseguir resolver, defina temporariamente ESLINT_USE_FLAT_CONFIG=false para voltar ao formato antigo.
P3: como acelerar um hook de pre-commit muito lento?
Sintoma: cada commit leva mais de 10 segundos, prejudicando bastante o ritmo de desenvolvimento.
Solução:
- Confirme que o lint-staged verifica apenas os arquivos em staging; normalmente, isso é automático
- Remova os scripts de teste do pre-commit, pois os testes devem ser executados na etapa de CI
- Se o projeto for grande, considere executar o ESLint apenas nos arquivos
.tse.tsxe usar apenas o Prettier nos demais
P4: os integrantes do time não têm os hooks do Husky instalados
Sintoma: depois de clonar o projeto, um novo integrante faz commits sem acionar o hook de pre-commit.
Solução:
Confirme que package.json contém o script prepare:
{
"scripts": {
"prepare": "husky install"
}
}
Peça ao colega para executar pnpm install uma vez. Os hooks do Husky serão instalados automaticamente.
P5: o Husky não funciona no Windows
Sintoma: para usuários do Windows, o hook de pre-commit não é executado durante o commit.
Solução:
- Confirme que o Git está configurado para usar o Git Bash, e não o CMD
- Verifique as permissões do arquivo
.husky/pre-commite tente adicionar manualmente a permissão de execução:
chmod +x .husky/pre-commit
- Se ainda não funcionar, reinicialize o Husky:
rm -rf .husky
pnpm dlx husky init
Resumo e boas práticas
Levei cerca de meia hora para configurar essa cadeia de ferramentas, mas o valor que ela trouxe para o time é duradouro.
Principais benefícios
- Mais qualidade no código: o ESLint encontra possíveis problemas ainda durante o desenvolvimento e ajuda a evitar incidentes em produção
- Colaboração mais eficiente: a formatação padronizada reduz discussões sem sentido nos PRs e diminui conflitos de merge
- Garantia por automação: o Husky assegura que cada commit siga as regras, sem depender da memória de cada pessoa
Recomendações de boas práticas
- Configure aos poucos: não comece com regras rígidas demais. Use a configuração padrão por algum tempo e faça ajustes gradualmente conforme os problemas aparecerem.
- Chegue a um consenso no time: as opções do Prettier, como aspas simples ou duplas, devem ser decididas em conjunto, e não por uma única pessoa.
- Priorize o desempenho: execute apenas as verificações necessárias no hook de pre-commit e deixe os testes complexos para a CI.
- Atualize regularmente: acompanhe as mudanças de versão do Next.js e do ESLint, principalmente a futura remoção do comando
next lintno Next.js 16.
Próximas ações
Se você ainda não configurou essa cadeia de ferramentas no projeto, recomendo experimentar agora. Siga este artigo passo a passo e tudo ficará pronto em cerca de meia hora.
Depois, compartilhe a configuração com o time para padronizar o ambiente de desenvolvimento.
Por fim, ajuste as regras do Prettier e do ESLint à realidade da equipe. Lembre-se: as ferramentas devem servir às pessoas, e não o contrário.
Minha experiência
Sinceramente, configurar essa cadeia de ferramentas parece trabalhoso no início. Eu mesmo demorei um bom tempo para resolver os problemas da migração para o flat config do ESLint 9. Depois que comecei a usá-la, porém, não quis mais voltar atrás.
Hoje, quando faço um commit, não preciso me preocupar com a formatação nem com a possibilidade de esquecer de executar o lint. O hook de pre-commit verifica tudo automaticamente, e essa tranquilidade é excelente.
A eficiência do PR review do time também melhorou bastante. Antes, as pessoas discutiam no PR se determinado trecho deveria usar aspas simples ou duplas. Isso não acontece mais, porque o Prettier já padronizou tudo. Podemos investir nosso tempo na lógica de negócio e na arquitetura, em vez de discutir detalhes de formatação.
O ganho de eficiência proporcionado por essa automação compensa o tempo necessário para configurá-la.
Espero que este artigo ajude você. Se encontrar algum problema durante a configuração, deixe um comentário e farei o possível para ajudar.
Boa configuração!
15 min de leitura · Publicado em: 6 jan 2026 · Atualizado em: 8 set 2026
Guia completo Next.js
Se você chegou pela busca, o caminho mais rápido é ir para o post anterior ou próximo desta série.
Anterior
Configuração avançada de TypeScript no Next.js: otimize o tsconfig e aumente a segurança de tipos
Aprenda a otimizar o TypeScript no Next.js com modo strict no tsconfig, rotas type-safe e tipagem de variáveis de ambiente para eliminar o uso de any e melhorar a experiência de desenvolvimento.
Parte 17 de 26
Próximo
Error Boundary no Next.js: 5 práticas para lidar com erros em runtime
Aprenda a usar error.tsx, global-error.tsx e reset() no Next.js, tratar erros em Server Components e criar uma recuperação segura sem deixar a página em branco.
Parte 19 de 26



Comentários
Entre com GitHub para comentar