How I Created My Blog Using JAMStack
Tags: jamstack, tutorials
Published: 2021-12-01 14:47:05

---
title: How I Created My Blog Using JAMStack
published: true
date: 2021-12-01 14:34:28 UTC
tags: JAMStack,Tutorials
series: JAMStack
canonical_url: https://www.underthehoodlearning.com/how-i-created-my-blog-using-jamstack
cover_image: https://res-1.cloudinary.com/under-the-hood-learning/image/upload/q_auto/v1/blog_images/JAMStack-Tutorial-Intro.png
---

In the first two articles of this series, we explored **JAMStack** *(what it is, its components and architecture, available tools for JAMStack development, its pros and cons, and comparison between WordPress and JAMStack)*. If you haven't read it yet, I highly suggest you give it a read first.

- [What Is JAMStack And Whether You Should Use It For Your App?](https://www.underthehoodlearning.com/what-is-jamstack-and-whether-you-should-use-it-for-your-app/)
- [JAMStack vs. WordPress: Which One Is Better?](https://dev.to/thanhtr99270163/jamstack-vs-wordpress-which-one-is-better-2c87)

For the remainder of this series, I'll walk you through the process of how I created my personal blog with JAMStack *- a modern web development practice*. But before we jump into our first tutorial, let's review the entire process at the high level and some *"gotchas"* and challenges I discovered along the way and how I overcame those challenges.😎

## Why JAMStack?

My decision to set up my own blog as well as my decision to use JAMStack came a long way. I originally started blogging on [DEV Community](https://dev.to/thanhtr99270163). DEV is really a great community, don't get me wrong, but I was in need of a blogging platform that would offer some amount of flexibility and customization of how my blog should look like. Also, I thought it would be great to start growing my personal "brand", and having your own blog with your own domain name would be a good starting point.

So I set out to look for a way to cross-post content between my blog on DEV Community and my to-be-created blog with its own domain name. I quickly noticed that DEV actually has an extension that would allow you to generate a personal blog from your DEV Community posts using [Stackbit](https://www.stackbit.com/). Great! "This is exactly what I need", I said to myself. I then followed some tutorials trying to set up my own blog on Stackbit.👩‍💻

However, I quickly ran into issues migrating my posts from DEV Community into Stackbit. I emailed Stackbit's support team and was told that they were aware of the issue and have been working on fixing it. Bummer!😞

I could either wait until Stackbit fixes the issue or find another solution. I decided to find another solution simply because I just don't like the fact that I have to rely on someone else to fix the problem, and that's just the nature of using a ***site builder***  like Stackbit, which is aimed toward less technical users.

So my mission now is to find another solution, which I will explain in more detail in the next section. However, I think it's important to acknowledge the fact that my decision to use JAMStack as well as what tools to use to build my JAMStack app started with Stackbit and is heavily influenced by it. After all, I learned about **Netlify, Gatsby,** and even **Ghost CMS** from my initial attempt with Stackbit because it uses JAMStack.

## JAMStack components recap

![How I Created My Blog Using JAMStack](https://res-2.cloudinary.com/under-the-hood-learning/image/upload/q_auto/v1/blog_images/10586.jpg)  
Let's quickly recap all the components of our JAMStack blog and the technologies that we will be using for each of the components.

- **Static site generator**  
All websites, doesn't matter what they are, fundamentally consists of HTML, CSS, and JavaScript. It doesn't matter what tools or frameworks you use to create your website, the final result needs to be compiled into these file formats in order for the browser to understand and display on the screen. Our blog is no exception.  
There are two sources of HTML for our blog: the **static** HTML contents (site header, logo, layout, footer, etc.) and the **dynamic** HTML contents from the actual blog posts. We need to somehow combine both of these ***static*** and ***dynamic*** HTML sources into a single HTML file at every single build of our app. **Static site generator** to the rescue!🦸‍♂️  
A ***static site generator*** is a software application that creates HTML pages from templates or components and a given content source during a ***build*** process. There are many static site generators available out there. We will be using [Gatsby](https://www.gatsbyjs.com/) for our blog.  
During a build, **Gatsby** loads JSON data from **GraphQL** and merges it with components to create HTML pages. These generated pages are then deployed to a web server. When the server receives a request from a browser, it responds with rendered HTML.  
So the question that needs to be answered now is ***where does the GraphQL data come from?***🤔. I'm glad you asked because that's exactly what we're going to explore in the next section.😉

- **Content Management System (CMS)**  
Dynamic contents for JAMStack sites *(in our case, these are our blog posts)* can be controlled via a CMS, typically known as ***headless CMS.*** Once a change is made in CMS *(a post is published/added/edited/deleted)*, a new build of our site will be triggered and deployed as static assets. Similar to static site generators, there are many options for CMS available out there, but we will be using [Ghost CMS](https://ghost.org/) for our blog.  
As mentioned above, after a change is made to either our ***static HTML*** from **Gatsby** or to our ***dynamic HTML*** from **Ghost CMS** , we will need to somehow trigger the deployment to the web server to rebuild and regenerate the HTML files. How are we going to do that?🤔 Again, glad you asked! Join me in the next section!😎

- **Deployment**  
The generated HTML pages need to be hosted on a web server somewhere in order to allow users from anywhere to access our blog. There are several services available, but we will be using [Netlify](https://www.netlify.com/) for our blog.  
I chose Netlify because it has an awesome [free plan](https://www.netlify.com/pricing/) that comes with great features such as:

Now that you understand all these components at a high level, I'll share with you some of the challenges that I encountered as I was setting up my blog.

## Gatsby static site generator

In order to get my site up and running as quickly as possible, I decided to use one of Gatsby's [starter libraries](https://www.gatsbyjs.com/starters). **Starters** are open-source Gatsby sites maintained by Gatsby that enable users to dive into their next Gatsby project with minimum effort. Starters range from minimal boilerplate to full proof of concept. Since we will be using **Ghost** as our content management system. It seems logical that the [gatsby-starter-ghost](https://www.gatsbyjs.com/starters/TryGhost/gatsby-starter-ghost/) is the best option for us.

Besides a few customizations to give the blog the look and feel of my personal brand, the following features were implemented/improved to suit my needs:

- Added a [Tags](https://www.underthehoodlearning.com/tag/) page that displays my posts grouped by their corresponding tags.
- Added **Google Analytics**
- Added [Algolia Search](https://www.algolia.com/)
- Added block code syntax highlight using [highlight.js](https://highlightjs.org/)

## Ghost CMS

**Ghost** offers [Ghost(Pro)](https://ghost.org/pricing/) *- a managed hosting service for Ghost* that offers users the fastest way to get started on Ghost. It includes out-of-the-box features such as *custom domain, custom themes, server maintenance and backups, CDN, etc.* However, since I was looking for a low-cost option, I opted for a [self-hosted instance](https://ghost.org/docs/install/).

Out of the box, Ghost comes with:

- A core JSON API
- An admin client app
- A front-end theme layer using **Handlebars** templating languages

However, since I use Gatsby for the frontend theme layer, I had to modify a few things after installing Ghost. Ghost's Admin Client app has the page preview feature that only works if you use one of Ghost's themes. Therefore, I had to set up a proxy server with some URL redirect configuration in order to be able to preview my posts with my Gatsby theme from the Admin Client app. The page preview on the Branding setting page still doesn't work, but that didn't bother me much, so I didn't spend time fixing it. More on that later when we get to the tutorials.

## Cloud hosting

![How I Created My Blog Using JAMStack](https://res-5.cloudinary.com/under-the-hood-learning/image/upload/q_auto/v1/blog_images/3040061.jpg)  
As mentioned above, we will use **Netlify** to manage automatic build and deployment of our site. Basically, we will connect Netlify to our GitHub repo where we store our Gatsby code and configure it so that every time a change is pushed to the remote repo, a build is triggered in Netlify. In addition to that, we will integrate Netlify's **build hook** with Ghost so that every time a change is made in Ghost (you can configure what type of changes you want such as post added, post updated, global changes, etc.), a build in Netlify is automatically triggered.

Unless you're planning on hosting your Ghost server on your local machine, which you can if you want, you will need to pick a cloud platform ( **AWS, Azure, Heroku, Digital Ocean,** etc.) to host your server app. Since my goal is to come up with a low-cost solution, here is what I ended up using for my stack:

- Use **Heroku** to host my Ghost server, which is essentially a **Node.js** app. I found [this](https://github.com/thelovekesh/ghost-v4-on-heroku/) GitHub repo that can be used to deploy a Ghost server into Heroku with just a click of a button. However, this app is preconfigured to use [JawsDB](https://www.jawsdb.com/) as the **MySQL** database where all data for our posts are stored. JawsDB does have a **free plan** , but it only comes with **5MB** of storage. The next price tier is **$10/month** for which you'll get **1GB** of data. I needed to come up with a lower-cost option for my data storage.
- I ended up using **AWS RDS** for my MySQL database. If you sign up for a free tier account with AWS, you're eligible for **750 hours** of RDS instances and **20GB** of storage. Even if after you have used up your free tier credits, the cost to host a MySQL database on Amazon RDS is still much lower compared to JawsDB. Therefore, I needed to modify the code in the GitHub repo to re-configure the add-ons. More on that later!

As mentioned above, in order to fix the site preview issue in Ghost, I had to create a proxy server, which is essentially a **Node.js** app, which is also hosted on Heroku.

## My blogging workflow

With this setup, here is my typical workflow just so that you can understand what it looks like:

1. **Edit site template**
  - Edit and test site locally
  - Commit and push changes to GitHub
  - Netlify automatically builds and deploys the site
2. **Publish new content**
  - Add/remove/edit posts locally and publish from the Ghost Admin Client app
  - Netlify automatically builds and deploys the site based on change detection settings in Netlify's build hook. Below is an image, taken from Ghost's website, just to give you an idea of what the UI for the Admin Client app looks like.  
 ![How I Created My Blog Using JAMStack](https://res-5.cloudinary.com/under-the-hood-learning/image/upload/q_auto/v1/blog_images/post-list-1600.png)

That's it. Sounds simple, huh?😎 Well, if you like what you hear and are still interested, join me in the next part of this series where I will be sharing tutorials on how I set up my site. See you there! 👋

## Photo Credits:

1. [Technology vector created by pch.vector - www.freepik.com](https://www.freepik.com/vectors/technology)
2. [Technology vector created by stories - www.freepik.com](https://www.freepik.com/vectors/technology)