How to Delete Page When a Subpage Should Be Undeletable?

I’m working on 3 websites, all of which need to have Landing Pages - pages that the clients will be able to add as needed. The Landing Pages on all sites follow the same structure:

  • Mandatory HERO BANNER at the top - must be present on every page, and the client must not be able to delete it
  • Optional INFO SECTIONS - the client should add these when and if needed. Client can add several, or none at all.
  • Optional CONTACT SECTION - which the client may or may not add, but if they do, there can be only one on the page.

I wanted to use @timoetting beautiful Page Builder plugin but there is no way to stop deletion of inserted blocks, so it wouldn’t work for the Hero Banner.

I then tried to implement a Kirby-native solution, building the Landing Page as a one-pager, using the ‘subpage builder’ script shown in the Migration guide. The problem with that, however, is that if we’re using subpages, the client will not be able to delete a Landing Page unless they can also delete the subpages - and that means, once again, that they must be able to delete the Hero Banner. Not OK.

There doesn’t seem to be a way to work with hooks here, either. If we set the Hero Banner blueprint to delete: false (to stop the client from deleting the Hero), then try to delete the page programatically using a hook on page.delete, it will fail, and the Landing page will not delete. There is no way to programatically override a page option set in the blueprint. I’ve put in a feature request for that, but realise there may be many other items on the list that will take priority. I’ve also put in a feature request in the Page Builder repo, asking for Tim to please add ‘min’ options to fieldset blocks.

But, in the meantime, I’m kindly asking for any suggestions that will allow me to achieve this right now, without delaying my projects, or causing me to have to do multiple upgrades later on: is there a way for me to stop the client from deleting the Hero Banner, while still being able to delete the Landing Page?

I just had an idea how this could be achieved with hooks but need to test it first.

Why not do the hero outside of the builder stuff so they can only add and delete content builder modules, but cant ever delete the hero. The worst they can do is mess with the hero’s content. Put the hero in its own tab, and put the builder stuff in another tab.

Personally I have setup two builders on my page, one for different kinds of heros, and another for content blocks.

If you did that, you could atleast a hard code a fall back hero that gets used if the hero builder loop comes back empty.

Same with the contact section. Don’t use builder for it, put that in its own tab with a toggle field to turn front end display on or off.

@texnixe can’t wait to read your suggestion!

@jimbobrjames we can indeed set this up with just tabs and page sections - no builder code necessary at all - but it makes the interface needlessly complex and unintuitive for the user. Right now, we already have a tab for ‘Metadata & SEO’ stuff. If we split the sections into tabs, we’ll need at least 3 more tabs: one for ‘Hero’, one for ‘Contact’ and one for the optional ‘Info Sections’. All of these sections, however, are going to have several call-to-action buttons, which the user can configure ‘globally’, so we’ll also need to setup a ‘Call-to-Action’ tab. So, we’re up to 5 tabs already. On top of that, the interface is now kind of inconsistent, because although all ‘sections’ are the same - they are all just ‘subsections’ of the parent page - in order to manage the Info Sections the user now has to go ‘one level deeper’, compared to the Hero the Contact, which feel as if they are ‘part of the parent’. This is “workable”, but very inelegant, and feels hackish.

At the moment, we have 2 tabs only: one is the SEO tab, and the other is ‘Content’. In the content tab, there are 3 page sections - one for Hero, one for Info Sections and one for Contact - and then a fields section to configure the Call-to-Action buttons. It’s all super intuitive and elegant, precisely as Kirby 3 is supposed to be. The only thing we need to work out is the funky deletion of the Hero Banner…

What is your current structure? You you send me an outline?

Right now, I’ve got a blueprint for the ‘Landing Page’ - the parent page. Then, 3 blueprints for the subpages: ‘Landing Hero’ (Hero Banner section), ‘Landing Info’ (for the Info sections) and ‘Landing Contact’ (for the optional Contact section).

The Landing Page blueprint is currently setup with a custom ‘autobuild’ option, and a hook, which automatically adds a Hero Banner and a Contact Section to the Landing page on creation - the hook is pretty much a copy+paste of the suggested hook in the Migrations Page.

Can I give you more information?

Ok, I did a test (I love tests, it seems). All subpages of a landingpage parent are theoretically deletable (no blueprint setting that prevents that), but a hook prevents that the user can delete the hero (ok, the user can click the delete button, but then is presented with a nice error message that they can only delete the parent page).

'page.delete:before' => function ($page) {
  if($page->intendedTemplate() == 'hero') {
    throw new Exception('You may not delete me, but you can delete my parent, if you want to get rid of this landingpage');

However, when deleting the parent landingpage, the hero is deleted without problems.

This solution might not be ideal, as users may be lured into thinking they can delete the page, but certainly better than nothing. Additionally, you could hide the delete button for the hero page via CSS (at least in connection with this plugin that adds additional classes to the Panel, so you can target specific buttons).


I love you, @texnixe :heart:

Just in case this might be useful for others: it is now currently possible to implement a very elegant workaround with the Panel View Extended plugin. The plugin allows us to hide the Settings menu through a blueprint option, and therefore take away the user’s ability to delete the page, even if the page is still deletable. It also includes other goodies, like the ability to hide a page’s status, too!