How to: Integrate Contentful with DADI

Contentful is a hosted API solution which offers a fast and slick way to create an API-first product. The icing on the cake is a flexible and powerful interface that you do not have to self-host.

Contentful is a hosted API solution which offers a fast and slick way to create an API-first product. The icing on the cake is a flexible and powerful interface that you do not have to self-host.

At DADI, we’re aiming at a slightly different use-case, but the two projects share similar goals and there is nothing to stop you mix-and-matching, especially if you don’t want the hassle of hosting your own API and database.

To show how easy it is to integrate DADI products with other solutions, we have created a sample project where you can use DADI Web with Contentful’s API service. It makes use of a new restapi datasource type we’ll be launching with Web soon.

This tutorial assumes you have installed DADI Web already, but if you haven’t, you might find this post useful.

🔗Generate an API key

After you have signed up for Contentful, you’ll need to generate an API key to allow DADI Web to communicate with the service.

You can do that by visiting Space settings > API Keys and clicking Add API key.

This will generate the info you need. Name the API key DADI Web, so future you knows what it’s for.


You should also make a note of the values for Space ID and Content Delivery API - access token. We’ll make use of these in the next step.

🔗Configure Web

New in Web 6.0 is the ability to add configurations for multiple APIs in your main config.json file.

      "api": {
        "contentful": {
          "type": "restapi",
          "provider": {
            "contentful": {
              "": {
                "__domain": {
                  "auth": {
                    "qs": {"access_token": "[0]"}
                "spaces/YOUR_SPACE_KEY/{endpoint}": {
                  "__path": {
                    "alias": "__default"
          "auth": {
            "qs": {
              "access_token": "YOUR_API_KEY"

Replace YOUR_SPACE_KEY and YOUR_API_KEY with the values from Contentful.

*Note: It’s not best practice to store these keys in a GitHub repository, even though these are read-only keys.*

🔗Create a datasource

We’re going to assume you’re creating a blog-like site for the purposes of this article, however the process will be pretty similar for any other type.

In Contentful we have a Content Type of Post. Once we have filtered view for that content we can grab the contentTypeId in the url, which we’ll use asYOUR_CONTENT_KEY.

Filtered content view in the Contentful interfaceFiltered content view in the Contentful interface

Next, we can create the datasource in DADI Web:


      "datasource": {
        "key": "posts",
        "source": {
          "api": "contentful",
          "endpoint": "entries"
        "query": {
          "content_type": "YOUR_CONTENT_KEY",
          "limit": 10
        "requestParams": [
            "param": "slug",
            "field": "fields.slug",
            "target": "query"
            "param": "skip",
            "field": "skip",
            "target": "query"

You can see we also have some requestParams which will help us paginate the data and create individual pages for our posts later.

Anything in query is sent directly to the Contenful API - review their documentation to choose what you need.

🔗Resolving links

Contentful has a concept called Links which are ways of referencing content from other entities, for example the author name on a post. This is an important concept, because it means you can update the author name (for example), without having to update each post individually.

As an aside, in DADI API we resolve these connections automatically for you — a concept we call composition which acts on reference fields.

Luckily Contentful have an NPM package called contentful-resolve-response which can help us out. We can combine this with an Event in DADI Web:


    const resolveResponse = require('contentful-resolve-response')

    const Event = function(req, res, data, callback) {
      data.postsMeta = {
        skip: data.posts.skip,
        limit: data.posts.limit
      data.posts = resolveResponse(data.posts)

      // Fin

    module.exports = function(req, res, data, callback) {
      return new Event(req, res, data, callback)

We’ve also created a postsMeta object which we’ll use later for pagination.

🔗Create a page

Now we have the datasource we can create a page in Web, attach the datasource and event, and render out the data.

We’ll also setup a route so we can view individual post pages. The second route has an optional slug parameter, which is used by in the requestParams of our /workspace/datasources/posts.js datasource to filter posts.


      "page": {
        "name": "index"
      "events": [
      "datasources": [
      "routes": [
          "path": "/"
          "path": "/post/:slug?"

🔗Write a template

We’re modifying the boilerplate Web templates here to give the bare minimum to make a viewable page. We already have some CSS and header and footer partials in place, but obviously you’re free to bring your own front-end code and template language too!



    ${ => `
          <h2><a href="/post/${i.fields.slug}">${i.fields.title}</a></h2>
            By <strong>${[0]}</strong> on ${date(i.sys.createdAt, 'MMMM Do, YYYY')}

        ${params.slug ? markdown(i.fields.body) : truncate(markdown(i.fields.body), 250)}

    <div class="pagination">
      ${postsMeta.skip > 0 && (postsMeta.skip - postsMeta.limit) !== 0 ? `<a class="pagination--prev" href="?skip=${postsMeta.skip - postsMeta.limit}">&larr; Prev</a>` : ''}

      ${(postsMeta.skip - postsMeta.limit) === 0 ? `
        <a class="pagination--prev" href="/">&larr; Prev</a>
      ` : ''}

      ${ > (postsMeta.limit + postsMeta.skip) ? `
      <a class="pagination--next" href="?skip=${(Number(params.skip) || 0) + postsMeta.limit}">Next &rarr;</a>
      ` : ''}


We’re using three small helpers here to help with date formatting, Markdown parsing and truncating long content for the article preview on the homepage (don’t forget to NPM install the extra modules if you’re following along: npm install marked moment).


    const moment = require('moment') = (date, format, parseFormat) => {
      return moment(date, parseFormat || null).format(format)


    const marked = require('marked')

    module.exports.markdown = chunk => {
      if (!chunk) return
      return marked(chunk)


    module.exports.truncate = (str, maxLen, separator = ' ') => {
      if (str.length <= maxLen) return str;
      return '<p>' + str.substr(0, str.lastIndexOf(separator, maxLen)).replace(/<(?:.|\n)*?>/gm, '') + '…</p>';

And we’re done, if you run npm start you should see a simple site showing data from your Contentful service.


You can find all the assets for this project in this GitHub repo.

Related articles

More tutorials articles
Mail icon

Like what you are reading? Want to earn tokens by becoming a DADI Node? Save money on cloud computing services? Build amazing digital product with DADI Web Services? Join our mailing list.

To hear about our news, events and products or services subscribe now. You can also indicate which services you are interested in, which we use for research and to inform the content that we send generally.

* You can unsubscribe at any time by emailing us at or by clicking on the unsubscribe link which can be found in our emails to you. Read our Privacy Policy.