Back to blog

Building a Progressive Blog App with Apollo and Cosmic

Jacob Knaack's avatar

Jacob Knaack

April 18, 2019

cover image

Hello stranger.  Come with me on a short adventure as we build a fast, simple interface for publishing blog style articles. Something sensible.  It should look clean and simple yet have the ability to perform powerful resource fetching with some query magic. I'm talking about Graphql, the query language built with web APIs in mind. And speaking of web APIs,  we will also be using our handy Content Management Service: Cosmic, to Create and Store our Blog Data.


Progressive Apollo Blog
Progressive Apollo Blog Codebase 

0.0 Before You Start

Before you go any further make sure you have the required developer tools installed on your machine.  Mainly you will need Node JSits accompanying package manager: npmand git.  Git is semi optional and will only be used to code storage and deployment if that is your goal.

Once you have those installed we can begin setting up our project and eventually start writing some Javascript.

0.1 Libraries and packages

Let's go over the main packages that we will use to create our blog platform.

  • Create React App - We will be leveraging the ever prevalent React library to build our UI components.  To bootstrap our project we will also be using a handy command line tool create-reate-app so that we can spend as little time as possible on configuration and setup and just get to creating meaningful javascript.

  • Semantic UI- This is a UI framework that will allow us to import fully styled UI components.  No fussing around with tedious CSS specs to get something that looks nice right out of the gate. 

  • Apollo / Graphql - These two packages go hand in hand.  Apollo will be used as the Graphql client to make requests to our Graphql server endpoints.   It's easy to configure and very straight forward to use. Again, allowing us to focus on writing less javascript and instead focusing on the high level composition of our application.  Graphql of course will allow us to make requests that return only data we care about, letting us efficiently grab content from Cosmic.

I believe with all that boring business out of the way, we can start slapping our keyboards!

1.0 Setting Up Our Project

Let's fire up our terminal and start bootstrapping our project source files.  For those that don't have Create React App installed, we can do that with a simple npm command:

$npm install -g create-react-app

Once this finishes (or you have this package already installed), we can summon our initial project files by running the cli:

$create-react-app apollo-blog

You will notice a fair amount of wizardry occurring in your terminal as our app is bootstrapped with all sorts of powerful libraries and source code.  Taking a look at our file system will show a directory titled `apollo-blog`.  Changing directories into this folder will show a structure similar to this:


We should now be able to run:

$npm start


$yarn start

This will run the start script stored in our `package.json` file which is all bundled together with Webpack and build tools that will handle compiling all of our React source code and bundling that into files ready to be served to a browser.

After the script runs you should see a simple message in your terminal, and your default browser should open to a tab with project running.  You should see something like this:

1.1 Installing Javascript Libraries

The next step is installing some npm libraries so that will help quickly create a good looking App Interface as well as easily fetch data from the Cosmic graphql servers.

In your terminal run the following command and let's talk about what each of these packages will be doing for us:

$npm install --save apollo-boost react-apollo graphql dotenv semantic-ui-css semantic-ui-react react-router-dom

apollo-boost / react-apollo / graphql - These guys are going to serve as the main solution for getting our data efficiently and scalably from Cosmic servers to our client side UI.  They provide wrappers for our components to be able to configure queries  and provide useful variables for data loading and error handling.

dotenv - this package will allow is to configure semi sensitive keys so we don't have to store anything publicly for accessing our Cosmic Bucket.

semantic-ui-css / semantic-ui-react - Our UI framework that will let us import pre-styled containers and components letting us focus on programming functionality, spending less time fidgeting with CSS and other styling considerations.

react-router-dom - A react library that will allow us to configure url routing logic to control linking within our app and accessing URL parameters.

with these installed we can begin writing some javascript!

1.2 Configuring Environment Variables

We are going to add a minimal security precaution so that we won't let just any request come through our bucket's API endpoint,  feel free to skip this section but be warned that your components will behave a little differently and your bucket can be queried from anyone with the knowhow to make API Requests.  So, you know... don't put any sensitive info in your buckets.

We are going to require a read_key to be attached to every API request to our bucket.  You'll have to generate one by heading to the settings tab for your Cosmic bucket and clicking on Basic Settings. Cosmic > Your Bucket > settings > main

At the top there should be as section titled API Access > API Read Access Key.  Click on the button to Generate new key.  Copy the key to your clipboard and let's configure our project directory with our config file:

$touch .env

this file is going to be used to configure our project with our API Read Access Key so we don't have to hard code it in with our source code and commit it for the world / other prying eyes to see.

