03/05/2026 #astro #seo #cloudflare

Trailing slash no Astro com Cloudflare Pages: always, never e por que vou migrar pro never+file

Cloudflare Pages força um 308 que quebra trailingSlash never no Astro. Tem duas saídas válidas. Saí do never, fui pro always pra resolver o 308, e agora vou de novo pro never+file por gosto e simplicidade. O caminho contado por inteiro.

Trailing slash no Astro com Cloudflare Pages: always, never e por que vou migrar pro never+file

Comecei esse site com trailingSlash: 'never', achando que era a escolha mais moderna (URLs limpas, tipo /blog/post, sem barra no fim). Funcionava bem em dev. Em produção no Cloudflare Pages, o Screaming Frog começou a apontar uma cadeia de redirecionamentos 308 que eu não tinha pedido pra ninguém, e o Search Console reclamou de “Page indexing affected”.

A primeira reação foi voltar pra always: barra em todo lugar, configuração documentada como “default seguro pra Cloudflare”, problema do 308 resolvido. Funcionou.

Depois, conversando sobre o post, caiu a ficha: existe uma terceira combinação (never + file) que também resolve o 308 e mantém a URL sem barra, sem deixar .html aparecendo em lugar nenhum. Esse era exatamente o cenário que eu queria desde o começo, só não tinha conectado os pontos.

Então esse post conta os dois trechos: por que never + directory quebra no Cloudflare, por que always é uma saída sólida, e por que estou migrando pra never + file agora — não por ser “tecnicamente melhor”, mas por preferência estética e por evitar a categoria de erro bobo de indexação que o trailing slash gera.

O que é trailing slash, rapidamente

Trailing slash é a barra no fim da URL. marciotoledo.com/blog/ tem, marciotoledo.com/blog não tem. Pra Google, na raiz do domínio dá no mesmo (marciotoledo.com = marciotoledo.com/), mas em qualquer outra rota são URLs distintas. Se as duas respondem 200, vira conteúdo duplicado.

A convenção antiga (Apache, WordPress, sites estáticos antigos) era usar barra no fim porque a URL representava uma pasta no servidor, e o servidor entregava o index.html daquela pasta. /blog/ = /blog/index.html. Era o mapa direto entre URL e sistema de arquivos.

Sites modernos (Next, Astro, frameworks SPA) tendem a abandonar a barra porque a URL não representa mais pasta nenhuma, é só uma rota lógica. Daí a tentação do never.

Onde o Cloudflare Pages estraga a festa

O Cloudflare Pages tem um comportamento documentado e não desligável: quando alguém acessa /blog, ele procura /blog.html. Se não acha mas encontra /blog/index.html, ele redireciona com 308 permanente pra /blog/.

A documentação do Astro reconhece isso de forma direta: “Trailing slashes on prerendered pages are handled by the hosting platform, and may not respect your chosen configuration.” Ou seja: você pode setar trailingSlash: 'never' no astro.config.mjs, que o Cloudflare ignora e redireciona mesmo assim.

Resultado prático no meu caso: tinha links internos sem barra (/works, /blog, /links/), o Cloudflare redirecionava cada um deles com 308 pra versão com barra, e o Screaming Frog apontava isso como redirect chain ou non-indexable URL. Não é fim do mundo, mas é desperdício de crawl budget e gera ruído nos relatórios de SEO.

As três opções no Astro

O Astro tem trailingSlash: 'always' | 'never' | 'ignore', e o build.format pode ser 'directory' (gera /blog/index.html) ou 'file' (gera /blog.html). A combinação dos dois define o que sai do build.

{% table %}




Coluna importante: “Como você escreve o link”. No never + file, você escreve <a href="/blog/post">, sem barra e sem .html. O .html é detalhe interno do build, nunca aparece na URL pública nem no link que o leitor copia. Foi essa parte que me confundiu inicialmente, achando que format: 'file' deixaria .html exposto.

Por que primeiro fui pro always

Quando vi os 308 do Cloudflare apontados no Screaming Frog, a saída mais rápida foi inverter de never pra always: tudo passa a ter barra, Cloudflare entrega direto, problema resolvido. Dois commits, sitemap regenerado, links internos do Layout.astro ajustados pra garantir o / final.

Funcionou. O Search Console parou de reclamar, o Screaming Frog ficou limpo. Mas a barra em todo lugar nunca me agradou esteticamente.

Por que vou migrar pro never + file

A escolha pelo never + file daqui pra frente é preferência minha, não recomendação técnica universal:

  1. Estética: prefiro /blog/post sobre /blog/post/. URL sem barra é o que Vercel, Netlify e Next.js entregam por default. O resto do mundo moderno caminhou pra esse lado.
  2. Simplicidade visual: menos caracteres, mais limpo de copiar e colar, mais fácil de ler em listagens.
  3. Evitar a categoria do erro: com always, você sempre depende de todos os links internos terminarem com / pra não cair em 308. Um link esquecido sem barra (em post, em footer, em CTA) gera redirect. Com never + file, esse modo de falhar simplesmente não existe.

Não é que never + file seja tecnicamente superior a always + directory. Em SEO, o Google trata as duas como equivalentes. É preferência estética + redução de uma classe de erro chata.

Plano de migração

Pra fechar o post de forma honesta, esse é o plano que vou executar (provavelmente num post de follow-up):

  1. astro.config.mjs: trailingSlash: 'never' e adicionar build: { format: 'file' }.
  2. Sitemap: a função getBlogPages() monta URLs com / no fim. Tirar.
  3. Layout.astro: remover a lógica que adiciona / em paths internos.
  4. Links internos: header, footer, nav, links em posts (.md) — tirar a barra final.
  5. Middleware (src/middleware.ts): redirects /en/links/links/ viram /en/links/links.
  6. _redirects no public/: mapear /blog/post//blog/post 301 pra preservar link juice durante o período em que o Google ainda tem as versões com barra indexadas.

Resumo

No Cloudflare Pages, evite trailingSlash: 'never' com o format: 'directory' default. Essa combinação é a que quebra: o Cloudflare força 308, o Search Console reclama, o Screaming Frog acende alerta. Não é bug do Astro, é design do Cloudflare, e não tem flag pra desligar.

Sobram duas saídas igualmente válidas:

Entre as duas, é gosto e contexto. Não tem ganho de SEO de um sobre o outro. Google trata as duas como válidas desde que sejam consistentes.

Pra Vercel ou Netlify, never funciona normalmente com o default directory — as duas plataformas respeitam a config do Astro sem reescrever rota.

A recomendação geral de SEO segue válida: escolha um padrão e seja consistente. Google não premia nem pune nenhum dos dois, mas pune inconsistência (mesma página acessível com e sem barra, sem canonical).

Agradecimento

Quem me destravou nesse problema foi o Morris Liu, num artigo curto e direto explicando exatamente o porquê do trailingSlash não funcionar como esperado no Cloudflare Pages e a saída via build.format: 'file'. Sem aquele post, eu provavelmente teria ficado preso no always por mais tempo achando que era a única opção. Vale a leitura.


Referências

Você pode me encontrar no: Github, Behance, LinkedIn, YouTube, Instagram, X ou por email [email protected]!

Se eu te ajudei de alguma forma e você quiser retribuir, pode me pagar um café ou ainda usar um dos meus links de indicação para abrir conta em serviços como Asaas, Bunny, Clara, assinar conteúdos gratuitos ou usar serviços recomendados.

© 2002 - 2026 | Marcio Toledo. Todos os direitos reservados. For LLMs