Serving an XML Sitemap with Ghost

UPDATE: You can ignore pretty much everything below if you're running Ghost 0.5.7 or greater, which now includes sitemap.xml and robots.txt files out of the box! See the Ghost blog for more details

Ghost is a pretty awesome up-and-coming blogging platform that I’ve been using for the past few months to power this blog. Unfortunately, since it’s still very new, there are some big SEO gaps missing from the core code.

Today, we'll through a quick-and-dirty way to get your Ghost blog serving an XML sitemap file for the various search engines that may want to crawl your site.

I’m super new to node.js and the Ghost framework, so there are probably more robust / more ‘correct’ ways to serve a sitemap, but this solution is quick, easy to implement, and easy to maintain when you update Ghost to later versions.

UPDATE: tstrimple has provided a great dynamic alternative in the comments, see this comment for details

Now then, on with the show:

  1. Generate a site map for your site. I used the XML-Sitemaps.com for this site because the number of pages fits well under their 500-page limit, but feel free to use whatever you’d like.
    Ghost doesn't yet have a built-in way to generate the sitemap yet, though there is an issue in GitHub.
  2. Put the site map in the /content/ folder inside your Ghost installation.
  3. Copy and paste the following code to create the route in Ghost:

    • If you're using Ghost 0.3, paste the code into /core/server.js around line 372, right after the line of code that reads

      ...
      server.get('/', frontend.homepage);
      
      
      // PASTE THE FOLLOWING:
      // Customization for sitemap file.
      server.get(/^\/sitemap.xml\/$/, function (req, res, next) {
          res.download(path.join(__dirname, '/../content/sitemap.xml'));
       });
       // End sitemap customization.
      
    • If you're using Ghost 0.4, paste the code into /core/server/routes/frontend.js around line 20, right after the line of code that reads

      ...
      server.get('/', frontend.homepage);
      
      
      // PASTE THE FOLLOWING:
      // Customization for sitemap file.
      server.get(/^\/sitemap.xml\/$/, function (req, res, next) {
          res.download(path.join(__dirname, '/../../../content/sitemap.xml'));
       });
       // End sitemap customization. 
      
    • If you're using Ghost 0.5, paste the code into /core/server/routes/frontend.js around line 20, right after the line of code that reads

      ...
      router.get('/', frontend.homepage);
      
      
      // PASTE THE FOLLOWING:
      // Customization for sitemap file.
      router.get(/^\/sitemap.xml\/$/, function (req, res, next) {
          res.download(path.join(__dirname, '/../../../content/sitemap.xml'));
       });
       // End sitemap customization. 
      
    • If you use the gzipped version of the site map (i.e. sitemap.xml.gz), remember to change the above code accordingly.

    • UPDATE: Mathachew in the comments indicated that he had to make another addition to the code above
  4. Restart Ghost. Browse to www.YourSite.com/sitemap.xml to confirm the presence of the site map.

There y’go! It’s quick, it’s dirty, and it’s not the most ‘correct’ way to do it, but it’s also the most maintainable method I’ve found because there’s only one modification in one file (until someone builds the functionality into core or a plugin).

As I said, I’m fairly new to node.js and the Ghost app, so if you’ve got a cleaner, simpler way to deliver a sitemap, feel free to post it in the comments :)