---
title: "Trailing slash no Astro com Cloudflare Pages: always, never e por que vou migrar pro never+file"
description: "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."
published: "2026-05-03"
tags: ["astro", "seo", "cloudflare"]
source: "https://marciotoledo.com/blog/trailing-slash-astro-cloudflare-pages"
---

# 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.

> **WARNING**
>
> Esse comportamento do Cloudflare Pages é **por design** e não tem flag pra desligar. Tem uma feature request aberta na comunidade desde 2023 pedindo a opção, e até hoje não saiu.

## 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.

- Config
- URL final no browser
- Como você escreve o link
- Estrutura no disco
- Comporta no Cloudflare Pages?
---
- `trailingSlash: 'always'` + `format: 'directory'` (default)
- `/blog/`
- `/blog/`
- `/blog/index.html`
- **Sim**, caminho natural do Cloudflare. Sem redirect.
---
- `trailingSlash: 'never'` + `format: 'directory'`
- redireciona pra `/blog/`
- `/blog`
- `/blog/index.html`
- **Não**. Cloudflare força 308. Quebra.
---
- `trailingSlash: 'never'` + `format: 'file'`
- `/blog`
- `/blog`
- `/blog.html`
- **Sim**, Cloudflare acha o `.html` direto. Sem redirect.

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.
1. **Simplicidade visual**: menos caracteres, mais limpo de copiar e colar, mais fácil de ler em listagens.
1. **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' }`.
1. **Sitemap**: a função `getBlogPages()` monta URLs com `/` no fim. Tirar.
1. **`Layout.astro`**: remover a lógica que adiciona `/` em paths internos.
1. **Links internos**: header, footer, nav, links em posts (.md) — tirar a barra final.
1. **Middleware** (`src/middleware.ts`): redirects `/en/links` → `/links/` viram `/en/links` → `/links`.
1. **`_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.

> **TIP**
>
> Se você está começando um projeto agora no Cloudflare Pages, escolha cedo entre `always + directory` ou `never + file`. As duas funcionam. Trocar depois implica revisar links internos, sitemap e configurar redirects 301 pra não perder ranking. Não é difícil, mas é chato.

## 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:**

- `always + directory` → URLs com barra (`/blog/`). Default seguro, zero refactor se você já estava aí.
- `never + file` → URLs sem barra (`/blog`). Estética moderna, elimina a classe de erro do "esqueci a barra no link".

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).

> **NOTE**
>
> Sim, é chato ter que decidir isso por causa do hosting. Mas no fim do dia, o Cloudflare Pages me dá deploy global gratuito, edge functions, image transformations e cache decente. O preço foi escolher entre as duas combinações que ele aceita, e dá pra pagar.

## Agradecimento

Quem me destravou nesse problema foi o [Morris Liu](https://realmorrisliu.com/thoughts/fixing-astro-seo-cloudflare-trailing-slash/), 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

- Astro Documentation. [Configuration Reference: trailingSlash](https://docs.astro.build/en/reference/configuration-reference/)
- Cloudflare Pages Docs. [Redirects](https://developers.cloudflare.com/pages/configuration/redirects/)
- Cloudflare Community. [Disable Non-Trailing Slash 308 Redirect (feature request)](https://community.cloudflare.com/t/cloudflare-pages-disable-non-trailing-slash-308-redirect/316995)
- Morris Liu. [Fixing Astro SEO on Cloudflare Pages: Why trailingSlash Doesn't Work (and What Does)](https://realmorrisliu.com/thoughts/fixing-astro-seo-cloudflare-trailing-slash/)
- GitHub. [Cloudflare adapter strips trailing slash, redirect becomes 404 (#13165)](https://github.com/withastro/astro/issues/13165)
- GitHub. [v5.5.2 trailingSlash setting does not work (#13423)](https://github.com/withastro/astro/issues/13423)
- Zach Leatherman. [Trailing Slashes on URLs: Contentious or Settled?](https://www.zachleat.com/web/trailing-slash/)
- Ahrefs. [What Is A Trailing Slash & When Does It Matter](https://ahrefs.com/blog/trailing-slash/)
- Aurelien Kinet. [How to remove trailing slash in URLs with Astro and Cloudflare](https://medium.com/@aurelienkinet/how-to-remove-trailing-slash-in-urls-with-astro-and-cloudflare-acacde667c96)
- Google Search Central. [Does trailing slashes affect SEO?](https://support.google.com/webmasters/thread/76843139/does-trailing-slashes-affect-seo)
