How Pages Work in Gatsby

Follow

We believe that Editors  (you know, the folks actually creating content) should have full control over their website pages and not rely on a developer. 

The gatsby-source-agilitycms plugin makes it easy to source content, but it also generates your Pages for you based off of your sitemap in Agility CMS.

This means that editors in the CMS control what pages are available, what their URLs are, and exactly what UI components (we call these Modules) make up each page.

The Secret Sauce...

Each Agility CMS page is composed and generated dynamically at build-time using a masterPageTemplate that you define in your gatsby-config.js plugin options.

Page Generation

The following example is based on the Blog Template instance. Don't have one? Sign up for one!

mceclip0.png

The above figure represents a sitemap of Pages as well as the UI Components (Modules) that are on each page - all are managed in the CMS. 

This means that when a build occurs in your Gatsby site, the following pages will be auto-generated for you:

  • /
  • /posts
  • /posts/* - your dynamic page route for all of your blog posts (i.e. /posts/my-first-post)
  • /contact-us
  • /about-us

Page Rendering

When a Page is being generated during build time, the final step is rendering the page to HTML. In order to do this, you must provide a Master Page Template React component. This will be your layout used for each rendered Agility CMS page.

In our agility-gatsby-starter site, this file is configured as ./src/AgilityPage.js (from gatsby-config.js):

module.exports = {
  siteMetadata: {
    title: "Agility CMS Gatsby Starter",
  },
  plugins: [
    ...
    {
      //the name of the plugin
      resolve: "@agility/gatsby-source-agilitycms", 
      //the options for our plugin
      options: {
        ...
         //the page template that will be used to render Agility CMS pages
        masterPageTemplate: "./src/AgilityPage.js"
      },
    },
    ...
  ]
}

Sample source code for ./src/AgilityPage.js:

import React from 'react'
import { graphql } from "gatsby"
import agilityUtils from './agility/utils'
import AgilityPageTemplate from './agility/components/AgilityPageTemplate'
//Some things we need for our layout
import LayoutTemplate from "./components/LayoutTemplate"
import PreviewBar from "./components/PreviewBar"
import GlobalHeader from './components/GlobalHeader'
import SEO from './components/SEO'


//Our query to get the our page data and check for a dynamic page item (agilityItem)
export const query = graphql`
  query($pageID: Int!, $contentID: Int!, $languageCode: String!) {
    agilitypage(languageCode: { eq: $languageCode }, itemID: { eq: $pageID }) {
        pageJson
	}
    agilityitem(languageCode: {eq: $languageCode}, itemID: {eq: $contentID}) {
		itemJson
    }
}
`
const AgilityPage = ({ pageContext, data }) => {
    const viewModel = agilityUtils.buildPageViewModel({ pageContext, data });
    return (
        <LayoutTemplate>
            <SEO title={viewModel.page.title} description={viewModel.page.seo.metaDescription} />
            <PreviewBar isPreview={viewModel.isPreview} />
            <GlobalHeader />
            <main className="main">
                <AgilityPageTemplate {...viewModel} />
            </main>
        </LayoutTemplate>
    );
}
export default AgilityPage;

Page Rendering Process

  1. Your React Master Page Template dependency is resolved, then proceeds to run the component.

  2. The GraphQL Page Query is run for the current Agility CMS page being rendered.

    //Our query to get the our page data and check for a dynamic page item (agilityItem)
    export const query = graphql`
      query($pageID: Int!, $contentID: Int!, $languageCode: String!) {
        agilitypage(languageCode: { eq: $languageCode }, itemID: { eq: $pageID }) {
            pageJson
    	}
        agilityitem(languageCode: {eq: $languageCode}, itemID: {eq: $contentID}) {
    		itemJson
        }
    }`
  3. The result of the query is passed as the data prop to the AgilityPage component.

    The result of the query includes a JSON string (data.agilityPage.pageJson) representing the page object, and may also include a JSON string (data.agilityItem.itemJson) representing a dynamic page item (i.e. if you are rendering a blog post).
    const AgilityPage = ({ pageContext, data }) => {
        ...
    }
  4. The data is massaged into a viewModel object that is used to pass as props to render components for the page.
    const AgilityPage = ({ pageContext, data }) => {
        const viewModel = agilityUtils.buildPageViewModel({ pageContext, data });
    			...
        );
    }

    viewModel.page - contains page-level properties, as well as for instructions on which inner page template to use, and each module (and its fields) that are on the page

    viewModel.dynamicPageItem - if the current page being rendered is a dynamic page, then this will give you a reference to the dynamic item and its fields

    viewModel.isPreview - is set to true/false depending on whether you've set you are in preview mode or not (via gatsby-config.js)

  5. The page viewModel is passed to the <AgilityPageTemplate {...viewModel} /> component. This component will render the corresponding react page template that the current page depends on.

  6. The page template uses the <ContentZone /> component to identify where modules for specific zones should be rendered within the page template.

    import React from 'react';
    import ContentZone from '../agility/components/ContentZone'
    
    const OneColumnTemplate = (props) => {
        return (
            <div className="one-column-template">
                <ContentZone name="MainContentZone" {...props} />
            </div>
        );
    }
    export default OneColumnTemplate;
    
  7. Within each <ContentZone /> component defined in the template, each module that exists on the content zone in the CMS is resolved to a react component and rendered in-place.

0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.