Extending Ghost with apps

· Code ·

This blog is on Ghost, I'm in the process of moving the Flybase Blog to Ghost.

It's great, and works well.

But, I wanted to expand it a bit.

So I looked at using front matter, which is a term used in Jekyll and other blog engines for a piece of yaml content at the front of a post usually separated by +++ or ---.

Here's an example of front matter:

blurb: 'Awesome Data'  
link: 'http://google.ca'  

# My Blog Post

Front matter is awesome  

Now, in my post.hbs file, I can add code like this:

{{#if data.link}}
    <a href="{{data.link}}">{{title}}</a>


And it will use data as the object referring to any front matter and let me format it as needed.

I wanted to do this, and I found an old module that was set up for it, but had a lot of issues as it was over 2 years old so I made my own based on it's idea.

You can see the repo here.

Adding the app to your ghost blog is fairly simple.

  1. Download the repo
  2. Copy the folder: ghost-app-frontmatter to your Ghost apps folder: content/apps/ghost-app-frontmatter
  3. Update your Ghost blog's activeApps to include the app: "key":"activeApps","value":"["ghost-app-frontmatter"]"

Step 3 is the trickiest, you have to open the database for your Ghost blog and go to the settings table, then find the record with the key activeApps and add "ghost-app-frontmatter" inside the [] braces. This is an array, so adding other apps just means adding the name to this record.

Now, when you start your blog up, you'll have front matter.

So a word about Heroku

If you use this on Heroku, with postgresql, then you have to add one extra step.

You see when you add apps to activeApps then on startup, it will handle installing any packages used by that app and then add it to the installedApps record inside settings.

That's fine, but...

When you push an update to heroku, it will destroy the current file systems and reinstall it all, except since Ghost sees installedApps containing your app...


You got it!

The app will break without it's dependencies, so what's the work around?

The are two really:

  1. Move off heroku (really don't, it's great for this).
  2. Set up a postinstall action to clean out the installApps record before it starts up.

I went with number 2, and set a postinstall action inside my package.json:

"scripts": {
  "postinstall": "NODE_ENV=production node cleanup.js",
  "start": "heroku-node-settings server.js"

Then I added a file called cleanup.js:

var isProduction = process.env.NODE_ENV === 'production';  
var knex = require('knex');  
var path = require("path");

if( !isProduction ){  
    console.log('loading local env');
    var knex = require('knex')({
        dialect: 'sqlite3',
        connection: {
            filename: path.join(__dirname, 'ghost-app/content/data/ghost-dev.db')
        useNullAsDefault: true
    var pg = require('pg');
    pg.defaults.ssl = true;
    var knex = require('knex')({
        client: 'pg',
        connection: process.env.DATABASE_URL,
        useNullAsDefault: true
knex('settings').where({key: 'installedApps'}).update({value: "[]"}).then (function (count) {  
    console.log( count );
}).finally(function () {

This file simply connects to the postgresql database, updates the installedApps record to have a value of [] and exits.

Then when the app starts up, it will run that step, then re-install the apps from the apps folder.

Update: this originally used straight postgres queries to update, but since you could use postgres or sqlite (local or production), I updated it to use knex properly instead.

Finishing up

This step may make it more complicated, but in the end, you've got an addon that makes your ghost blog infinitely customizable, letting you add whatever you want to the front matter and just adding it to your database.

Think of it like the custom fields in Wordpress.

About the Author: Roger Stringer

It's all about finding that Work-Life Balance.

I spend most of my time solving problems for people, and otherwise occupying myself with being a dad, cooking, coding, speaking, learning, writing, reading, and the overall pursuit of life. I live in Penticton, BC.

Learn More
Roger Stringer
  • LinkedIn
  • Reddit
  • Google+
  • Pinterest
  • Pocket
Comments powered by Disqus