Handling Trailing Slashes in Astro Static Sites
/ 3 min read
Table of Contents
Preface
This blog is built using Astro in a private github repo. On every update a Github Action runs the build and rsync’s the static pages to a dead simple shared hosting account I run now for roughly 20 years. In the golden days of blogging I ran PHP+MySQL sites there but nowadays it’s just static sites and some .htaccess
spaghetti. I recently threw this blog into Google Search Console (previously known as Webmaster Tools) and noticed some problems getting the site properly indexed. One issue was the handling of trailing slashes. Here’s the setup I came up with to solve this, let’s hope it plays out nicely with page indexing.
The Challenge
Astro generates static sites by creating directories with index.html
files. For example, a blog post URL like /blog/my-post
is actually served from /blog/my-post/index.html
. By default, this can lead to different versions of the URL being accessible:
/blog/my-post
(clean URL)/blog/my-post/
(directory with trailing slash)/blog/my-post/index.html
(full path)
Having all these versions accessible can cause SEO issues and confusion for users. We need to fix this and serve content properly when accessed without trailing slashes and redirect requests with trailing slashes to their non-trailing slash versions.
The Solution
1. Configure Astro
In your astro.config.ts
or astro.config.mjs
, set the trailingSlash
option to 'never'
:
import { defineConfig } from "astro/config";
export default defineConfig({ trailingSlash: 'never', // ... other config options});
Search all your code for places that builds URLs and check it doesn’t add trailing slashes, I searched for /` and /‘.
2. Configure Apache (.htaccess)
Add these rules to your .htaccess
file:
RewriteEngine On
# Remove trailing slash and redirectRewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_URI} ^(.+)/$ [NC]RewriteRule ^ %1 [R=301,L]
# Handle directory access without trailing slashDirectorySlash OffRewriteCond %{REQUEST_FILENAME} -dRewriteCond %{REQUEST_URI} !/$RewriteCond %{REQUEST_FILENAME}/index.html -fRewriteRule (.*) $1/index.html [L]
The first rule block catches any URL with a trailing slash and redirects it to the non-trailing slash version using a 301 (permanent) redirect.
The second rule block handles the internal rewriting of clean URLs to their corresponding index.html files:
DirectorySlash Off
prevents Apache from automatically adding trailing slashes to directories- The conditions ensure we only rewrite requests that:
- Are for directories
- Don’t end with a slash
- Have an
index.html
file in them
Testing
After implementing these changes, verify that:
- URLs without trailing slashes work correctly
- URLs with trailing slashes redirect to their non-trailing slash versions
- All content is served properly
- No redirect loops occur
Hope that helps!
Does it work? (Update 2025-02-11)
Google Search Console is quite slow in picking up reindexing request, but finally I’m seeing some progress here:

References
- Astro docs for
trailingSlash
: https://docs.astro.build/en/reference/configuration-reference/#trailingslash