Skip to content

Instantly share code, notes, and snippets.

@amandeepmittal
Created November 17, 2018 09:12
Show Gist options
  • Save amandeepmittal/6c3bcb9ff6c435428d96e79068bf78aa to your computer and use it in GitHub Desktop.
Save amandeepmittal/6c3bcb9ff6c435428d96e79068bf78aa to your computer and use it in GitHub Desktop.

Build a Blog with React and Markdown

If you are looking to revamp your developer/company portfolio, adding a blog can be a great feature right now. Publishing blog posts on various mediums such as Medium itself can be a great asset to gain attraction but making a collection of blog posts and having all of them in one place is an asset to the content creator.

In this scenario, where you need to add a blog to your portfolio website or just starting out with a new blog, a static site generator can really help you. What is a static site, you ask? Well, this type of site will have fixed content. In several uses cases of the web, that is enough. However, modern-day static site generators such as GatsbyJS can be used for pretty much any web application including blog and e-commerce web applications. In this post, we are going to examine a complete strategy to build a blog from scratch using GatsbyJS which ReactJS and GraphQL at its core.

What is GatsbyJS?

Gatsby is a simple, robust and fast static site generator. It uses ReactJS to render static content on the web. The content in a Gatsby app is written in the same way as any other React app, through components. These components are then rendered at build time to the DOM as static HTML, CSS, and JavaScript. At a high level, Gatsby uses various source plugins to read data and make it available via a GraphQL interface. You write GraphQL queries to load this data and render React components. It can render content that is sourced from a large number of formats and sources such as Markdown, CSV, and CMS like Wordpress, Drupal, GraphCMS, and so on.

Why use Gatsby?

There are a lot of modern paradigms that Gatsby takes care of, for the developer, behind the scenes to start building and launch their project. Another cool thing about Gatsby that I like is its ever-growing data plugin ecosystem, especially for data transformation. Overall, I think the below points are enough to lure you to it out.

  • Future proof JAMstack websites
  • Gatsby has a rich plugin ecosystem that is easily extensible
  • Pre-configured Webpack based build system (no need to break your head)
  • Supports PWA (Progressive Web App) by default
  • Optimized for speed. Gatsby loads only critical parts so that your site loads as fast as possible. Once loaded, Gatsby prefetches resources for other pages so that clicking on the site feels incredibly fast

Pre-requisites

To continue to read this tutorial and follow along, I am listing below all the necessary things.

  • Familiarity with HTML, JavaScript, ReactJS
  • Nodejs with npm or yarn installed
  • Gatsby CLI (which we are going to install in next section)

Note: Please note that, at the time of writing this tutorial, Gatsby v2 was officially launched.

Getting Started with Gatsby

To start, we need to install the command line utility provided by GatsbyJS team to quickly scaffold projects. Open your terminal and type the following command.

https://gist.github.com/c4114b038f180986d87e20fc776e404d

To verify that it has been installed, run the following command.

https://gist.github.com/80193725b3db6c74348bcc27e7069ff7

Once you successfully installed gatsby-cli it is time to generate a new project.

https://gist.github.com/67798224f24acc21db2541cc3b53cf3a

This process will take a minute or two and at the end of it, you will have a new directory. Traverse inside it. The project structure that Gatsby give is by default looks like below.

(ss1)

To see what we get by default, run gatsby develop. This will run the project without creating the official build directory on a development server through webpack (used by Gatsby internally). After the command runs successfully, you will be prompted by the following screen like below in your terminal.

(ss2)

You can visit http://localhost:8000 to see the default site in action.

(ss3)

Running a GraphQL Query

(ss4)

Every Gatsby project contains at least these files. You might be familiar with some such as node_modules, public directory, which is served when deployed. It also contains package.json, which contains the metadata of any modern Javascript application.

Our main focus and concern are in the directory src and files such as gatsby-config.js and gatsby-node.js.These contain the metadata and other essential information about our current application. Inside the src/ there are two sub-directories: components/ and pages/. The components/ contain further two files: layout.css and layout.js. These serve as the starting point of our application.

You have already seen how the default page that comes with Gatsby looks. We have a title in the navigation bar. Let us add a subtitle. Open gatsby-config.js and a new field description and change title like below.

https://gist.github.com/abe6062523dd4c8f89b124f955754c2c

Gatsby allows us to query metadata fields described in this file as a GraphQL query. In order to take a look at what kind of stuff we can query from Gatsby, let us go ahead and run gatsby develop from the terminal. You will not see any changes at http://localhost:8000/ yet because we haven't modified the component responsible for that. However, we can verify by running a simple GraphQL query. Open http://localhost:8000/___graphql in the browser.

(ss5)

We've got the GraphiQL browser open and over on the side here, we can see the documentation explorer, which lets us go through our schema and look at what kind of stuff we can query for. We can click on the query type on the right hand side to see what query fields we can access.

(ss6)

This gives us a list of all of the query types that we can look for. Let us take a look at the site and the siteMetadata. You can start typing an s, and you will see an autocomplete for the query type site. This is really helpful. Let us run the below query.

(ss7)

This is great! Now that you are familiar with nitty-gritty or Gatsby and how it works, in the next section, we are going to start working on the blog.

Writing our first Markdown blog post

Gatsby makes use of various plugins for building static sites. In this section, we are going to install and configure in order to make use of gatsby-source-filesystem and gatsby-transformer-remark to work with locally stored Markdown files. Open your terminal and type.

