How to create a blog using Hexo static site generator and free web hosting on GitLab Pages
Tags: tutorial, node, gitlab, beginners
Published: 2021-03-27 07:05:36

This is a complete tutorial on how to create a blog using a static website generator and free web hosting in 2021. It is better to have at least basic programming experience to proceed with the tutorial.

We will use [Hexo](https://hexo.io/) as a blog framework, [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) as a free hosting with HTTPS and a custom domain, [Node JS](https://nodejs.org) and [Git](https://git-scm.com/downloads).

In the end, I will give you a recommendation about website monitoring.

Let’s get started.

## What is a static site generator

A static website is a website that is not generated on every request on the server-side. Every time you visit a page, the server will return the same pre-generated content. 

Dynamic web pages, in contrast, may generate new content on every request. It may get data from the database or use business logic on the server-side to generate content.

A static site generator is an application that generates a website from templates or any other source. For example, Hexo generates HTML files from Markdown documents.

## Choose the best static website generator

There are a lot of static site generators. Choosing the best is not an easy task. Many of them use Javascript frameworks like ReactJS or VueJS. Not everyone knows those frameworks. So there is another category, which uses Markdown as an input.

Here are the most known generators I found with some stats from Github. Stats actual for March 2021.

[Hexo](https://hexo.io/)  
![Hexo GitHub stats](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/patnv0k45a0qo9fy9q12.png)
- used by 83.3K, 856 watchers
- 32.4K stars, 10.46 avg. stars/day
- 83 open issues, 3650 total issues 
- 152 contributors, 956 total pull requests 
- primary language is Javascript 
- last release version is 5.4.0

[Hugo](https://gohugo.io/)
![Hugo GitHub stats](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7okm2zdbl2yvdfdye6xp.png) 
- used by 65K, 1059 watchers
- 50.7K stars, 18.02 avg. stars/day
- 592 open issues, 5223 total issues
- 700 contributors, 3052 total pull requests 
- primary language is Go
- last release version is 0.81.0

[Jekyll](https://jekyllrb.com/)
![Jekyll GitHub stats](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ph9dnh4an1i46kx2zq2.png)  
- used by 1.1M, 1473 watchers
- 42.4K stars, 9.35 avg. stars/day
- 80 open issues, 4367 total issues
- 949 contributors, 4060 total pull requests
- primary language is Ruby
- last release version 4.2.0

Jekyll looks the best based on these simple stats. Hugo's major version number is still 0, and it has more issues than others.

The main reason for me is a primary language. I am using NodeJS a lot, so this technology may be easier for me in case of any bugs or whenever I need to extend some functionality with a plugin. 

That's why I choose Hexo there.

## Hexo installation
At first, you need to install [Node JS](https://nodejs.org) and [Git](https://git-scm.com/downloads) version control system, if you don't have it. I am using NodeJS version 14. You can install specific NodeJS using [NVM](https://github.com/nvm-sh/nvm) (Node Version Manager).

Then install Hexo globally. Run this command to install hexo-cli package.
```bash
npm install -g hexo-cli
```
I am using Hexo version 5.4.0.

## Create a new Project with Hexo

Initialize new Hexo project. Change "blog" to your desired project name.
```bash
hexo init blog
```

Go to the new folder and install project dependencies.
```bash
cd blog
npm install
```

Create a simple post with the command below.
```bash
hexo new post "My first post title"
```

You will see the new post file in the output.
```bash
INFO  Created: /app/source/_posts/My-first-post-title.md
```

Let's add some content to our first page. Copy content below to the "My-first-post-title.md" file.
```markdown
---
title: My first post title
date: 2021-03-16 06:19:49
tags:
---
# This is H1 header

This is content
```

Next, run Hexo server to preview your website and post. Enter the command below in your terminal to run a server locally.
```bash
hexo server
```
It will generate your website and serve generated files locally. So you can check how your website will look. If no errors, you will see this output:
```bash
INFO  Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.
```

Open provided ULR in a browser and check your website. 

That's it. Our simple website is ready to deploy.

For more information see Hexo [documentation](https://hexo.io/docs/index.html). Otherwise, use the help command instead of documentation. Just run `hexo help` in the terminal to see all available commands.

Let's continue with the deployment process to GitLab Pages.

## What is GitLab Pages

GitLab Pages is a simple hosting for static sites. You can host your website for free here. The main difference with a traditional hosting is that you publish a website directly from the repository.

We will use GitLab Pages here as a free web hosting in the tutorial and set up it with a custom domain and HTTPS. 

Here is the main alternative if you want to have a look: [GitHub Pages](https://pages.github.com/).

## Create a new GitLab repository

At first, create a new repository on the [GitLab website](https://gitlab.com/). Then run the command below in the project folder to initialize Git repository locally.
```bash
git init
```

Add your created remote GitLab repository to your local repository with this command:
```bash
git remote add origin <your_repository_link>
```

You can get your repository link from the GitLab new repository. After you created the repository, scroll down a little, and you will see the commands listed under the "Push an existing folder" section. 

Just copy commands from there. Here is my test repository commands screenshot as an example:  
![GitLab initialization commands](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgv8dqcfdr7ruwrmmyvm.png)  

Let's proceed with a deployment configuration.

## Add GitLab Deployment Configuration to the Project
The next step is to prepare a deployment configuration. 

Hexo is a static website generator. It doesn't store generated HTML files in the Git repository. That's why we need to re-generate files on every website update. 

Static files will be generated automatically at the GitLab side, every time you send updates to the remote repository with GitLab Continuous Delivery (CD) tool.   

Add the new file `.gitlab-ci.yml` to the root of your project with the content below.
```yaml
image: node:14
cache:
  paths:
    - node_modules/

before_script:
  - npm install hexo-cli -g
  - npm install

pages:
  script:
    - hexo generate
  artifacts:
    paths:
      - public
  only:
    - master
```
  
If you want to understand what this config does, here is a simple explanation:  
- `image` - here we specify Docker image. `node:14` is the official [Node JS Docker image](https://hub.docker.com/_/node/) with NodeJS version 14
- `cache:path:` - contains a folder to cache between jobs   
- `before_script` - contains scripts we want to run before any job  
- `pages` - contains job configuration  
- `pages:script` - script to run in the job. We will generate static pages with Hexo here  
- `artifacts:paths` - this folder with a generated website will be hosted at GitLab Pages and will be available in GitLab UI after the job finishes  
- `only` - conditions to run jobs, i.e. run this job only on the master branch  

Reference:
[Actual Hexo config](https://hexo.io/docs/gitlab-pages)  
[Actual GitLab yaml reference](https://docs.gitlab.com/ee/ci/yaml/README.html)

## Commit your Project
Commit is saving your changes to the local repository. To save the state of your project, run the commands below.
```bash
git add --all
git commit -m "Commit message, describing your changes"
```
Now we are ready for the deployment. Next, we need to set up the GitLab project.

## Create a Page on GitLab
Go to your GitLab repository and open `Settings - Pages`. Ensure that checkbox "Force HTTPS" is checked. Then press `New Domain` button and fill in your domain name.
![GitLab Pages New Domain](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqqsr6uhsjb23nb8ylqh.png)  

Make your page available: go to `Settings - General`, click to `Visibility, project features, permissions` and change configuration for Pages to **Everyone**
![GitLab Pages visibility](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pcnmjmlyn2j0ru08qfgi.png)

## Set up DNS records

The next step is to configure DNS records. Add **TXT** record in a domain DNS configuration to verify domain ownership. Then add **A** record with IP 35.185.44.232 to map your domain to GitLab Pages. 

Check the actual [GitLab Pages IP](https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/index.html#for-root-domains).

Here is how it looks for my domain in the CloudFlare Admin panel.
![CloudFlare DNS GitLab Pages TXT record example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y42xfot9orp8503fhnik.png)
![CloudFlare DNS GitLab Pages A record example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkzkt4eika1kuprfqu71.png)

## Enable GitLab Runners

Go to `Settings -> CI / CD -> Shared Runners` and click `Expand` in **Runners**. Enable **Shared Runners** if it is disabled.  
![GitLab Enable runners switch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oxfe8qmbwmckdhfrwsrx.png) 
A runner is an application that runs build and deployment jobs.   

## Upload your website to GitLab

Upload your local changes to the remote repository with the `push` command
```bash
git push -u origin master
```

After pushing GitLab CD automatically generate static files and update your website. You can see the running job in project `Settings - Pipelines` or `Jobs`.
![GitLab running pipeline example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4x9othv8sxov61oks2s.png)

It may take up to 30 minutes before the site is available after the first deployment. Then your website should be available by your domain.

Also, you can check it by GitLab URL. You can check URLs in the `Settings - Pages`.
![GitLab Pages available urlst](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7cnv43o1x2oiuhu8k2e.png)

Read my post [How to monitor the website](https://bogomolov.tech/how-to-monitor-website/) to know more.