Disable public URL for pages

We’ve created a page blueprint blog-category and a corresponding pages section. The pages in that section represent blog categories (selected on blog pages through a pages field). However, those sections don’t have any content on their own and there are no category index pages in the frontend. So we would like for those pages to not be publicly accessible and to show a 404 page when the direct URL for a blog category is accessed.

Is there a simple way to solve this? Or is there a better approach to creating content containers that are used in other pages but aren’t supposed to have their own URL?

This example in the reference has an url: false option in the blueprint, but it doesn’t appear to do anything.

So you are talking about website visitors, not panel users, right?

Visitors could be redirected in your blog-category.php controller to /blog with go() | Kirby CMS (or via Routing | Kirby CMS)

The url option in the blueprint refers to the url option permission in the blueprint itself.

1 Like

Thanks for the suggestion! Yes, I’m talking about the website frontend.

Using a controller was my fallback solution, but it’s not great for a couple of reasons:

  • We don’t want a redirect, but a 404 page.
  • We would need to repeat that redirect logic for every type of category we create, and not every category (or other type of generic content container) can be redirected to something.
  • It feels like a workaround or hack – the system still thinks that an URL for the page exists. For example, the edit form still shows the Open link for the news category – if this leads to a 404 page or redirects to something else, it’s not great UX for editors working with the panel.

Feels like there should be a simpler solution that is better integrated into the panel. How are other people handling those types of content containers that don’t have their own URL?

You can use a route: Routing | Kirby CMS. No need to clutter up the site/controller / templates with this.

Ok, I understand your point and it’s fair.

I think the only built in way in Kirby would be to leave the content container as a draft.
That should trigger a 404. But I’m not sure your site hierarchy/templates allow for that.
As soon as it’s unlisted/listed it’s a page and has a public url.

  • We would need to repeat that redirect logic for every type of category we create, and not every category (or other type of generic content container) can be redirected to something.

You could keep the controller general and always redirect to the parent or home page. But again, I don’t know your whole site.

  • It feels like a workaround or hack – the system still thinks that an URL for the page exists. For example, the edit form still shows the Open link for the news category – if this leads to a 404 page or redirects to something else, it’s not great UX for editors working with the panel.

You can disable/remove the preview button as well.

Do you need the content containers in your full url? Or is it just to structure your site? You could also remove the content container url with a route…

So I would create a route that matches all news category pages (assuming they all live in one dedicated folder so they can match a specific route) and then show the 404 page from that route with something like go('error')?

I think the only built in way in Kirby would be to leave the content container as a draft.
That should trigger a 404. But I’m not sure your site hierarchy/templates allow for that.
As soon as it’s unlisted/listed it’s a page and has a public url.

@stffr I thought about keeping them as drafts, but I think that’s not a scalable solution. This will cause too much hassle to make sure all templates and fields using those categories expect all categories to be in draft status. And it’s not that convenient if you need to edit the content directly without using the panel.

You could keep the controller general and always redirect to the parent or home page. But again, I don’t know your whole site.

Yeah, that would be a workaround. Though redirecting to the homepage and not showing a proper 404 page is an antipattern and not good for SEO. I guess I can manually render the 404 page from the controller, at least I found some forum posts recommending this.

You can disable/remove the preview button as well.

Thanks, I missed that in the documentation, that’s definitely an improvement!


Do you need the content containers in your full url? Or is it just to structure your site? You could also remove the content container url with a route…

I just want to have some pages that store a reusable piece of content, but that don’t have their own page or URL in the frontend. For example, say you want to have Call-To-Action elements on your website that you want to define in one central location and only select which CTA to show on every page. As far as I can tell, the only way to unique refer to such a piece of content is to represent them with pages. But those CTA elements aren’t supposed to have their own URL – I don’t want to have a page /call-to-action/contact-us, I just need that page as a way to store a headline, text and an email address that are gonna be displayed on a bunch of places but can be edited in one place.

This is a very common requirement (at least in our projects), so we’re looking for the recommended approach to do this in Kirby. Feels like if I have to manually add routes and render 404 pages that’s not very close to the intended usage. So I’m wondering how others are approaching this requirement and if there’s an easier solution.

As I wrote above, imo the best way to handle this is a route. You only need one route that catches any categories below a given container

'pattern' => 'blog-category/(:any)'

Sine the blog category pages itself probably shouldn’t be accessible either:

'pattern' => ['blog-category', 'blog-category/(:any)']
2 Likes

Thank you! Alright, so defining a route with that pattern and returning false from the action shows the error page, so looks like a good solution:

[
    'pattern' => 'blog-categories/(:any)',
    'action' => fn () => false,
],

Then I can configure the page blueprint to not show the preview button and use hooks to set those pages to unlisted by default. So this would be the recommended way in Kirby projects to solve the ‘content container’ requirement mentioned above?

Yes, since there is no container concept (yet) but only pages in Kirby, this is the easiest way to go, I think. Manageable from a single place and pretty easy to implement.

There is also this plugin, but it doesn’t take care of the parent, only for the modules (in your case the categories themselves): GitHub - medienbaecker/kirby-modules: Plugin for modular Kirby websites

1 Like

@texnixe Thanks for the replies! I’ll look into that plugin. Allowing pages to more easily function as ‘content containers’ without a public URL and without having to create a parent folder as well would definitely get a +1 from me!

1 Like

@MoritzLost I came across the same issue and opened a feature suggestion: Reusable resources like pages without URL

1 Like

Good idea, upvoted!
For now, we’re disabling the URL for our content containers using the route approach outlined above. But of course that’s a manual step that we have to remember every time we add a blueprint that is not supposed to have public URLs. So having an ‘official’ solution to this would be great.