How to Create Subdirectories in Ghost Using Content Collections

How to Create Subdirectories in Ghost Using Content Collections

Creating subdirectories in Ghost requires the use of content collections and most Ghost sites will eventually need to use them.  Despite their necessity, content collections are fairly hard to understand and the documentation is not particularly clear on exactly when and how to use them.  The configuration itself is done using a YAML file and that configuration has been parked under 'Labs' forever.

We've put together a step-by-step guide to help you create content collections for your Ghost site.

What are content collections in Ghost?

Content collections are just that, posts that you group together for a common purpose. For example, say you wanted to create a group of posts comparing your site to your competitors.  These posts would not show up as regular blog posts, but instead, be linked to the main webpage of your site.

Take the Mindspun footer, for example - the posts under the heading 'Comparisons' are content collections.

Ghost Content Collections

Each column is actually a separate collection, but we'll stick with 'comparisons' as the example for this article.

When should I use content collections in Ghost?

Use content collections in Ghost when:

  1. You want to create a 'subdirectory' of content, i.e. all comparison pages under /compare/.
  2. You want those posts to only show in that subdirectory and not in their default location.

If you are creating a grouping of posts but you still want them to be in their default location, then use taxonomies.

How to use content collections in Ghost:

Here are the steps for creating a content collection in Ghost:

  1. Create an internal tag that will be used to tag posts in your collection.
  2. Add the collection definition to the routes section using routes.yaml.
  3. Tag posts using the internal tag.
  4. Create an 'index' page for the subdirectory.
  5. Use the collection in your theme.

Create an internal tag

Go to the Ghost admin panel and create an internal tag to indicate a post is in the collection.   We'll use #compare to denote our comparison pages.

Ghost admin panel - internal tag

Make sure that the slug begins with the prefix hash- followed by the name.  Ghost should fill this in automatically but it's easy to overwrite.  Note: we won't use the description for this tag or any of the other attributes.

Update routes.yaml

This is the most complicated step of the entire process as it involves editing a configuration file manually and then re-uploading it.

Under the 'Labs' section of the admin panel, click the 'Download current routes.yaml' link.

(Note; The 'Labs' section will only show up if you're the administrator of you Ghost site)

Ghost admin panel - Labs - Routes

Open routes.yaml in a text editor, which should look like this:

routes:
  /:
    template: home
    data: page.home

collections:
  /blog/:
    permalink: /blog/{slug}/
    data: page.home

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

This is the routes configuration that comes with a new Mindspun site - it defines a home page (the / route) and puts all posts under the /blog/ subdirectory by default.  The default routes.yaml file for Ghost looks slightly different.

Modify the file by adding a 'compare' collection similar to the 'blog' collection.  This is a YAML file so formatting is important.  The complete file will look like this:

routes:
  /:
    template: home
    data: page.home

collections:
  /compare/:
    permalink: /compare/{slug}/
    filter: tag:hash-compare
  /blog/:
    permalink: /blog/{slug}/
    data: page.home

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

A couple of things to note:

  • Collections are processed in order so /compare/ must come before /blog/.
  • At this point, there is an entry in the sitemap for the URL for /compare/ but that page doesn't exist.  We'll need to fix this later.

Upload the routes.yaml file back to your site by clicking Upload routes YAML  as shown above.

Tag your content

The last step was the most complicated, this one is the easiest.  Simply add the tag #compare to any post that you want to include in your collection.  You can add additional posts to the collection at any time in the future.

Post in Ghost

Once you've added the tag to at least one post, check to make sure that the page is located under /compare/.  The Post URL in the left-hand sidebar will not show the correct URL - the editor is unaware of route settings.

The above post is now located at /compare/versus-a.

Create an 'index' page for your collection

As noted above, the sitemap contains an entry for /compare/ but that page doesn't exist.  (This is likely a bug in Ghost and may be fixed in future versions)

Create a page whose slug is 'compare' - this should be a true Ghost 'page' instead of a 'post'.

Create a page in Ghost

The contents of the page can be anything you like, but common usage is to create a listing of all pages in the collection (see below).

IMPORTANT: make sure you fill out the meta description for this page.

Use the collection in your Ghost theme

Now that you have a collection, use that collection in your site.  This process can be as simple as putting a link in the navigation but usually you'll want something more, such as:

  • A list of links to all pages in the collection, such as those in the Mindspun footer shown earlier in this article.
  • An Index page of post cards like below.
'Post Cards' in a Ghost Theme

Both of these examples work the same way, getting a list of posts from the API - based on particular criteria - then generating HTML from the result.

(These examples assume that you know how to update your Ghost theme.)

List of post links

Here are the relevant parts of the theme that shows the "Comparisons" column in the footer.

<div>
  <a href="/compare/">Comparisons</a></h5>
  <ul>
    {{#get "posts" limit="all" filter="tag:hash-compare" order="published_at asc"}}
      {{#foreach posts}}
        <li>
          <a href="{{url}}">{{title}}</a>
        </li>
      {{/foreach}}
    {{/get}}
  </ul>
</div>

All styling classes have been removed for clarity.

The Handlebars get helper generates a list of posts filtered by the tag #compare (which has to be specified as hash-compare since the hash tag (#) isn't allowed).

The column title 'Comparisons' links to the index page ensuring the index page has at least one inbound link.

Index page of post cards

This method works just like the above, but with a couple of small tweaks.  As an example, we'll create a template for the 'compare' page.

Create a page template in your theme with the filename page-compare.hbs.

{{!< default}}

<header>
    {{> navbar }}
</header>

<main>
  {{#post}}
    <section>
      <h1>{{title}}</h1>
      {{content}}
    </section>
  {{/post}}

  <section>
    <div>
      {{#get "posts" order="published_at desc"filter="tag:hash-compare"}}
        {{#foreach posts}}
          {{> "post-card"}}
        {{/foreach}}
      {{/get}}
    </div>
  </section>
</main>

{{> footer }}

Again, styling classes are omitted.

Page templates like this one are a little confusing, since it contains both 'post' and 'posts'.  The 'post' helper at the top refers to the page - in this case, the one whose slug is '/compare/'.  The title and content attributes both come from that page.

The 'posts' helper refers to the posts tagged with #compare just like the previous example.  The 'post-card' partial is used to display cards representing each post.

Conclusion


So now you know how to create subdirectories, and when to use them, you can easily improve your site's navigation and UX design. You can also adapt this method for any grouping you want for your site.


If you found this article helpful, there are plenty more tutorials on the Mindspun blog!

Great! Check your inbox and click the link to confirm your subscription.
Please enter a valid email address!