Offline use of Kirby / Bash script to start localhost

At the moment I’m working on a private tool for a client, based on Kirby, to create different presentations (with animations/videos/images). Presentations should be available both online (with a secret link and/or password) and offline. Here I have two options in mind: first, using a custom statify script to get plain HTML files. The problem is that new slides are called by AJAX (to have a smooth transition), and I also don’t want the whole structure (there is a “media gallery” built in, as well as all other presentations) to be exported each time (the tool will hold about 200 projects with multiple images and videos as a “database”, for easy reusing in presentations).

The other option which came to my mind was to use a bash script, and export assets, the kirby folder and a custom content folder with the presentation included. The bash script should then start a localhost and open the website in the browser. As I have absolutely no experiences with (custom) bash scripts, I wonder if this would be possible? Maybe some of you have experience with this?

The offline presentations just have to work on Mac OS X – and as far as I know, there is an prebuilt apache/php installation coming with OS X, right? (MAMP user, so no experiences with the console in this case)

Would be great to hear some insights and/or hints. Thank you all!

This script should work:

# Make sure we are in the directory of this script
cd "$(dirname $0)"

# Open in browser
# Done first so that we can run the PHP server in the foreground afterwards
sleep 1 && open http://localhost:3000 &

# Run PHP server in the background
php -S localhost:3000

You need to place this script in the root directory of your Kirby site and make it executable with chmod +x start-server.

1 Like

Wow, that was fast, thanks dude!

Can I also make it executable via PHP and do shell_exec("chmod +x start-server")? So that everything happens in the built process (= client clicks a button, everything is generated and packed as zip file with included executable file, so that the client just has to double-click the file and is ready-to-go)?

Thanks for your fast help!

You only have to make it executable once and it can then be opened any number of times. So you could place it into the repository if you use one. Git saves the permissions. :wink:

Okay, I see! Perfect, thank you so much!

Oh, what comes to my mind: If you want it to be double-clickable, you should use the following code to make sure it runs with bash:


# Make sure we are in the directory of this script
cd "$(dirname $0)"

# Open in browser
# Done first so that we can run the PHP server in the foreground afterwards
sleep 1 && open http://localhost:3000 &

# Run PHP server in the background
php -S localhost:3000
1 Like

Okay – works basically as expected, only problem is that the change of directory seems to have problems. It is pointing to /, where everything works, but of course that is not what I wanted to achieve :smiley:

When I do an cd "$(dirname $0)" directly in the Terminal, I get the following return:

dirname: illegal option -- z
usage: dirname path

Only thing which is not working, localhost and opening everything as expected. Now I just hope that Kirby will work inside… in addition to the script, I plan to export an .app with the help of appify, so that the client has just one file left which holds everything else. App is already working, only problem is the directory change – but I guess this shouldn’t be a big problem…

Yes, that doesn’t work on the terminal, only inside the script.

Does the script work when used outside of the app you generated?

No, even then it just searches for files in /. The only problem is finding the right directory, no matter in which environment i launch the script (app/terminal/script).

What if you replace the cd in the first line with an echo? This won’t make it work, but it will output what it thinks its current directory is.

This outputs the location of the script itself, together with it’s filename.


I tried setting the document root with php -S localhost:3000 -t "$(dirname $0)", but still no change – the script is still pointing to the root folder /.

Also tried it with turned-off MAMP, and on a separate account with no MAMP access, but still no change. I’m afraid I don’t have access to another separate Mac… using OS X 10.11, if this is important.

Okay, once again tested – I recognized that the php process was still running, thus it didn’t point to the right location. After deactivating MAMP and stopping the process the original script works as expected – server is closing when the terminal is closed. Perfect, thank you!

1 Like

After few months of sleeping this project is back again… I stumbled upon another issue when working with this script: I want the client to be able to download a .tar file, so I create an archive with the following code:

$tar = new PharData('my/destination/folder');

The thing is that the executable file loses its rights after added to the archive (or after extracting the archive, I don’t really know…). Is there a way to make it executable again? I tried the following without success:

$directory = 'phar:///root/to/my/destination/folder/exectuable-file';
$command = 'chmod +x "' . $directory . '"'

Files inside Phar archives can’t be accessed from the outside world, only by PHP itself. So you can’t make files inside a Phar archive executable using a shell command.

To have an executable Phar, you need to create a full-blown Phar instead of a PharData. Full Phar archives can have a so-called “stub”, which is a PHP file that will get executed if the Phar is executed. You can basically rewrite your shell-script in PHP and can then use it as a stub.

After you have done that, you can start the webserver by using php my.phar.

Edit: I don’t know whether you can actually run the PHP dev server inside a Phar. So maybe instead of creating a Phar, create a normal tar archive and let the client extract that manually.

Okay, thank you! I will have a look at that one…

Another issue i just found out – somehow, there’s some weird miss-routing or something, I can’t access any URL via AJAX, there is always 404 returned. Direct access in the browser is working perfectly. I am using PJAX here, and VideoJS for, well, videos, which is also not working.

Those issues only appear when used “inside” this script.

I also tried disabling rewriting in config, or anything else – but no chance :frowning:

That’s maybe just the PHP dev server. It has a few quirks. :slight_smile:

Do I have any chance to change this? Setting up another version or anything else? My problem is that if this doesn’t work I have to look for a complete different solution, since the tool/site is heavily based on those things. I just really need some offline version of it, no matter how…

The PHP + executable script for Mac approach you took is nice but I find it a bit brittle.

Perhaps you could plug in StaticBuilder to build the offline version? If your templates already build a full presentation as a single HTML page, and you need to export that HTML + the relevant CSS, JS and images, I think it already has the necessary tools.

At the moment, I’m not building one single html; as written above I use ajax a lot, and that’s not possible when local html files (at least not with Chrome and Safari, in Firefox it used to work, but I don’t know about the latest versions).

But yes, as you said, the approach seems nicer than it actually is – too many little problems – I might go with the static builder. But first, I have to rewrite my templates… :wink:

Just a short question, I will look it up later by myself, but maybe you can give me some insights on this: when I’m following this plan and have one big HTML file, my images remain in different folders, not directly related to this page. Will they be exported as well? Or do I have to do that on my own? I don’t want all files from the content folder to be exported, only the ones included in the HTML, since all would be about ~5GB with a lot more to come (lots of videos and HD rendering stuff). Is this already possible with your script?