Here are a few common examples of using the Ghost Content API within an Eleventy project.

Retrieving data from the Content API within an Eleventy project is pretty similar to using the API in a JavaScript application. However there are a couple of conventions and techniques that will make the data easier to access when creating template files. The majority of these examples are intended to be placed in the .eleventy.js file in the root of the project, to find out more on configuring Eleventy refer to their official documentation.

Initialising the Content API

More information on setting up and using the Content API using the JavaScript Client Library can be found in our API documentation

const ghostContentAPI = require("@tryghost/content-api");

const api = new ghostContentAPI({
  url: process.env.GHOST_API_URL,
  key: process.env.GHOST_CONTENT_API_KEY,
  version: "v3"
});

Retrieving posts

This example retrieves posts from the API and adds them as a new collection to Eleventy. The example also performs some sanitisation and extra meta information to each post:

  • Adding tag and author meta information to each post
  • Converting post date to a JavaScript date object for easier manipulation in templates
  • Bring featured posts to the top of the list
config.addCollection("posts", async function(collection) {
  collection = await api.posts
    .browse({
      include: "tags,authors", // Include tags as well as authors
      limit: "all" // Get all posts to generate all content at build time
    })
    .catch(err => {
      console.error(err);
    });

  // Convert publish date into a Date object
  collection.map(post => {
    post.published_at = new Date(post.published_at);
    return post;
  });

  // Bring featured post to the top of the list
  collection.sort((post, nextPost) => nextPost.featured - post.featured);
  return collection;
});

This code fetches all posts because Eleventy creates the HTML files when the site is built and needs access to all the content at this step.

Retrieving posts by tag

You'll often want a page that shows all the posts that are marked with a particular tag. This example creates an Eleventy collection for the tags within a Ghost site, as well as attaching all the posts that are related to that tag:

config.addCollection("tags", async function(collection) {
  collection = await api.tags
    .browse({
      include: "count.posts", // Get the number of posts within a tag
      limit: "all"
    })
    .catch(err => {
      console.error(err);
    });

  // Get all posts with their tags attached
  const posts = await api.posts
    .browse({
      include: "tags,authors",
      limit: "all"
    })
    .catch(err => {
      console.error(err);
    });

  // Attach posts to their respective tags
  collection.map(async tag => {
    const taggedPosts = posts.filter(post => {
      return post.primary_tag && post.primary_tag.slug === tag.slug;
    });

    // Only attach the tagged posts if there are any
    if (taggedPosts.length) tag.posts = taggedPosts;
    return tag;
  });

  return collection;
});

Retrieving site settings

We used this example within our Eleventy Starter, but rather than putting this in the main configuration file it's better to add it to a Data file, which partitions it from other code and allows it to be attached to a global variable like site.

module.exports = async function() {
  const siteData = await api.settings
    .browse({
      include: "icon,url" // Get the site icon and site url
    })
    .catch(err => {
      console.error(err);
    });

  return siteData;
};

Asynchronous data retrieval

All the examples above use asynchronous functions when getting data from the Content API. This is so Eleventy intentionally awaits until the content has come back completely before it starts building out static files.

Next steps

Check out our documentation on the Content API Client Library to see what else is possible, many of the examples there overlap with the examples above. The official Eleventy docs site is very extensive as well if you wish to delve deeper into the API.