Ghost Node Express 4


ghost as an npm module!

Today's adventure: 1] Find a decent node blog. 2] Get it configured on a Heroku's NodeJs engine.

According to the Ghost docs, I just needed to do this..

ghost().then(function (ghostServer) {  
  app.use(ghostServer.config.paths.subdir, ghostServer.rootApp);
  ghostServer.start(app); //'app' is the existing Express app
});

But, this didn't seem glaringly obvious at first. How does this fit in with my existing NodeJs Express 4 app?

Order is Important

It's important that the Ghost server is mounted before your existing Express app. Remember that that app in ghostServer.start(app) should match the name of your Express app. It look's something like this..

var express = require('express'),  
    app = express(),
    ghost = require('ghost'),
    port = process.env.PORT || 4000;

/* mount the ghost app.. */
ghost().then(function (ghostServer) {  
  app.use(ghostServer.config.paths.subdir, ghostServer.rootApp);
  ghostServer.start(app);
});

/* the exising app routes are here.. */
app.get('/', function(req, res){  
    res.send('Hello node express app..');
});

app.get('/*', function(req, res){  
    res.send('Hello node express app not found..');
});

if (!module.parent) {  
  app.listen(port);
  console.log('Express app started on port '+port);
}

What URL Will Ghost Use?

In this case, I simply wanted my Ghost app to live at: http://mydomain.com/blog. This was a matter of setting this URL in the the ghost/config.js file. Find and set the development.url accordingly. FYI, Ghost uses the development config by default, but this can be switched to production by way of Ghost start-up options.

development: {  
        // The url to use when providing links to the site, E.g. in RSS and email.
        // Change this to your Ghost blogs published URL.
        url: 'http://mydomain.com/blog'
        ..     
}

Where Do The Ghost Assets Live?

Out-of-the-box, Ghost puts the blog files in the /content folder. That worked fine for me, but it can be overridden by modifying the development.paths setting in the config.js file.

Data Persistence

When I first deployed Ghost to Heroku, I didn't change the default SQLite database settings:

database: {  
    client: 'sqlite3',
    connection: {
         filename: path.join(__dirname, '/content/data/ghost-dev.db')
    }
 }

That worked fine to get things set-up, but now we need a real datastore that won't be overwritten by subsequent deployments to Heroku. Heroku completely builds the app on each deploy so adding /data to .gitignore won't prevent your persisted data from being wiped out.

I'll go with PostgreSQL since Heroku offers a free add-on, and it's easily configured in Ghost. Once you add the add-on in Heroku you'll get these connection settings:

database: {  
    client: 'pg',
    connection: {
    host: '...',
    user: '...',
    password: '...',
    database: '...',
    port: '5432'
    }
}

For security reasons you'll want to add these connection vars to your Heroku apps Config Variables so that the connection settings are not stored in the Ghost config.js

Move /content & config.js to Deploy-able Folders

I chose to install Ghost as an NPM module locally using NPM install ghost. This local /node_modules folder is also in my .gitignore so that all the node modules are not continually re-deployed. That's what package.json is for! Here it is added to my package.json so that ghost gets installed by NPM when I deploy to Heroku...

"dependencies": {  
    "ghost": "0.5.2",
    ..
}

To repeat, NPM will install Ghost in /node_modules/ghost which is not deployed since it's in my .gitignore. So the /content dir from Ghost must be copied to the root folder that will be deployed. Also copy the config.js with the appropriate database and path settings as detailed above. Then, tell Ghost to use this config.js, in the Nodejs server.js file:

var express = require('express'),  
    app = express(),
    ghost = require('ghost'),
    path = require('path'),
    port = process.env.PORT || 4000;

ghost({  
  config: path.join(__dirname, 'config.js')
  }).then(function (ghostServer) {
      app.use(ghostServer.config.paths.subdir, ghostServer.rootApp);
      ghostServer.start(app);
  });

/* the exising app routes are here.. */
app.get('/', function(req, res){  
    res.send('Hello node express app..');
});

if (!module.parent) {  
  app.listen(port);
  console.log('Express app started on port '+port);
}

The (somewhat) final project structure looks like this...

\ghost-blog
   \content
   - config.js
   - package.json
   - server.js
   - Procfile

You'll also want to store assets like images and videos on a CDN since they'll also be overwritten by future deployments.

Viola! And, here you are. Reading the Codeply blog powered by Ghost, Node, Express and Heroku. Let's call it the GNEH stack.