Plugin asset not loaded (403 error)

Dear community,

I’m trying to create my first small Kirby plugin, but I’m running into a problem loading assets on the frontend. I read (and thought I understood) the handling of plugin assets. However, it’s still not working.

The asset is located on the server at site/plugins/pluginname/assets/js/myscript.js
So the url to include in the header should be media/plugins/pluginauthor/pluginname/js/myscript.js and I included it via
<?php echo(js(['media/plugins/pluginauthor/pluginname/js/myscript.js', '@auto'])); ?>

Now when I load the page from the remote webserver, the request for the mentioned asset returns a 403 - forbidden. File permissions for this asset on the remote server are the same as as for standard (non-plugin) assets. Standard assets are being loaded correctly, plugin assets not.

When loading the page locally with the php built-in server (php -S …) the asset is loaded correctly.

So I assume it has to do with the .htaccess file which kicks in on the remote webserver. However, I’m using the default .htaccess from Kirby plainkit and the media folder is not rewritten there or anything. The only line which might be involved is this
RewriteRule ^site/(.*) index.php [L]
However, this shouldn’t have an effect on the file which is accessible by the url media/… and not site/…

Can anyone please help me out?

Best regards,


<?php echo(js(['/media/plugins/pluginauthor/pluginname/js/myscript.js', '@auto'])); ?>

It might be that your hosting needs absolute paths, rather than relative. It might also be a case sensitivity issue, but i think would cause a 404 rather then a 403.

Thanks for the suggestion, but no, this doesn’t change things. I’m also referencing other assets from assets/js/… which are working fine (I just removed them for this ticket for brevity). I tried using an absolute path nevertheless, but without success.

Any other ideas?

I am one step further now.
I can see that Kirby automatically creates a symlink
which points to

When I replace this symlink by the actual file, everything is working as expected and the file is loaded correctly.

So the symlink somehow seems to throw off my webserver and I guess my question boils down to: How do I get my webserver to handle the symlink correctly? Any settings in php.ini I can make?

Any suggestions?

You might have to talk to your webhost. They may have disabled symlinks.

you can try adding

Options +FollowSymLinks

To .htaccess, but if they’ve disabled it, that wont have any affect.

It’s working now, but I needed to edit the symlink manually. It was pointing to
which is not the complete absolute path.
Changing the symlink to be pointing to
did the trick for me.

Is this something, which could be fixed in the Kirby core, where the absolute path for the symlink is determined? $_SERVER[‘DOCUMENT_ROOT’] seems to return the correct directory.

Kirby just uses PHP’s symlink() to create so it should work just fine.

There is a similar thread over here that might help you…

Thanks, I saw this thread, but in my case it doesn’t seem to be an issue of the hosting provider.
Kirby really is using PHP’s symlink(), but still this function must be fed with a target and a link.
My question is whether these parameters could/should be adjusted.

Trying doing in a page template:

<?php var_dump($page->root())?>

It should give the full server path to the page.

And see what it gives you. Im trying to figure out if its just plugin assets guessing wrong or php is set wrong.

That’s the same thing. It outputs

That snippets in the path is tottally weird. are you storing the site in a subfolder? is /html/ the server root?

I am so sorry for causing confusion… The snippets folder mentioned above has absolutely nothing to do with the Kirby snippets folder! I’m talking about an internal test/demo site, where I want to store some Kirby snippets in order to be able to look them up there and combine them for future projects. This demo site lives in a domain, which I call snippets.domain.tld and that’s why I put the files in a subfolder called snippets.
So the output I posted might as well be
The web root is /html/demo/
Maybe it’s better to discuss on this basis in order not to confuse my own snippets folder with the Kirby snippets folder.

So my original question remains: Might my absolute path problem be solvable in the Kirby core?

What do you get if you echo this, let’s say in a Starterkit in the home.php template

realpath() is what Kirby uses to determine the absolute path

<?= realpath(__DIR__ . '/about.php') ?>

Or any other template name that happens to be in your template folder?

It looks as if your paths are truncated, though, for whatever reason.

So as I understand you, your setting up some common code (“snippets” in this case) to share among several other projects from a central point?

Might i suggest using a plugin? A kirby plugin doesnt have to be a plugin, it can just just contain snippets, or blueprints, or templates, or all 3. You can store this in a private Git and install it into kirby with submodules, allowing easy updating. Just a thought.

I did this

and this is the result
Looks like the first part of the path is truncated.

However, if I do this
I get this
which looks OK to me.

Why is Kirby using realpath instead of $_SERVER[‘DOCUMENT_ROOT’]?

I don’t know why, but if dump( $_SERVER[‘DOCUMENT_ROOT’]), it’s an empty string.

This seems to be related to my hosting company after all. The realpath() function, which Kirby is using seems to return some unexpected, i.e. truncated, path, which leads to the symlinks not being followed.

So I am fixing the problem with a custom script right now, which adjusts all symlinks from the plugins folder to have the right (absolute) links. Basically, I’m just adding a prefix, if doesn’t exist, yet.

My hosting company is using symlinks themselves in the directory setup, so I guess this is related to the problem, but I have no idea whether there is a way to mitigate this problem in the Kirby code.

The only chance might be using _SERVER[‘DOCUMENT_ROOT’] instead of realpath() in Kirby. This would solve the problem for me, but I don't know whether _SERVER[‘DOCUMENT_ROOT’] is set consistently correct or whether this might fail for other setups.

@texnixe, I guess realpath() doesn’t return an empty string in your setup?

FWIW, I had this issue locally. I had changed the name of the website in the directory, but the symlink created by Kirby had stayed the same. Once I deleted the /media/plugins directory, and reloaded the site, the symlink rebuilt with the new, correct path and the plugin asset was found again.