In this article I will show you one possible workflow for Ghost theme development, to customize your blog by altering Ghost's default theme.

The Ghost CMS is pretty well documented. But I think the documentation for theme development is a bit unstructured and unclear. For Example, LiveReload is not available by just starting Ghost in development mode. You have to put some additional effort into it ...


As always I am using Linux for my tutorials, so watch out for the used directory paths and change them accordingly, so they work with your OS.

For theme development it makes sense to create a local installation of Ghost.

To do so, install a supported version of Node.js and use npm to install Ghost globally on your development machine:

npm install ghost-cli@latest -g

Ghost uses Gulp as its build system, so we have to install Gulp-CLI. Furthermore, it is recommended to use gscan as a tool to check for compatibility issues within your theme. Let's install both:

npm install gulp-cli gscan -g

If the installation process succeeds you can skip the next section.

Used versions for this tutorial:

  • Ghost: 3.13.4
  • Node.Js: 12.16.2
  • NPM: 6.14.4
  • Gulp-CLI: 2.2.0
  • gscan: 3.5.3

First Troubleshooting

Error often occur when performing the simplest tasks. When I tried to install the necessary tools for theme development, I encountered this error:

gyp WARN EACCES user "nobody" does not have permission to access the dev dir "/root/.cache/node-gyp/12.10.0"

There are two ways to resolve this error:

  • I haven't tested it myself, but if you take the message by its word, you could create the user nobody and give it permission to access /root/.cache/node-gyp/12.10.0
  • The approach I took is to change npm’s default directory, which is also recommended by the npm docs.

Changing the default directory of npm also changes some of its behavior when using it. Every Node.Js package you will install globally with your current user, will be available only to this user. Furthermore, you will no longer need the sudo command to install Node.Js packages globally.

To change the default directory of npm, create a new global directory:

$ mkdir ~/.npm-global

Tell npm about this directory:

$ npm config set prefix '~/.npm-global'

Extend your $PATH variable with this directory path, by editing the  ~/.profile of your user. Create the ~/.profile, if it does not exist.

Add or edit the following line:

export PATH=~/.npm-global/bin:$PATH

In the last step we have to tell the current shell about the new $PATH variable:

$ source ~/.profile

For me that did the trick. Retry to install the packages that caused this error. Everything should work now.

Preparing a Local Project

Next we will prepare a local instance of Ghost which we will use, to work on our theme.

A local project can be easily set up:

$ mkdir ghost_local
$ cd ghost_local
$ ghost install local

When the ghost install local command finishes, the output will tell you where you can access your local Ghost instance:

$ ghost install local
✔ Checking system Node.js version
✔ Checking current folder permissions
✔ Checking memory availability
✔ Checking for latest Ghost version
✔ Setting up install directory
✔ Downloading and installing Ghost v3.13.4
✔ Finishing install process
✔ Configuring Ghost
✔ Setting up instance
✔ Starting Ghost

Ghost uses direct mail by default. To set up an alternative email method read our docs at


Ghost was installed successfully! To complete setup of your publication, visit: 


We can see that the instance is hosted at http://localhost:2368/ghost/. Before messing around with the theme, we have to set up the CMS like we would, if this was the production environment. Open http://localhost:2368/ghost/ and follow the provided instructions to set up the administrator user.

As soon as you are greeted by the admin panel, you can already stop the instance.

Ghost CMS admin panel when entering it the first time 

Stop the Ghost instance by running:

$ cd ghost_local
$ ghost stop
✔ Stopping Ghost: ghost-local

You can watch the current state of all of your ghost instances by running the ghost ls command.

Start Developing

In this section I will finally show you how you can start editing the default Ghost theme. First we will install the necessary browser extension to enable LiveReload, so we don't have to manually refresh the page every time we change something about our theme. The ghost process which starts automatically after we instantiated our local ghost project hides its output from us. In the second step we will make this output visible to make debugging easier.

Start by installing the LiveReload extension for your browser. I will use Firefox in this tutorial, but it really shouldn't make a difference for any other browser.

If you use Firefox you can get the LiveReload extension from the official Add-Ons-Page. Somewhere in your browser you should now find this button:

Inactive LiveReload button

Later this will activate the functionality to automatically reload the page as soon as we change our Ghost theme.

You have to know, that a classical Ghost theme can be seen as a Node.Js project by itself. I will use the default "Casper" theme as an example.

From your ghost_local project directory navigate to the Casper theme and run npm install:

# in ghost_local
$ cd current/content/themes/casper
$ npm install

The next and last two steps are to start the Ghost instance in development mode and run the Ghost theme project. Open two terminals.

In the first terminal we run our Casper theme project using the gulp command:

$ cd ghost_local/current/content/themes/casper
$ gulp
[14:03:46] Using gulpfile ~/blog/ghost_local/versions/3.13.4/content/themes/casper/gulpfile.js
[14:03:46] Starting 'default'...
[14:03:46] Starting 'css'...
[14:03:47] Finished 'css' after 519 ms
[14:03:47] Starting 'js'...
[14:03:47] Finished 'js' after 87 ms
[14:03:47] Starting 'serve'...
[14:03:47] Finished 'serve' after 1.36 ms
[14:03:47] Starting 'cssWatcher'...
[14:03:47] Starting 'hbsWatcher'...
Starting the Casper theme project

In the second terminal run Ghost in development mode by entering:

$ cd ghost_local
$ ghost run --development
The `ghost run` command is used by the configured Ghost process manager and for debugging. If you're not running this to debug something, you should run `ghost start` instead.
[2020-04-26 11:49:43] INFO Ghost is running in development...
[2020-04-26 11:49:43] INFO Listening on:
[2020-04-26 11:49:43] INFO Url configured as: http://localhost:2368/
[2020-04-26 11:49:43] INFO Ctrl+C to shut down
[2020-04-26 11:49:43] INFO Ghost boot 1.06s

Starting Ghost in development mode

Open http://localhost:2368/ and activate your LiveReload browser extension:

Everything you edit in ghost_local/current/content/themes/casper will now trigger an automatic reload of your page.

Below you can see the full setup in action:

  • The right side of the screen show the Ghost landing page and activated with LiveReload extension.
  • On the left side you can see the code editor with the opened casper/index.hbs file.
  • Below the editor you can see the two terminals with the running Ghost instance (left) and the running theme project (right).

As soon as I add the <h1> tag to index.hbs and save the file, gulp recognizes the change, rebuilds the project, the LiveReload extension refreshes the page, and we can see the altered theme.

Shipping Your Theme

In the beginning we installed gscan to check our theme for any errors. So lets use it.

Run gscan on your altered "Casper" theme:

$ gscan themes/casper

Checking theme compatibility...

✓ Your theme is compatible with Ghost 3.x

If gscan gives us the green light, it's time to bring out theme into our production environment by creating a ZIP file of it. Creating this ZIP file is fairly easy:

$ cd ghost_local/current/content/themes/casper
$ npm run zip

You will find the ZIP file in the casper/dist/ directory.

Open the admin panel of your production instance, open the designs tab select Upload a theme and upload your prior created ZIP file.

If everything went well, your theme should now be visible in your production environment.


This tutorial showed you how you can use the default "Casper" theme to get started with theme development. Furthermore, you've learned how to scan your theme for errors and ship your developed theme to production.

I hope you enjoyed this tutorial and I will see you in the next one!