Dynamic panel stylesheet

I try to add some custom styles in the panel dynamically through PHP depending on some conditions.
I create a plugin for that because once I will make it work, I want to go futher by adding more options and conditions and maybe share it.

Actually the first PoC I try to do is just add a custom stylesheet to the panel by changing the body color and background color. But even if the value have changed (I can see it by looking for the custom route /panel-color.css), the stylesheet remain not loaded in the panel.

Here my plugin files that I use on the starterkit:


return [
    'debug' => true,
    'panel' => [
        'css' => 'panel-color.css'


Kirby::plugin('yoanmalie/panel-color', [
    'routes' => [
            'pattern' => 'panel-color.css',
            'action'  => function () {
                return new Response(panelStyle(), 'text/css');

function panelStyle() {
    // Path of the CSS file
    $path = "/assets/css/panel-color.css";

    // Default colors
    $colorDefaultBackground = "red";
    $colorDefault = "blue";

    // Set the choosen colors
    // @TODO add conditions, options, etc.
    // Make it default for now.
    $colorBackground = $colorDefaultBackground;
    $color = $colorDefault;

    // Patterns replacement
    $patterns = [
        '{{ bg-color }}',
        '{{ color }}',

    // Colors list
    $colors = [

    // CSS file to fetch
    $css = file_get_contents(__DIR__ . $path);

    return str_replace($patterns, $colors, $css);


body {
    background-color: {{ bg-color }};
    color: {{ color }};

What I am missing here?
Also, is there a better (and flexible) way to do this than my current code?


This is the method that calls the custom Panel css file:

    public static function customCss(App $kirby)
        if ($css = $kirby->option('panel.css')) {
            $asset = asset($css);

            if ($asset->exists() === true) {
                return $asset->url() . '?' . $asset->modified();

        return false;

This doesn’t work with a path though.

If I understand, by using this method my CSS file have to be in the ./assets/css/ path?
This only just return the file URL, and I have to use it with the route method?

Also, do you think it’s a good idea to enhance this customCss function to accept custom path? I can create an issue in the idea repo.

Well, I don’t think you can replace the real file with a path, because if you look further, $asset->exists() actually checks if the file exists in the file system:

 public function exists(): bool
        return file_exists($this->root()) === true;

Sorry I don’t get the point, and my dev skill are basic.

What can I do to make this work?

I don’t know. What I tried to say was that according to my understanding, it doesn’t work like this and that you need a file at the location you are defining in the config.