Rebel CMS

The point

The Rebel CMS is a statically generated (SSG) site using GatsbyJS

The core benefits of this pattern include:

  • High performance for our customers as the pages/files can all be stored in a CDN and live at Cloud edge locations
  • SEO Optimization thanks to static content that isn't relying on JavaScript or a Single Page Application pattern.
  • Pages built using defined React components
  • A consistent theming engine
  • All pages are defined as code and living in source control
  • Use of a deployment pipeline with a11y testing at build time
  • A GraphQL-driven schema to fetch site data (http://localhost:8000/___graphql)

GatsbyJS

Although the GatsbyJS documentation is fantastic, there are a few key points that need some further explaining.

First - Gatsby is a Static Site Generator that leverages our data and builds html/css versions of all our pages. This is the part that really boosts performance and SEO. Once these static assets are deployed to the cloud, they're incredibly fast to fetch from a browser.

Second - These static pages are simply the entry point for users into the site. Once the html/css is downloaded and rendered, the rest of the code (JS) catches up and hydrates into a full React Single Page Application (SPA). This includes client-side routing (reach-router) and all other interactions. It's seamless to the user, but once the code is downloaded, you're in React world. Every subsequent page is loaded by React. Using an <a> to navigate from page to page will round-trip the user to the target static page to start this whole process over. Using a <Link> provided by Gatsby will use the internal router and give a faster user experience. Do that.

The last sticking point in regards to Gatsby is what it actually does under the hood. Everything is in GraphQL... but what does that even mean?

The main idea is that we can use literally any data source to hold our page data. This is plastered all over the documentation. You can use the File System, a Headless CMS, REST call, SaaS, etc...

So what?!

So... you can fetch all this data and Gatsby magically lets you query for it? Hardly magical. Genius implementation, but not magical.

All source plugins do is fetch the raw data from somewhere and use Gatsby's exports.sourceNodes hook in the gasty-node.js file to run through the data and create Nodes of a given type. By creating nodes using the createNode function (check the docs), we're given a pair of GraphQL queries for free. "allExamples" to fetch every node of that type and "example" to fetch a specific Node with query variables and matchers to filter.

These Nodes are all contained within an internal, in memory GraphQL database/server/thing available to us at build/run time. This is what you see at https://localhost:8000/___graphql.

Transform plugins well expend this data. For example, gatsby-transformer-json will take all source nodes of a .json page and will parse through the code to add child nodes matching the data. This is how we can query for CMS page data.

The point is the we must query for this data using page queries (or static queries, check the docs) in order to get this data into the actual pages at build time.

These are the steps to remember in order to keep the right mental model:

  • Fetch the data from the source
  • Creating GraphQL Nodes (and their schema) and add them to the internal data store
  • Extend some of the data, as needed, using transformer plugins
  • Fetch the data you need at build time for the pages you're building. This is typically done using the template components.

Query fields missing from the schema will result in a build error. Forgetting to query for data that does exist in the schema will never get that data to your template component. These two actions are the link between sourcing the data and getting into the React code.

Static Schemas

As all the nodes described above are created by the source data, the schema is infered by the data itself. This means we could freely add fields to our json, adjust the query fetching that data and use it in the React code.

The issue that arose over time is that we needed at least one instance of every piece of data to present at all times in order to build the site properly. Otherwise, the query (and fragments) had to be modified constantly to resolve errors. Just because we don't currently have a page using certain fields today, doesn't mean we want to remove all supoort for it right away.

By defining the schema statically using the createSchemaCustomization hook in gastby-node.js, we can provide a consistent schema for our data. It will have to be maintained, no doubt, but this really helps contributors outside the development team by avoiding cryptic build errors. It also helps for documentation and reference.

Panel Pages

The vast majority of pages manually created for the Rebel and Internic sites are considered "Panel Pages" in that they're comprised of a set of individual panels or sections.

The panels themselves are build with extensibility in mind and typically allow for a great deal of flexibility in how they look and what type of information they can present.

All panel pages are created in a .json file within the /pages folder of the project and use the panel-page.js template.

Using the gatsby-source-filesystem to pull our pages from the filesystem and the gatsby-transformer-json to insert the .json file data into the GraphQL schema.

The pages themselves are created at build time using the createPage function within the gatsby-node.js file.

TLD Pages

Generic Pages

...

Custom Pages

...

Markdown Pages

...

Static Schemas

...

Static Schemas

...

Resolving fields and schema stitching

  • DynamicPrices