Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically create Gatsby pages from Contentful data

I am looking for help with GatsbyJS and Contentful. The docs aren't quite giving me enough info.

I am looking to programmatically create pages based on contentful data. In this case, the data type is a retail "Store" with a gatsby page at /retail_store_name

The index.js for each store is basically a couple of react components with props passed in e.g. shop name and google place ID.

  1. Add data to contentful. Here is my example data model:

    {
        "name": "Store"
        "displayField": "shopName",
        "fields": [
            {
                "id": "shopName",
                "name": "Shop Name",
                "type": "Symbol",
                "localized": false,
                "required": true,
                "validations": [
                    {
                    "unique": true
                    }
                ],
                "disabled": false,
                "omitted": false
                },
                {
                "id": "placeId",
                "name": "Place ID",
                "type": "Symbol",
                "localized": false,
                "required": true,
                "validations": [
                    {
                    "unique": true
                    }
                ],
                "disabled": false,
                "omitted": false
            }
    }
    
  2. I've added the contentful site data to gatsby-config.js

    // In gatsby-config.js
    plugins: [
        {
            resolve: `gatsby-source-contentful`,
            options: {
            spaceId: `your_space_id`,
            accessToken: `your_access_token`
            },
        },
    ];
    
  3. Query contentful - I'm not sure where this should happen. I've got a template file that would be the model for each store webpage created from contentful data.

As mentioned this is just some components with props passed in. Example:

import React, { Component } from "react";

export default class IndexPage extends Component {
constructor(props) {
    super(props);
    this.state = {
        placeId: "",
        shopName: "",
    };
}
render (){
    return (
        <ComponentExampleOne shopName={this.state.shopName} />
        <ComponentExampleTwo placeId={this.state.placeId} />
    );
}

I'm really not sure how to go about this. The end goal is auto publishing for non-tech users, who post new stores in Contentful to be updated on the production site.

like image 581
Barney Avatar asked Jan 15 '18 00:01

Barney


1 Answers

You can create pages dynamically at build time and to do that you need to add some logic to the gatsby-node.js file. Here is a simple snippet.

const path = require('path')

exports.createPages = ({graphql, boundActionCreators}) => {
  const {createPage} = boundActionCreators
  return new Promise((resolve, reject) => {
    const storeTemplate = path.resolve('src/templates/store.js')
    resolve(
      graphql(`
        {
          allContentfulStore (limit:100) {
            edges {
              node {
                id
                name
                slug
              }
            }
          }
        }
      `).then((result) => {
        if (result.errors) {
          reject(result.errors)
        }
        result.data.allContentfulStore.edges.forEach((edge) => {
          createPage ({
            path: edge.node.slug,
            component: storeTemplate,
            context: {
              slug: edge.node.slug
            }
          })
        })
        return
      })
    )
  })
}

the createPages that was exported is a Gatsby Node API function you can find the complete list in the docs here.

For the query allContentfulStore it's called like that because your contentType name is store the gatsby query will be allContentful{ContentTypeName}.

Finally, I created a youtube video series explaining how you can build a Gatsby website with Contentful. You can find it here

I hope this answer your question. Cheers, Khaled

like image 181
Khaled Garbaya Avatar answered Sep 30 '22 13:09

Khaled Garbaya