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 ...
Prerequisites
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 thenpm
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 https://ghost.org/docs/concepts/config/#mail
------------------------------------------------------------------------------
Ghost was installed successfully! To complete setup of your publication, visit:
http://localhost:2368/ghost/
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.

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:

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'...
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: 127.0.0.1:2368
[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
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.
Conclusion
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!