Astro has two settings that decide whether your URLs end in a slash. build.format controls the files a static build writes: 'directory' (the default) writes about/index.html, served as /about/, and 'file' writes about.html, served as /about. trailingSlash ('ignore' by default, or 'always' or 'never') controls which form the dev server and on-demand routes accept. For most static sites, the safest pairing is build.format: 'directory' with trailingSlash: 'always'.
Key Takeaways
build.formatdecides the static output; the host decides what URL serves it.trailingSlashenforces one form in dev and on demand, so mistakes show up before production.'directory'+'always'matches how almost every static host serves folders.- Make internal links, canonicals and the sitemap all use the same form.
What each setting does
// astro.config.mjs
export default defineConfig({
trailingSlash: 'always', // 'always' | 'never' | 'ignore'
build: { format: 'directory' }, // 'directory' | 'file' | 'preserve'
});
build.format
| Value | src/pages/about.astro builds to |
Natural URL |
|---|---|---|
'directory' (default) |
dist/about/index.html |
/about/ |
'file' |
dist/about.html |
/about |
'preserve' |
Mirrors your source: about.astro → about.html, about/index.astro → about/index.html |
Depends on the file |
Most static hosts serve about/index.html at /about/ and redirect /about to it. Hosts differ on about.html: some serve it at /about, some need “pretty URLs” enabled.
trailingSlash
'ignore'(default): the dev server accepts both/aboutand/about/.'always': only/about/matches;/aboutgets a 404 in dev (or a redirect on some adapters).'never': only/aboutmatches.
It also changes how Astro.url and the sitemap format URLs, and on-demand routes enforce it in production.
Why it matters
Search engines treat /about and /about/ as two URLs. If both return 200 with the same content, you’ve split signals between duplicates. If internal links use one form and the host serves the other, every click goes through a redirect.
The fix is consistency: one form for files, dev server, links, canonical tags and sitemap.
Recommended combinations
Most static sites: 'directory' + 'always'.
export default defineConfig({
trailingSlash: 'always',
build: { format: 'directory' },
});
Hosts serve folders at the slash URL, and 'always' makes the dev server reject links you wrote without a slash, so you catch them early.
You prefer no slashes: 'file' + 'never', on a host that serves about.html at /about. Cloudflare Pages does this by default; on other hosts it can depend on a setting (Netlify’s pretty URLs, Vercel’s cleanUrls), so check before switching.
Migrating an existing site: match whatever the old site used, so you don’t need redirects for every URL.
Make links match
With 'always', write internal links with the slash:
<a href="/blog/">Blog</a>
<a href={`/blog/${post.id}/`}>{post.data.title}</a>
Build canonicals from Astro.url.pathname, which follows the setting:
<link rel="canonical" href={new URL(Astro.url.pathname, Astro.site)} />
The canonical URLs tip covers that in more detail.
Endpoints and files
URLs with a file extension, like /rss.xml or /robots.txt, are never given a trailing slash, whatever the setting. You don’t need to special-case them.
Checking a live site
curl -sI https://www.example.com/about | head -3
curl -sI https://www.example.com/about/ | head -3
One should return 200 and the other a 301 or 308 to it. If both return 200, your canonical tag is doing all the work, which is acceptable but weaker than a redirect.
For the full routing picture, see the Astro routing guide. The Astro configuration docs show where these options sit in a theme’s config, and every value is listed in the configuration reference.
FAQ
What is the default trailingSlash in Astro?
'ignore', which accepts URLs with or without a trailing slash in development. The default build.format is 'directory'.
Should Astro URLs have a trailing slash?
Either works for SEO if you’re consistent. With the default 'directory' format, trailing slashes match how hosts serve your files, so trailingSlash: 'always' is the lower-friction choice.