No trailing slash messes up MkDocs relative link
I had to share the blog homepage as ariesta.id/blog/
.
There's an updated config below the post.
Now, I can share it as ariesta.id/blog
(without trailing slash).
Static pages built by MkDocs allow users accessing the path /blog
to be served with the content of /blog/
, but the relative links inside the blog homepage is written like this: 2025/01/04/flask-google-login
. (I set this blog on Coolify, so this maybe a specific behavior, not caused by MkDocs.)
However, when the browser interprets that link, it resolves to /2025/01/04/flask-google-login
, which, if opened, breaks the blog.
There is no problem if users open the blog homepage at /blog/
, since the child path will be interpreted as /blog/2025/01/04/flask-google-login
(the correct slug built by MkDocs).
Luckily, Coolify uses NGINX and I chose to force trailing slash for each path.
rewrite ^([^.]*[^/])$ $1/ permanent;
Source: Bob Monteverde's answer on Stack Overflow.
Update
I'm not sure why, but suddenly the server started redirecting non-trailing slash URLs to something like ariesta.id:3000/blog/
. My stack is Coolify (with Caddy and Traefik), Dockerfile, Nginx, Mkdocs and so on. So maybe that's complicating things. Serves me right for relying on so many technologies to serve a static blog, huh?
So, naturally, I asked DeepSeek-R1 (and subsequently V3, because R1 was overthinking). Here's the new setting:
if (!-d $request_filename) {
rewrite ^([^.]*[^/])$ $scheme://$host$1/ permanent;
}
I don't fully understand it, but let’s try to break it down. First line means "if the requested path is not a directory" (according to V3).
For the second line: rewrites any URLs that don’t end with a /
(that's what the regex means) into the following format.
$scheme://$host$1/
In this context:
- $scheme
is the protocol (e.g., https
),
- $host
is the domain, and
- $1
is the regex match that we want to rewrite, appended with a /
.
Read here to setup MkDocs for blogging.