https://gist.github.com/ac4bcb29ccf5ed2fce33e0972cef02bb

I am using yarn because Gatsby uses it by default over npm as the package manager. Once both of these dependencies are installed, let us configure gatsby-config.js file like below.

https://gist.github.com/a586bcec1128327594b43e2d0f3f6902

Rest of the plugins remain same. gatsby-transformer-remark is used parse Markdown files in .md format into HTML. gatsby-source-filesystem helps us with reading those markdown files from the disk. Each post in our blog is going to be in markdown format.

To understand it better, let us add some posts. Traverse to src/pages directory and then add one or two posts in a year, month, and date format with a slug like below.

(ss8)

Each markdown file is supposed to have some frontmatter fields that are used to create and update our posts. Open the 2018-11-14-hello-world.md and the following content.

https://gist.github.com/dfa006747c9b711d5e91efddd5d7b23d

Similarly you can add the content to the second post.

https://gist.github.com/6778ecf1dc92a5e13570f07358f24b30

The content of these two Markdown files will be our first two blog posts. The block surrounded in dashes is referred to as frontmatter, and the contents of the block can be used to inject React components with the specified data, e.g. path, date, title, tags etc.

One important note is that path will be used when we dynamically create our pages to specify the URL to each blog to render the file. We are going to do this later.

Creating the Blog Template

If you take a look at your blog in a browser, you will see that Gatsby is not displaying any blog post that you have created. This is because Gatsby still does not know where these blog posts are or that you even want them to be displayed in the browser. However, if you try to query it in the GraphiQL browser tab, you can see that frontmatter data of blog post is available.

(ss9)

Each Markdown file is parsed into a node of type MarkdownRemark. To query all markdown files in on query, we are using allMarkdownRemark. All frontmatter fields are converted into GraphQL fields.

To display each post let us create a new template that will be consistent in style and getting frontmatter from GraphQL query we have just seen. Inside the src directory, create a new folder called templates and inside it, create a new file called blogPost.js.

https://gist.github.com/46350ba9db58b21d8660fe470279ebd4

In this component, notice the new query postQuery we are creating. This query will help us to display our blog posts into the template. This query then puts all the frontmatter we require in order to display blog post in the component Template's props.

https://gist.github.com/8b06729e8b07e9d056e8ead89c08fded

In above, I am fetching the title for each post and the HTML content. While rendering the output we get from the query, I am using dangerouslySetInnerHTML which is a React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it exposes a user to a cross-site scripting (XSS) attack if used with sensitive data. Since we do not have any users (no login system), I am just using it for content that is rendered as HTML from markdown.

We now have a template of how our blog post will look but we still haven't configured a way to render and convert a blog post into HTML. That's next. Open gatsby-node.js in the root of your project and add the following code.

https://gist.github.com/ebc80bce480ec1b37ec5bcd9ff24058d

We start by requiring Node's path in order to fetch the blog post template. Notice the actions along with graphql as parameters when we are exporting createPages. Gatsby uses Redux internally to manage state. That's where actions come from. The object actions contain the functions and these can be individually extracted by using ES6 object destructuring. It has pre-defined functions such as createPage, createRedirect, setWebpackConfig and so on. You can find all of them here.

We then make use createPage programmatically. There are two other ways other than the approach we are implementing. In our case, we need to read Markdown files.

Since our home page is still not done to display a list of blog posts you will have to visit each URL listed below in order to see the blog posts in action.

  • For the first post, visit: http://localhost:8000/first-post
  • For the second post, visit: http://localhost:8000/second-post

(ss10)

Try to modify the Template component and other fields from the frontmatter. Open src/blogPost.js.

https://gist.github.com/3397ae8d62ee4abf9f7fb1bb85b13e7a

To represent the changes, I have added the date in italics just before the content of the blog post and after the title. Visit any post's URL and see it in action.

(ss11)

Adding Previous and Next Blog Post Links

For this feature to work with our blog, we are going to make use Gatsby Link component. It is a wrapper around @reach/router’s Link component that adds enhancements specific to Gatsby and you can even use props such as activeStyle or activeClassName to add styling attributes to the rendered element when it matches the current URL. Just like how a normal routing component in React behaves. Open blogPost.js file and add this.

https://gist.github.com/53a034e47289167e4788573447ad12c2

Notice how I am using span tags with attribute role to wrap emojis along with aria-label attribute. It is considered as good practice in Gatsby, React and you will definitely avoid any linting errors. Now to make the above code work, we need to modify the context in gatsby-node.js.

https://gist.github.com/08269f4b0ddc8212717a4e56d9a87848

The context object now contains two keys called prev and next. We are also using index value of each post. If the index === 0, there is not going to be any previous post since it is the first one. You cannot go to a previous post here. We are then using these new context properties in blogPost.js using pathContext.

Visit the first post and you will the following result.

(ss12)

Display all posts on HomePage

Since all of our markdown posts are getting rendered into HTML correctly, the next and previous post feature working too. So let us move ahead and display all the blog posts on the home page. Not the complete posts, but a link to each one.

https://gist.github.com/24bc648b37086bdfc4dcb38655fc44f7

On visiting the Home page URL: http://localhost:8000/ you will get the following result.

(ss13)

Conclusion

This completes our tutorial. We have a functioning blog. I challenge to expand it further by adding comments or tags functionalities. Gatsby has a lot to offer. You learn more about Gatsby at their official documentation.

You can find the complete code for this tutorial in the Github repo below 👇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment