In this article, I am going to explore using GraphCMS, React.js, and GraphQL to develop a prototype CRUD (Create, Read, Update, Delete) application by leveraging the Content and Mutation APIS — the two API categories exposed by the GraphCMS software.
Traditionally, content management systems have been bulky, all-in-one software solutions for effectively creating, managing, storing, and retrieving content.
Although these large, unwieldy software were the perfect solution to the problems (content creation, management, and persistence) that they were created to solve, modern problems require modern solutions, and this is why the concept of Headless content management systems evolved.
Examples of traditional content management systems include WordPress, Drupal, and Joomla.
Headless content management systems are a new breed of content management tools that, unlike their more traditional predecessors, are developed around the core idealogy that data (content) should be created, managed, and stored as a standalone component, separate from presentation logic.
This means that content can be created, updated, and stored as a separate entity from the presentation product, therefore allowing the content management process to be lightweight and streamlined.
The core idea behind modern headless CMS tools is that content should be a separate component and must be persisted in a way that allows it to be easily injected in, or detached from, presentation logic.
It is easy to see the many advantages that this approach to content development offers. Creating content using the WordPress platform, for example, means that the content will only be available on the WordPress platform. This precludes the freedom to switch the choice content management system to some other platform: Joomla, for example.
On the other hand, headless content management systems allow creators to easily and seamlessly switch the logic behind their presentation (React.js, for example) to a different technology or platform (Angular, for instance) without having t worry about data malformation or data loss.
While there are many great products built around the headless CMS idea, GraphCMS is an emerging product that has really come to stay. It offers several features for managing content and these have made it a fast-rising star in the industry.
About The Technology
The core technologies I’ll be using are React.js, GraphQL, and GraphCMS.
React.js is a lightweight client-side library that is great for developing awesome user interfaces for the web, mobile, and desktop platforms using JavaScript. Released in 2013, React is arguably the most popular clientside tool for creating user interfaces, especially for the web software platform.
The beauty of React is that it encourages software to be built using a component-based methodology.
React apps are usually made up of components that can be reused in multiple instances throughout the codebase. This approach ensures uniformity throughout the software development pipeline.
Read more about React.js here: https://reactjs.org.
GraphQL is a Query Language for storing and querying data. It is a powerful alternative to traditional protocols such as the popular REST API protocol. GraphQL allows the client to request ONLY the data it needs from the server. This makes it highly efficient at syncing data between the client and the server.
Read more about GraphQL here: https://graphql.org.
GraphCMS is a powerful headless CMS offering that uses GraphQL technology for querying data and performing mutations (or updates) to the content. Common use cases where it makes sense to choose GraphQL + GraphCMS over traditional content management systems are:
- Blogging platforms and blogging software
- Online stores and e-commerce
- Customer Relationship Management (CRM) software
- Productivity software
- Simple websites, web apps and mobile apps.
In this article, I will develop a prototype blogging platform with a front-facing webpage for viewing and interacting with posts.
At the end of the article, the software will allow users to create and publish posts and view published posts.
Getting Started With GraphCMS
The onboarding process for GraphCMS is quite simple and user-friendly.
First, you’ll need to create an account with GraphCMS if you don’t have one already:
- Go to https://app.graphcms.com/signup to create a free-forever account.
- After the account creation process, log in to your dashboard and click Create a new project from scratch.
- Enter a name and short description for your project. A good name might be “Blog CMS Using React, GraphQL and GraphCMS”.
- Select a region on the map to have your content served from and click Create Project. For optimal results loading your content, choose the region that is nearest your location (or the likely location of your audience).
- Select the Free Forever plan to proceed. Of course, you can choose a paid plan later if you need it.
- Click Invite Later to continue. GraphCMS offers an exciting collaboration feature that is handy when working with a team on a project, but we won’t be using this now. You should be presented with a screen that looks like this:
In the sidebar menu, click Schema (the third option) to continue.
The Schema page allows us to layout out our content and add/customize fields for our content.
In the Models tab, click Add.
- Enter post in the Display Name field.
- Enter a short description of the model.
- Click Create Model to create your post model.
- Toggle Show system fields on.
We need to create extra fields (title, author, body, coverImage and trending) for our model.
Title: A short title for each post.
Author: The author of each post.
Body: The content of each post.
coverImage: A cover image for each post.
Trending: A boolean indicating whether a post is currently trending among readers or not.
The sidebar to the right provides different field types for the different data we need to store about our posts:
- Click Single line text for the Title field.
- Enter the Display name: title.
- Enter the API ID: title.
- Enter a short Description.
- In the Validations tab, select Mark field required.
- Click Create.
Repeat these steps for the author field.
For the body field:
- Click Multi line text for the Body field.
- Enter the Display name: body.
- Enter the API ID: body.
- Enter a short Description.
- In the Validations tab, select Mark field required.
- Click Create.
For the Trending field:
- Click Boolean.
- Enter the Display name: trending.
- Enter the API ID: trending.
- Enter a short Description.
- In the Advanced tab, select Set initial value and set the initial value to False.
- Click Create.
For the coverImage field:
- Click Asset picker.
- Enter the Display name: coverImage.
- Enter the API ID: coverImage.
- Enter a short Description.
- Click Create.
Next, click Content in the sidebar menu (fourth option). Here, we’ll enter some data for our model.
Click Create Item. Enter some dummy data for the new entry and click Save and Publish.
Do this a couple more times. Two or three posts should be enough to work with.
Next, click Settings in the sidebar menu and make a few changes:
Click Save.
Next, create a new access token and save it.
At this point, you are ready to begin developing the client app.
Developing The Client App
We’ll need an audience-facing app as a proof of concept. Basically, we need a blog so that readers of our content will be able to view (and engage with) posts that we publish. Fortunately, setting up a functional prototype isn’t difficult at all. We’ll use Create React App, the popular CLI tool, to scaffold a new React application.
Note: Throughout this tutorial, I will use NPM as my package manager of choice. If you’d prefer to use Yarn instead, you can still follow along by replacing NPM commands with the corresponsing Yarn ones.
- Ensure you have both Node.js and the Node Package Manager (NPM) installed by starting a terminal instance and running:
node -v && npm -v
If both Node.js and NPM are installed, you should still the version numbers for both Node.js and NPM printed thus:
If you do not get output similar to mine, you will need to [https://nodejs.org/en/download/](install Node.js and NPM) before you continue with this tutorial.
- Create a new React project by running:
npx create-react-app
For example:
- After the installation process concludes, open up the project directory in your favorite code editor.
- We’ll need a couple of components for our blog. To start, we’ll need:
- A Home component in a views folder.
- A Navbar component in a components folder. Create these folders and their respective files.
- Next, let’s write dummy code for our Home component:
- We’ll now import out Home component in the App.js folder:
We can test our application now by opening our project directory in a terminal starting up a development server by running:
The development server may take a few moments to start up, but once it does, you’ll be able to view your application in a browser if you navigate to localhost:3000.
You should see This is Home displayed in the webpage.
Next, create the Navbar component. To make the development process easier, we’ll use Bootstrap, the world’s most popular web UI library, to quickly effect styles with minimal CSS.
Install Bootstrap in your project by running this in your terminal:
After Bootstrap is installed, add the following line to the App.js file, at any point before the App function:
You can have this directly below the line that says
Back to the Navbar component. We want our navigation menu to be simple. There should be a logo (or brand name) to the far left, a group of links to the far right, and nothing in-between. Of course, if you can style your Navbar however you want. This is just the UI style we’ll be aiming for in this tutorial.
Since we’ll be adding a Dashboard view later on, which is where we’ll create and edit posts, we’d better set up routing for our app right away. This was, we’ll have working navigation in our web app.
We’ll use React-Router-DOM for our routing:
After the installation is finished, we’ll need to add routing capability to our project by editing App.js thus:
We can now continue with our Navbar component:
Import the Navbar component in the App.js component:
Now, we need to connect our app with our GraphCMS backend. We’ll need a couple of libraries:
- graphql, to use GraphQL (which GraphCMS is built atop).
- graphql-tag, to be able to be able to create GraphQL queries for retrieving and mutating content.
- react-apollo, a popular React.js library for Apollo. Provides a couple useful components for accessing query results, etc.
- apollo-boost, will allow us to create a GraphQL client in our application. npm install –verbose graphql graphql-tag react-apollo apollo-boost
Now, we’ll need to create a GraphQL client that we can use to query posts from our GraphCMS endpoint. We can do this directly in the index.js file:
Next, install dotenv…
Create a file in the project’s root directory named ‘.env’. Add the following to .env:
You can find your GraphCMS endpoint by navigating to Settings > API Access in your GraphCMS dashboard.
Restart the development server by entering Control + C (Command + C on Macs) and:
Make sure the app still works without errors before you continue.
We now have a GraphQL client running and pointed to our GraphCMS endpoint.
Querying Content And Displaying Posts
Querying content is as easy as writing a schema for the properties (of each post) we want and asing the GraphCMS server to return those properties for each post. This feature of GraphQL server-client relationships makes it so powerful.
Create a new folder services in the project’s root directory. Then create a new file graphcms.js.
We’ll have all our content querying and mutating code in a class in this file. The idea is to be able to move all our code by copying a single class file. This way, we can reuse code across projects, edit/update code and manage our API-specific interactions within one file.
Create a class GraphCMSContent and add a fetchPosts method thus:
All we are doing is:
- Creating a new GraphQL client just for this class. It’s supposed to be reusable, remember? The client is created whenever a new object is instantiated from this class, so we have the client-creation code in the class’ constructor method.
- Creating a fetchPosts method that we can call wherever we need to to fetch posts from GraphCMS.
- Specifying the properties of each post we want a fetchPosts function call to return.
We can now fetch posts into the Home component and display them.
Displaying Posts In The Home Component
We want our Home view to contain:
- A main area, where every post in the blog is displayed; and
- A sidebar, where trending posts in the blog are displayed.
We’ll create these areas:
Next, we want to display a list of the first six posts in the blog. We’ll create a PostPreview component that we can reuse. In the root directory, create a new folder components and create a new file postPreview.js:
In the Home component:
What We Are Doing:
- We import the Query component from react-apollo which will enable us to access query results.
- Next, we create a posts state with the useState hook (all about hooks here https://reactjs.org/docs/hooks-intro.html).
- We create a new GraphCMSContent object (Client).
- We define functions for returning specific JSX while posts data is being retrieved or if an error occurs in the API transaction.
- Finally, we query the GraphCMS endpoint and display the retrieved posts.
Check that this works fine in your browser. If the error component is displayed, check:
In order to have the same UI styling as I do, you’ll need to paste the following in your App.css stylesheet file:
Displaying Trending Posts
Displaying trending posts is a simple matter of filtering available posts based on whether the trending property (we defined this in our GraphCMS dashboard Content and the fetchPosts schema, remember?) is set to true or not. You can create a couple more posts in your GraphCMS dashboard and set their trending properties to true so that you’ll be able to test this.
To really streamline the process, and for the sake of code reusability, we’ll need a component specifically for displaying trending posts.
In the components folder, create a new file Trending.js:
Add the following code to Trending.js:
What We Are Doing:
- We import the PostPreview component.
- We filter the posts (which we receive from the parent component — the HomeView component, in this case — via the posts prop.
- Using the map() function, we invoke the PostPreview component for each post in the filtered posts array. We pass the noImage prop because we do not want images to be displayed in the trending-posts sidebar.
- Finally, we return these back to the parent component.
Replace the sidebar in the HomeView component with the following:
Our client app now works perfectly:
Developing The Dashboard View For Creating And Editing Posts
We need a way to create and edit content without needing to use the GraphCMS dashboard directly. There are a several reasons why this is important:
- We are in an organization and need to have different access levels for different roles.
- We need to provide abstraction for a client so that she won’t run the risk of breaking something by handling the GraphCMS dashboard directly.
- We need to integrate custom/external APIs or other web services in our client-server pipeline.
- We need to make content management more accessible. For example, by developing a mobile app.
GraphCMS allows us to get all these done via the GraphCMS Mutation API.
We’ll start by creating the Dasboard view.
Creating The Dashboard View
First, create a new file dashboard.js within the views folder:
Scaffold a functional component in the Dashboard.js file:
Add a route to the dashboard in App.js:
Test the route by clicking Dashboard in the navigation menu.
The Dashboard view will have two main sections:
- A main area with a form for creating new posts.
- A sidebar where the titles of every published post are displayed. Clicking a title will call up a modal for editing/updating the post.
We’ll start with creating new posts.
Creating New Posts
Add a createPost method to the GraphCMSContent class:
This is an asynchronous function that expects a title, a body and an author for the new post.
GraphCMS mutations are effected by creating a GraphQL query (using the qql tag and specifying “mutation” as the type of operation to be performed — in contrast to ”query” in our fetchPosts query). Then we specify the properties of the new item to be created by using the create__ function that GraphCMS exposes.
The create__ function is a special function that GraphCMS automatically creates for us whenever we create a new model. It’s name is always created by appending the name of the model to create. In our case, we called our model Post, hence the createPost function.
It is important to understand that if we try to use a “create__” function that does not exist, our queries will fail.
For example, if a model is called “Quiz”, the create_ function must be called “createQuiz”. “createQuizz”, “createQuizzes” and “createNewQuiz” will not be recognized.
We are interested only in the post id, title, body and author. Of course, you can add a cover image (property: coverImage) but I do not want to complicate things by handling file uploads.
The GraphQLClient class (imported from **graphql-request) exposes a *request* method that we can use to make requests. This request process is an asynchronous operation, so we wrap it within a try…catch block and “catch” any errors that might occur. This can also be done using the promise syntax.
Or:
Update Dashboard.js with the following:
The Dashboard view should now have a nice-looking form for adding new posts. Enter dummy content and click Create Post. If all goes well, a new post should be created. New posts won’t automatically show up in the app because they are still drafts, but you should be able to see them in the Content tab of your GraphCMS dashboard.
Click that pencil and click Publish to publish your post.
Reload the Home view to see your newly published post.
It is possible to publish posts without going to the GraphCMS dashboard directly, but we won’t be doing this in this tutorial. You can read the GraphCMS documentation to learn how.
Updating Previously Published Posts
Updating posts is as simple as replacing a post’s content with a new one and mutating the GraphCMS store with the change. The post becomes a draft again and can be re-published.
First, create an updatePost method in graphcms.js.
Like the create__ function, the update__ function is automatically created by GraphCMS whenever a model is created.
The update__ method requires two arguments: a where clause that tells which post to update (referenced by an id), and a data object that holds the data to replace the old content with:
Thereafter, updating a post is as simple as making a request using the request method of the GraphQLClient class.
To get data with which to update a post, we’ll need a form.
First, we’ll display all posts in the sidebar. Clicking a post will call up a modal containing the form. React-Bootstrap provides a nice easy-to-use modal that we can leverage.
Install React-Bootstrap:
Replace the Dashboard.js component with:
Test the app in the browser. Titles of each published post should now be displayed in the sidebar, and clicking a post should reveal a modal containing a form that can be used to edit that post.
After editing a post, you will need to re-publish it from within the GraphCMS dashboard.
What We Are Doing:
- First, we import the necessary components:
Remember, the Query component allows us to access the results of a query: it allows us to manipulate query results as JSX.GraphCMSContent is the special class we defined in the services folder, andModal is simply the modal component that React-Bootstrap provides. Since this is a prototype, we can justify installing a library just for one small function. In production systems, we might need to build a modal component from scratch in order to reduce deadweight, if this is the only reason we need React Bootstrap.
- Next, we define several bits of state that will help us manage the content creation/update process:
- The next thing we do is define a couple of important functions. These functions are responsible for handling form input and calling the API services in our GraphCMSContent class.
- There are:
- createPost, an asynchronous function: calls the createPost service. I have logged the response from Client.createPost so that you can see what the response object looks like. Basicaly, if Client.createPost returns false, an error occurred and an alert is shown. Any other response value is a success.
- ii. activateUpdateModal: is called when a post in the sidebar is clicked. It updates the postToUpdate state with the relevant post ID, which it receives from the onclick event prop of the clicked post, and sets showUpdateModal to true. When this happens, the modal is automatically displayed.
- The post ID in postToUpdate will be used by the updatePost service (in the where parameter of the query) to update the selected post.
- iii. handleUpdate, an asynchronous function. handleUpdate interfaces with the updatePost service. It invokes the service with the ID of the post to be updated, as well as the content of the new post that will replace the old one. If updatePost returns false, handleUpdate shows an alert with an error message, otherwise it shows a success alert.
Conclusion And Final Words
Knowing the right tools for a job is a skill that software developers are often called upon to use, and GraphQL + GraphCMS is one of the best combinations right now for solving content management problems. These together can be used to create powerful backends that are fast, light, and component-driven. Throwing in a powerful UI library like React can give a project development team so much freedom: freedom to create. GraphCMS, like React and GraphQL, makes no assumptions about the kind of project or its specifications, it enforces very little on the developer. This makes it a very flexible option for building content management backends that can scale. You can access the source code on Github.