Martin Carlin

This post is a follow-on from How to Use Capistrano 3 for Ghost Theme Deployment, so please read that first.

The aim of this post is to introduce SASS to the workflow instead of vanilla CSS.

I followed this excellent blog post here but I will describe what specific changes I made to my local project.

First off, as the post points out, you need to install the SASS gem both to your local machine and your production server.

gem install sass

When installing on production, the main thing to watch out for is to install it as the deploy_user and not root.

The problem I had is that my specific deploy user didn't have permission to write to the location where rbenv installs its gems so if you are using rbenv or rvm then that is something to watch out for.

I simply did

sudo gem install sass

and that solved the problem.

The next thing was to follow the steps from the blog post to create the .scss files and also untracking the existing screen.css and deleting the local copy once we have everything we need in the sass stylesheets.

The problem we will have now is that git doesn't track empty directories so we will need to update the deploy.rb to create the assets/css directory when we deploy.

To build it locally if you are doing local development you can do the following from your theme root directory:

sass assets/sass/input.scss:assets/css/screen.css --style compressed

You can add the --watch option to continually monitor for changes.

We then need to update the .gitignore file so that .css and .map files can't accidentally be committed:


The last thing to do is then update the execute statements in deploy.rb

# symlink REVISION file
execute 'sudo ln -sf /var/www/path_to_ghost_install/content/themes/theme_name/current/REVISION /var/www/path_to_ghost_install/content/themes/theme_name/REVISION'
 # create css directory for our compiled stylesheet to go in
execute 'sudo mkdir /var/www/path_to_ghost_install/content/themes/theme_name/current/assets/css'
# symlink all the files from the current release to the theme root
execute 'sudo ln -sf /var/www/path_to_ghost_install/content/themes/theme_name/current/* /var/www/path_to_ghost_install/content/themes/theme_name'
# chown everything to be owned by our ghost user and not the deploy user
execute 'sudo chown -R ghost_user:ghost_user /var/www/path_to_ghost_install/content/themes/theme_name'
# compile the css stylesheet from our sass files
execute 'sudo sass /var/www/path_to_ghost_install/content/themes/theme_name/current/assets/sass/input.scss:/var/www/path_to_ghost_install/content/themes/theme_name/current/assets/css/screen.css --style compressed'
# restart the forever process
execute 'sudo forever restart /var/www/path_to_ghost_install/index.js'

Don't forget to push your changes to your git repo before deploying.

As you may know, I am using the Bulma flexbox css framework for my personal Ghost theme.

As part of the framework, there are notifications and the framework also provides the ability to include a delete button for the notification, but it is completely static and doesn't do anything - yet.

I also had to add some CSS to fix the button for the notification:

.notification > button.delete {
  border: none;

which is strange as it seems fine on the Bulma site.

In addition to this, I added a new modifier class in the naming convention of the existing classes:

.is-hidden {
  display: none;

This class is then applied to the notification when the delete button is clicked.

To achieve that in jQuery, you can simply use this:

$(document).on('click', '.notification > button.delete', function() {
    return false;

You could optionally remove the element from the DOM completely by chaining the .remove() method, e.g.


See the Pen Bulma CSS Framework - Add Functionality to Dismiss Notifications by Martin Carlin (@martincarlin87) on CodePen.

To install a theme on Ghost, it's easy enough to do so from a git repo by cd-ing to the content directory and doing:

git clone repo_url.git
// change permissions, restart ghost etc.

What if there was another way where you didn't have to manually ssh to the (production) server every time there was an update?

This is something I wanted to do whilst developing my own personal Ghost theme - initially I had a local setup with Vagrant and VirtualBox but the time came when I wanted to actually deploy.

The problems I faced when trying to configure Capistrano were out-of-date blog posts that were written about Capistrano 2, or weren't quite suitable as they were geared towards the deployment of full projects rather than a single directory buried within the bowels of an existing app, which admittedly, is the main use case for Capistrano.

To begin, you need to cd to the directory that contains your theme on your local machine.

cd theme_directory

Then, we need to install the Capistrano gem, so you will need Ruby installed, which is probably the case if you're on Mac OS X.

gem install capistrano

Once the gem is installed, we need to Capify our project.

cap install

This sets up all the files that Capistrano needs in order to function.

Now we need to edit the config/deploy.rb file:

# config valid only for current version of Capistrano
lock '3.4.0'

set :application, 'theme_name'
set :repo_url, 'repo_url.git'

set :deploy_to, '/var/www/path_to_ghost_install/content/themes/theme_name'

set :user, 'deploy_user'

namespace :deploy do
  desc 'Restart application'
  task :restart do
    on roles(:web), in: :sequence, wait: 5 do 

      # here we are setting up the symlinks to point from the current release directory to the top level of the theme directory
      execute 'sudo ln -sf /var/www/path_to_ghost_install/content/themes/theme_name/current/REVISION /var/www/path_to_ghost_install/content/themes/theme_name/REVISION'
      execute 'sudo ln -sf /var/www/path_to_ghost_install/content/themes/theme_name/current/* /var/www/path_to_ghost_install/content/themes/theme_name'
      execute 'sudo chown -R ghost_user:ghost_user /var/www/path_to_ghost_install/content/themes/theme_name'
      # restart the forever process (or pm2, ghost service etc.)
      execute 'sudo forever restart /var/www/path_to_ghost_install/index.js'

  after :publishing, 'deploy:restart'

Once that's done, edit the config/deploy/production.rb file with the following:

server 'your_server_url', user: 'deploy_user', roles: %w{web app}

Finally, from your project directory, run

cap production deploy

To enable more environments like staging, just edit the staging.rb file as you did with production.

All the output can be pretty off-putting, but don't worry, if configured properly then your theme should deploy without any hitches.

If you encounter any issues, you can re-run the command w0th the --trace option (cap production deploy --trace).

Some things to watch out for is to make sure that the deploy_user you are using is added to the /etc/sudoers file and has shell access. I also highly recommend you setup ssh keys to make things much, much easier.

If you are not familiar with Capistrano, the current directory is a symlink to the latest release in the releases directory which also contains the last x number of releases (the last five are kept by default, including the most recent but this can be changed in your deploy.rb file.