Howdy ![]()
I believe this topic has been touched multiple times before, but I don’t think it has ever been resolved clearly or extensively, so I’d like to raise it again from a slightly broader perspective.
1. URL generation vs URL enforcement
At the moment, $page->url() always produces URLs without a trailing slash:
/blog/my-post
There is no configuration option to globally control whether Kirby should generate URLs with or without trailing slashes.
This is where things start to feel awkward:
- Kirby generates URLs without a slash
- users who prefer trailing slashes are expected to enforce them at the server level (e.g.
.htaccess) - this results in internal links that always redirect (200 → 301 → 200)
In my opinion, generating URLs in one format and enforcing another format via redirects is a poor practice, especially when this happens on every internal link.
I am fully aware of server-level enforcement and the official article here:
https://getkirby.com/docs/quicktips/trailing-slash
This is not about how to enforce — it’s about URL generation being configurable in the first place.
2. CMS-level enforcement would also be welcome
Closely related: it would be very nice if Kirby could optionally enforce the chosen URL format (slash / no slash) at the CMS level as well.
I understand the argument that redirects belong to the web server — but when Kirby already defines the canonical shape of URLs internally, having an optional CMS-level enforcement would be a big DX improvement.
3. Canonical links as partial mitigation
Another common workaround is adding a canonical link tag, which does help with SEO duplication to some extent.
However, this leads to another question:
4. Canonical URL generation with current Kirby setup
What is the recommended elegant way to generate canonical URLs in Kirby?
Example:
http://localhost:8000/blog/category:hello-world/?foo=bar
Calling $page->url() in this context returns:
http://localhost:8000/blog
Which is technically correct for the page — but often not what you want as a canonical when params or filters are involved.
Is there a recommended way to generate canonicals that:
- respect the desired trailing-slash convention
- handle params / query strings predictably
- don’t require custom helper functions sprinkled across templates?
5. Kirby’s own website behavior
I also noticed that https://getkirby.com/ itself does not enforce trailing slash rules via redirects, but it does use canonical tags.
Would you be willing to share:
- how canonical URLs are generated internally on the Kirby website?
- whether this is considered the “preferred” approach by the core team?
6. Core concern (the main point)
The biggest missing piece, in my view, is simply this:
There is no way to configure how Kirby generates URLs globally (with or without trailing slashes).
Given that $page->url() is a core primitive used everywhere, this feels like something that should be configurable — especially since overriding it cleanly is currently not possible.
Thanks for reading, and thanks for Kirby in general — this isn’t meant as a complaint, but as a genuine DX and architectural question. I’d love to hear the team’s perspective on whether this is something that could (or should) be addressed at the core level.
![]()