Developing Custom Ghost Themes with the Ghost CLI and Handlebars
Learn how to build and test custom Ghost themes locally using the Ghost CLI, Handlebars templates, and a Gulp asset pipeline to avoid production downtime.
10 Jul 2025, 08:56 UTC

The Challenge of Theme Iteration in Ghost
Updating a Ghost theme by manually zipping files and uploading them to a production server is slow and prone to error. When modifying the frontend presentation layer—the HTML, CSS, and JavaScript that users see—you need a local feedback loop that allows you to test Handlebars templates and asset pipelines without risking site downtime. The goal is to establish a local development environment using the Ghost CLI (Command Line Interface) where you can modify theme files and verify changes instantly before deploying to a live environment.Environment Prerequisites
Before starting, ensure your local machine meets these requirements for Ghost version 5.x (or current stable):
- Node.js: The LTS version recommended by the current Ghost release.
- MySQL 8.0: Ghost requires a MySQL database for local data storage.
- Ghost CLI: Installed globally via
npm install -g ghost-cli.
Setting Up the Local Development Instance
To avoid modifying production data, install a local instance of Ghost. Run these commands in a dedicated directory where you have write permissions.
# Create a directory for your Ghost installation
mkdir ghost-dev && cd ghost-dev
# Install Ghost locally (this sets up MySQL and Node automatically)
ghost install local
Risk: Running ghost install local in a directory that already contains a Ghost installation may cause configuration conflicts. Always use a fresh directory for new local instances.
Structuring the Custom Theme
Ghost themes use the Handlebars (.hbs) templating engine. Handlebars allows you to inject dynamic content from the Ghost API into static HTML. Your theme must reside in content/themes/[your-theme-name] and follow a strict directory hierarchy:
| File/Folder | Purpose |
|---|---|
package.json |
Defines theme metadata (name, version, Ghost version requirement). |
default.hbs |
The primary layout wrapper for all pages. |
index.hbs |
The template for the post feed/homepage. |
assets/ |
Contains CSS, JS, and images. |
Implementing a Build Pipeline for Assets
Ghost does not compile CSS or JS natively. To use modern tools like Sass or minify your JavaScript, you should implement a task runner like Gulp. This prevents the production theme from being bloated with uncompressed source files.
Example Gulp configuration for CSS minification:
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const cleanCSS = require('gulp-clean-css');
gulp.task('styles', function() {
return gulp.src('./assets/css/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(cleanCSS())
.pipe(gulp.dest('./assets/built/css'));
});
Run this task locally during development. Ensure your default.hbs links to the /assets/built/css/ directory rather than the raw source files.
Activating and Verifying the Theme
Once your files are in the content/themes/ folder, you must tell Ghost to use that specific theme.
- Log into your local Ghost Admin (usually
http://localhost:2368/ghost). - Navigate to Settings → Design → Change theme.
- Select your custom theme from the list and click Activate.
Verification Steps:
- CLI Check: Run
ghost lsin your terminal to confirm the instance is running and healthy. - DOM Inspection: Right-click your homepage in the browser and select View Page Source. Search for your custom CSS file path to ensure it is loading from the
assets/built/directory. - Template Check: Modify a string in
default.hbsand refresh the page. If the change does not appear, check for Handlebars syntax errors; incorrect tags often fail silently, leaving the page blank or rendering the old cached version.
Deployment and Rollback
To move your theme to production, zip the theme folder (excluding node_modules) and upload it via the Ghost Admin panel.
Rollback Procedure: If the production site breaks after upload, go to Settings → Design and reactivate the previous theme. Because Ghost stores themes as separate folders, activating a previous theme is an instantaneous state change that does not require re-uploading files.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.