simply add one line to your .env file:

Make sure you prefix your variable name with REACT_APP!  The build scripts that bundle our source code will look for this to make variables available in our compiled javascript.  With that done, we are now ready to use this key in our React project.

2.0 Creating our Routes and Components

Finally, we are ready to create our Components and set up our routes.  In an effort to keep things as simple as possible we are just creating two routes and two main components:


  • {protocol}://{host}/
    • The home route that will list our article
  • {protocol}://{host}/article/:articleName
    • The route that will display an article


  • /views/home.js
    • This component will fetch all articles and display general article info.
  • /views/article.js
    • The component that will fetch a single article and display all article content.

2.1 Configuring  App.js

Let's go ahead and open the App.js component in whatever text editor you prefer, and start to configure it with our routing logic and our Graphql client. 

We are going to import one component wrapper from react-apollo and one constructor function that will let the components within our component wrapper make requests to a specified Graphql server ( for us this will be the Cosmic's Graphql server).  

We also want to import our wrapping components for react-router-dom. This will allow us to us our browser url to systematically switch component views and access any url parameters.

Lastly we are going to import a CSS file from Semantic UI so that we can leverage it's class selectors and give imported components their base stylings.

Here's what our App.js should look like after everything is properly configured:

2.2 Creating The Home View

Let's create a new file in a new directory 


This folder will store all of our view layer React Components.  Our Home View will just return some brief info about our site and a list of articles that have been published to our blog.

The main parts of this component are a heading that display a title and a site description, and a list that will display Semantic UI components.

We also will need to configure this view with some Graphql logic so that it can make requests to Cosmic

Now we have ye old React Component,  that will fetch articles from our content manager (Cosmic) before the component renders and pass those as an array on component props.

Apollo also gives us some handy properties from is data object, specifically an error object, and a loading boolean, which we use to conditionally render components, such as loading message when the request is fetching, and an error message when our error object returns a message.

2.3 Creating The Article View

With our list of articles displaying on our home page, we need to Create the view that will display the blog content contained in each article object.

Let's create another file in our views directory:


Creating this component is similar to the Home View, but our query is going to include an article identifier from our URL stored on a prop: match which react-router-dom creates for us when we render a component at a Route.

This component is much simpler than our Home component, mostly due to the fact that we are just using the Query component wrapper instead of the turning our component into a higher level component using the Graphql component.  This gives us direct access to our Graphql directly in our component logic but does not make it available on component props! So take note.

For both components I have included some minimal styling objects in the source code, but feel free to use your creativity and change up the styling properties to create your own look and feel.

And that's it!  We have built two relatively simple and scalable React components that are configured to two separate url routes. We can control our views easily with react-router-dom and fetch our data sensibly with the power of Apollo / Graphql and Cosmic.

3.0 Deployment

create-react-app comes bundled with some handy deployment scripts if you feel so inclined to make your application available to the world.  

3.1 Running the Build Script

If you take a look at the package.json file that we have a script called build.  Running this will compile all your project files and bundle them into a static build directory that is ready to deploy to any hosting service.

You'll also notice after the script finishes that you have an option to publish directly to github pages using the serve module.  You just need to add a homepage value in package.json and make sure the serve package is installed with either npm or yarn.

Follow the link at the end of the build message to learn more about deployment using this method.

3.2 Deploying Using Netlify and Github

Netlify provides app building and deployment services and they will give you a free ( if not a little bit verbose ) URL for you to deploy client side code.  The process is pretty easy and we can use a github repository to deploy our code continuously when we make changes to our source code.

After you create and account / Log in to the Netlify dashboard, there should be a tab called sites.

Clicking the sites tab will reveal a list of sites you have deployed on Netlify. From here you have two options:

  1. Deploy using your static build directory created using the build script.
  2. Connect your Netlify account to a git repository and use continuous deployment.  This step requires that you commit your code to a git repository.

Deploying the static build directory is super simple but will require you to manually build and upload files to Netlify.  Simply drag the build directory directly over the area at the bottom of the sites tab from the Netlify Dashboard.  

This will automatically deploy your site to a url that Netlify will generate.  Simple but requires work every time you update your source code.

 On the far right side there will be a button that reads New site from Git. Selecting this option will walk you through the process of authorizing Netlify to access a code repository.  After these steps are finished Netlify will build your site files from a build script you specify and deploy it automatically each time you make a commit  to your repo!


Well that's it for me today.  Happy hacking until we meet again :)

If you have any comments or questions about building apps with Cosmic, reach out to us on Twitter and join the conversation on Slack.