Build a Modern Blog with Gatsby and MongoDB
Rate this tutorial
The web, like many other industries, works in a very cyclical way. Trends are constantly born and reborn. One of my favorite trends that's making a huge come back is static websites and focus on website performance.
presents a new way of building websites that mergers the static with the dynamic that in my opinion provides a worthwhile framework for your consideration.
For this tutorial you'll need:
The app that we are building today is called Books Plus. It is a blog that reviews technical books.
for all sorts of features and functionality easily interoperate to provide a powerful toolkit for anything you want your website to do.
The second key feature of GatsbyJS is it's approach to data sources. While most static website generators simply process Markdown files into HTML, GatsbyJS provides a flexible mechanism for working with data from any source. In our article today, we'll utilize this functionality to show how we can have data both in Markdown files as well as in a MongoDB database, and GatsbyJS will handle it all the same.
To create a GatsbyJS site, we'll need to install the Gatsby CLI. In your Terminal window run
npm install -g gatsby-cli.
To confirm that the CLI is properly installed run
gatsby -helpin your Terminal. You'll see a list of available commands such as gatsby build and gatsby new. If you see information similar to the screenshot above, you are good to go.
The next step will be to create a new GatsbyJS website. There's a couple of different ways we can do this. We can start with a barebones GatsbyJS app or a
app that has various plugins already installed. To keep things simple we'll opt for the former. To create a new barebones GatsbyJS website run the following command:
Executing this command in your Terminal will create a new barebones GatsbyJS application in a directory called
booksplus. Once the installation is complete, navigate to this new directory by running
cd booksplusand once in this directory let's start up our local GatsbyJS development server. To do this we'll run the following command in our Terminal window.
This command will take a couple of seconds to execute, but once it has, you'll be able to navigate to
localhost:8080to see the default GatsbyJS starter page.
The default page is not very impressive, but seeing it tells us that we are on the right path. You can also click the Go to page 2 hyperlink to see how Gatsby handles navigation.
If you were paying attention to your Terminal window while GatsbyJS was building and starting up the development server you may have also noticed a message saying that you can navigate to
localhost:8000/___graphqlto explore your sites data and schema. Good eye! If you haven't, that's ok, let's navigate to this page as well and make sure that it loads and works correctly.
is a powerful user interface for working with GraphQL schemas, which is what GatsbyJS generates for us when we run
gatsby develop. All of our websites content, including pages, images, components, and so on become queryable. This API is automatically generated by Gatsby's build system, we just have to learn how to use it to our advantage.
If we look at the Explorer tab in the GraphiQL interface, we'll see the main queries for our API. Let's run a simple query to see what our current content looks like. The query we'll run is:
Running this query will return the total number of pages our website currently has which is 5.
We can add on to this query to return the path of all the pages. This query will look like the following:
And the result:
The great thing about GraphQL and GraphiQL is that it's really easy to build powerful queries. You can use the explorer to see what fields you can get back. Covering all the ins and outs of GraphQL is out of the scope of this article, but if you are interested in learning more about GraphQL check out
that will get you writing pro queries in no time.
Now that we have our app set up, let's get to building our application.
A blog isn't very useful without content. Our blog reviews books. So the first thing we'll do is get some books to review. New books are constantly being released, so I don't think it would be wise to try and keep track of our books within our GatsbyJS site. A database like MongoDB on the other hand makes sense.
for MongoDB and one of them just happens to be a
. Let's use this dataset.
In my MongoDB Atlas cluster, I will create a new database and call it
gatsby. In this new database, I will create a collection called
books. There are many different ways to import data into your MongoDB database, but since I'm using MongoDB Atlas, I'll just import it directly via the web user interface.
Our sample dataset contains 431 books, so after the import we should see 431 documents in the books collection.
Now that we have our data, let's use it in our GatsbyJS application. To use MongoDB as a data source for our app, we'll need to install the
gatsby-source-mongodbplug in. Do so by running
in your Terminal window. With the plugin installed, the next step will be to configure it. Open up the
gatsby-config.jsfile. This file contains our site metadata as well as plugin configuration options. In the
pluginsarray, let's add the
gatsby-source-mongodbplugin. It will look something like this:
Save the file. If your
collectionare different from the above, take note of them as the naming here is very important and will determine how you interact with the GraphQL API.
If your GatsbyJS website is still running, stop it, run
gatsby cleanand then
gatsby developto restart the server. The
gatsby cleancommand will clear the cache and delete the previous version. In my experience, it is recommended to run this as otherwise you may run into issues with the server restarting correctly.
gatsby developcommand has successfully been re-run, navigate to the GraphiQL UI and you should see two new queries available:
allMongodbGatsbyBooks. Please note that if you named your database and collection something different, then these query names will be different. The convention they will follow though will be
Let's play with one of these queries and see what data we have access to. Execute the following query in GraphiQL:
Your result will look something like this:
Excellent. Our plugin was configured successfully and we see our collection data in our GatsbyJS website. We can add on to this query by requesting additional parameters like the authors, categories, description and so on, but rather than do that here, why don't we render it in our website.
We want to display the book catalog on our homepage. Let's open up the
index.jspage located in the
src/pagesdirectory. This React component represent our homepage. Let's clean it up a bit before we start adding additional styles. Our new barebones component will look like this:
Next let's add a GraphQL query to get our books data into this page. The updated code will look like this:
We are making a call to the
allMongodbGatsbyBooksquery and asking for all the books in the collection. For each book we want to get its id, title, shortDescription and thumbnailUrl. Finally, to get this data into our component, we'll pass it through props:
Now we can render our books to the page. We'll do so by iterating over the books array and displaying all of the information we requested. The code will look like this:
Let's go to
localhost:8000and see what our website looks like now. It should look something like:
If you start scrolling you'll notice that all 400+ books were rendered on the page. All this data was cached so it will load very quickly. But if we click on any of the links, we will get a 404. That's not good, but there is a good reason for it. We haven't created an individual view for the books. We'll do that shortly. The other issue you might have noticed is that we added the classes
bookbut they don't seem to have applied any sort of styling. Let's fix that issue first.
Open up the
layout.cssfile located in the
src/componentsdirectory and add the following styles to the bottom of the page:
Next, let's simplify our UI by just displaying the cover of the book. If a user wants to learn more about it, they can click into it. Update the
index.jsreturn to the following:
While we're at it, let's change the name of our site in the header to Books Plus by editing the
gatsby-config.jsfile. Update the
siteMetadata.titleproperty to Books Plus.
Our updated UI will look like this:
As mentioned earlier, if you click on any of the book covers you will be taken to a 404 page. GatsbyJS gives us multiple ways to tackle how we want to create this page. We can get this content dynamically, but I think pre-rendering all of this pages at build time will give our users a much better experience, so we'll do that.
The first thing we'll need to do is create the UI for what our single book view page is going to look like. Create a new file in the components directory and call it
book.js. The code for this file will look like this:
To break down what is going on in this component, we are making use of the
mongodbGatsbyBooksquery which returns information requested on a single book based on the
idprovided. That'll do it for our component implementation. Now let's get to the fun part.
Essentially what we want to happen when we start up our Gatsby server is to go and get all the book information from our MongoDB database and create a local page for each document. To do this, let's open up the
gatsby-node.jsfile. Add the following code and I'll explain it below:
The above code will do the heavy lifting of going through our list of 400+ books and creating a static page for each one. It does this by utilizing the Gatsby
createPagesAPI. We supply the pages we want, alongside the React component to use, as well as the path and context for each, and GatsbyJS does the rest. Let's save this file, run
gatsby develop, and navigate to
Now when the page loads, you should be able to click on any of the books and instead of seeing a 404, you'll see the details of the book rendered at the
So far so good!
We've shown how we can use MongoDB as a data source for our books. The next step will be to allow us to write reviews on these books and to accomplish that we'll use a different data source: trusty old Markdown.
srcdirectory, create a new directory and call it
content. In this directory, let's create our first post called
welcome.md. Open up the new
welcome.mdfile and paste the following markdown:
Save this file. To use Markdown files as our source of content, we'll have to add another plugin. This plugin will be used to transform our
.mdfiles into digestible content for our GraphQL API as well as ultimately our frontend. This plugin is called
gatsby-transformer-remarkand you can install it by running
npm install --save gatsby-transformer-remark.
We'll have to configure this plugin in our
gatsby-config.jsfile. Open it up and make the following changes:
gatsby-source-filesystemplugin is already installed, and we'll overwrite it to just focus on our markdown files. Below it we'll add our new plugin to transform our Markdown into a format our GraphQL API can work with. While we're at it we can also remove the
seo.jsstarter components as we will not be using them in our application.
Let's restart our Gatsby server and navigate to the GraphiQL UI. We'll see two new queries added:
markdownRemark. These queries will allow us to query our markdown content. Let's execute the following query:
Our result should look something like the screenshot below, and will look exactly like the markdown file we created earlier.
Now that we can query our markdown content, we can just as pre-generate the markdown pages for our blog. Let's do that next. The first thing we'll need is a template for our blog. To create it, create a new file called
blog.jslocated in the
src/componentsdirectory. My code will look like this:
Next we'll need to tell Gatsby to build our markdown pages at build time. We'll open the
gatsby-node.jsfile and make the following changes:
The changes we made above will not only generate a different page for each book, but will now generate a unique page for every markdown file. Instead of using a randomly generate id for the content page, we'll use the user-defined slug in the frontmatter.
Let's restart our Gatsby server and navigate to
localhost:8000/blog/welcometo see our changes in action.
We want our users to be able to read our content and reviews. Currently you can navigate to
/blog/welcometo see the post, but it'd be nice to display our latest blog posts on the homepage as well. To do this we'll, make a couple of updates on our
index.jsfile. We'll make the following changes:
We've updated our GraphQL query to get us not only the list of books, but also all of our posts. We named these queries
postsaccordingly so that it's easier to work with them in our template. Finally we updated the template to render the new UI. If you navigate to
localhost:8000now you should see your latest post at the top like this:
And of course, you can click it to view the single blog post.
The final thing I would like to do in our blog today is the ability to reference a book from MongoDB in our review. This way when a user reads a review, they can easily click through and see the book information.
To get started with this, we'll need to update our
gatsby-node.jsfile to allow us to query a specific book provided in the frontmatter of a post. We'll update the
allMarkdownRemarkso that in addition to getting the slug, we'll get the book parameter. The query will look like this:
Additionally, we'll need to update our
createPage()method when generating the blog pages, to pass along the book information in the context.
We'll be able to use anything passed in this
contextproperty in our GraphQL queries in our blog component.
Next, we'll update our blog component to account for the new query. This query will be the MongoDB based book query. It will look like so:
Notice that the
$bookparameter is optional. This means that a post could be associated with a specific book, but it doesn't have to be. We'll update our UI to display the book information if a book is provided.
If we look at our original post, it doesn't have a book associated with it, so that specific post shouldn't look any different. But let's write a new piece of content, that does contain a review of a specific book. Create a new markdown file called
mongodb-in-action-review.md. We'll add the following review:
Restart your Gatsby server so that the new content can be generated. On your homepage, you'll now see two blog posts, the original Welcome post as well as the new MongoDB In Action Review post.
Clicking the MongoDB In Action Review link will take you to a blog page that contains the review we wrote a few seconds ago. But now, you'll also see the thumbnail of the book. Clicking this thumbnail will lead you to the books page where you can learn more about the book.
In this tutorial, I showed you how to build a modern blog with GatsbyJS. We used multiple data sources, including a remote
database and local markdown files, to generate a static blog. We took a brief tour of GraphQL and how it enhances our development experience by consolidating all of our data sources into a single API that we can query both at build and run time. I hope you learned something new, if you have any questions feel free to ask in our