Frontend panel bar

I did not add this into suggestions because this is not a core suggestion, but might be a good idea for a plugin.

Panel bar frontend

WordPress have a top bar with shortcuts to the admin. I think it could be nice for Kirby too, as a plugin.

This is my idea of what it could look like (look at the black thing), very basic so far…

Both “Edit page” and “Log out” are shortcuts to the panel, just plain links.

What do you think about a plugin like that?

Exclude / include stuff

I’m thinking of having basic stuff as default and with a config array exclude stuff that is not needed.

Good idea? Or would you want an array of including stuff instead?

Change panel bar

I think it needs to be customizable. The best way I can think of is by having a snippet with a snippet name configured in the config. That way anything can be added to the panel bar.

Now there is a left and a right side on the bar.

Should it be two snippets, one for each side or just one?

1 Like

The main problem I see is that Kirby does not control the styling and layout of the page. It would definitely be required to manually embed the code snippet from the template by using a plugin function to keep it clean.

Yes and I kind of like it that way. WordPress does alot of “magic” stuff which usually end up as bloat.

If we add a function in the template I still think it would be clean, and best of all, it would be there in the code to be manipulated or deleted.

An example

    <?php panelbar::css(); ?>
    <?php panelbar('panelbar-snippet-name'); ?>
  • The panelbar function loads (or class) only when a user is logged in.
  • panelbar::css() loads the CSS from the plugin, only when a user is logged in.
  • panelbar('panelbar-snippet') loads a snippet, only when a user is logged in.


Looks good. But I wouldn’t define the snippets that way, I think this should be a global setting in the config.

So maybe just:

    <?php panelbar::css(); ?>
    <?php panelbar::bar(); ?>

I’ve cobbled together a snippet a while ago, providing me with a deeplink to the corresponding panel-page; ideal for fixing typos etc.; styling via css as a fixed button in the lower right in my case; could be easily extended with additional links/functionalities such as logout and others.

<?php if($user = $site->user()): ?>
  <a href="/panel/#/pages/show/<?php echo $page->uri() ?>/p:1" class="panel">EDIT</a>
<?php endif ?>

@lukasbestle I could not deside if the snippet name should be in the config or in the function. When in the config the template looks cleaner, but when in the template it’s faster to change it when needed.

It will probably be better to have it in the config after all, just because it has to do with the backend.

@franzwalter I also have a snippet of this already running on my site. I prefer to have the full url in the href, just to be safe.

What kind of other options would you like to have in such a bar?
Already working on a plugin.


  • Edit (the current page) ;
  • Show/Hide (the current page) ;
  • Admin (link to dashboard) ;
  • A list of other languages for the page if any (could be useful if there is no direct link in the front end).

Could be hard since this wouldn’t be just a link to an existing page (frontend or panel) anymore, but an action itself

Very first steps:

Implemented in the header snippet:

<?php echo panelbar::show() ?>

  <header class="header cf" role="banner">

Started on a plugin - Did not get far

I also started on a plugin but I got stuck. I did not get far. You are probably much more skilled than me so you are welcome to continue.


<?php echo panelbar::css(); ?>

It complains about that $site is undefined. The same thing with $page.

Plugin class

class panelbar {
    public static function css() {
        if( $site->user() ) {
            $stylesheet = c::get('panelbar.stylesheet');
            return $stylesheet;
    protected function __construct() { }
    private function __clone() { }
    private function __wakeup() { }

My thoughts

  • To be able to control the content with inside the bar with a snippet. Controlling it with an array can be nice at first but sooner or later you might want to control it fully.
  • Set own name for the snippet. This to not collide with other files in the snippets.
  • Use the icons from the panel icon font when possible.
  • Use the same font as the panel. Just to make it feel like we are still in the panel.
  • Use singleton pattern like @lukasbestle wrote, it looks nice.
  • Prefix div classes to prevent collisions, like “pb-”.

That’s because $site and $page are in global scope and not in the method’s scope. You need to use site() and page(). BTW: Why are you passing $page to the method? You are not using the variable.

And also: The constructor and other magic methods must be public.

Implemented a way to add custom elements to the panel bar by passing an array with functions that return the elements content:

echo panelbar::show(array(
  'custom' => function() {
                return '<div>ELEMENT</div>';

or with all default elements:

echo panelbar::show(a::merge(array(
  'custom' => function() {
                return '<div>ELEMENT</div>';
), panelbar::$elements));

Opps, I forgot to remove $page before pasting this here. I just think it’s strange because tpl::load() work with $site and $page without needing to passing them to the method. My own don’t.

I even tried to duplicate tpl::load() function (copied Kirby core code) and just renamed it jens::load(), but the jens-version did not work. Same problem, undefined $site or $page. I guess it’s a dependence I have not taken into account.

It looks like the Kirby style but if this goes directly into the template, doesn’t it get a little messy? Especially the last one?

Maybe as a config instead?

With snippets

c::set('panelbar.include') = array(
    'custom' => 'panel-snippet',
    'custom2' => 'panel-snippet2'

Or this for all elements

c::set('panelbar.include') = array(
    'custom' => 'panel-snippet'
1 Like

Yea, mine def needs some polishing and improvements - thanks for the input :+1:

The Tpl class is part of the Toolkit, which doesn’t know anything about $site and/or $page. Could you please link to the code you are referring to?

What work

Here is the code I tried with in my template:

<?php tpl::load( kirby::instance()->roots()->snippets() . DS . 'test.php', '', ''); ?>


<?php echo $page->title();  ?>

This works which means that it knows about $page in the snippet, even if I don’t send it or make it global.

What don’t work

I do the same thing with duplicated code from toolkit/lib/tpl.php

In a plugin:

class jens extends Silo {

  static public $data = array();

  static public function load($file, $data = array(), $return = true) {
    if(!file_exists($file)) return false;
    extract(array_merge(static::$data, (array)$data));
    $content = ob_get_contents();
    if($return) return $content;
    echo $content;


In the template:

<?php jens::load( kirby::instance()->roots()->snippets() . DS . 'test.php', '', ''); ?>

It makes $page and $site undefined.

I can see you are updating it all the time now. Can you write here when you have a version good enough for testing and feedback? Like a beta version.

I like your prefixing btw.

To add my two cents to the discussion :blush: : While a page edit button makes sense for single pages like a blog articles etc., it is quite useless if pages are made up of different modules. I would therefore prefer edit buttons right where the content that needs to be edited is (like it is implemented in Joomla).

1 Like