Welcome to the comprehensive blog post where we will take you on an exciting journey to create your very own website using a static website generator and free web hosting. Don’t worry if you’re new to programming, we’ll guide you every step of the way.

In this tutorial, we will be using the powerful, simple and user-friendly blog framework called Hexo. Combined with GitLab Pages, a free hosting platform offering HTTPS support and the ability to use a custom domain, your website will have a professional and secure online presence. To bring our vision to life, we’ll leverage the capabilities of Node.js and Git, two essential tools in the web development world.

So, whether you’re an aspiring writer, a passionate blogger, or a business owner looking to establish a digital presence, this tutorial is your gateway to creating a captivating website. Let’s embark on this exciting journey together and unlock the potential of your online presence. Get ready to turn your ideas into reality as we dive into the world of website creation!

What is a static site generator

Let’s dive into the world of static websites. Unlike dynamic web pages that create new content on the every page load, static websites have pre-generated content that doesn’t change. Every time a visitor loads a page, they will receive the same pre-generated HTML page.

To make these static websites, we use special tools called static site generators. One popular example is Hexo, which takes documents written in Markdown and turns them into HTML files.

By using a static site generator like Hexo, you can have a website that’s efficient and consistent. It won’t change unless you want it to. So, let’s explore the magic of static websites and the power of these generators. Get ready for a journey of simplicity and captivating content!

Choose the best static website generator

When it comes to static site generators, the options are plentiful, making the task of selecting the best one quite challenging. Many of these generators rely on popular JavaScript frameworks like ReactJS or VueJS, which may not be familiar to everyone. However, there exists another category of generators that simplifies the process by using Markdown as the input method.

To help you navigate through this diverse landscape, I’ve compiled a list of well-known static site generators along with some insightful statistics sourced from GitHub. These statistics were last updated in March 2021, and there haven’t been significant changes as of June 2023.

So, without further ado, let’s explore the world of static site generators and discover which one could be the perfect fit for your needs.


Hexo GitHub stats - 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 GitHub stats - 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 GitHub stats - 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

Based on the simple analysis of the provided statistics, Jekyll emerges as the better choice, among the various options considered. A notable observation is that Hugo’s major version number remains at 0, indicating a less mature state, and it exhibits a higher number of reported issues compared to its counterparts.

For me personally, the determining factor lies in the primary language I frequently use. As I extensively utilize NodeJS in my work, opting for a static site generator built on this technology offers the advantage of familiarity and convenience. In the event of encountering any bugs or desiring to extend the functionality through the utilization of plugins, the NodeJS ecosystem seamlessly supports these endeavors.

Considering these factors, my preference ultimately lands on Hexo as the chosen static site generator. Its alignment with NodeJS aligns harmoniously with my workflow and ensures a smooth and hassle-free experience when it comes to both troubleshooting and expanding the website’s capabilities.

Hexo installation

To begin the journey of creating your blog with Hexo, there are a couple of prerequisites you’ll need to fulfill. First and foremost, make sure you have Node JS and Git version control system installed on your machine, if they are not already present. In my case, I’m utilizing NodeJS version 18. If you desire to install a specific version of NodeJS, you can utilize NVM (Node Version Manager) to conveniently manage different NodeJS versions.

Once you have Node JS and Git set up, the next step is to install Hexo globally on your system. You can accomplish this by executing the following command, which will install the hexo-cli package:

npm install -g hexo-cli

For the purpose of this tutorial, I will be using Hexo-cli version 4.3.1 and Hexo version 6.3.0 (tutorial updated in June 2023).

Create a new Project with Hexo

To kickstart your Hexo journey, let’s begin by initializing a new Hexo project. Feel free to replace “blog” with your desired project name. Execute the following command in your terminal:

hexo init blog

This command will create a new folder with the specified project name and initialize it as a Hexo project.

Once the project is initialized, navigate to the newly created folder and install the project dependencies by running the following command:

cd blog
npm install

This command will ensure that all the necessary dependencies for your Hexo project are installed. In the newest versions of Hexo, the command npm install might not be needed. However, it will not break anything, so it is better to run it in case dependencies are not installed during Hexo initialization.

Now, let’s create your first blog post. Use the following command to generate a simple post with your desired title:

hexo new post "My first post title"

Upon execution, you will see the output indicating the creation of a new post file:

INFO  Created: /app/source/_posts/My-first-post-title.md

You can find the newly generated post file at the specified location.

Let’s add some content to our first post. Copy and paste the following content into the “My-first-post-title.md” file:

title: My first post title
date: 2023-06-11 12:00:00
# This is H1 header

This is content

Now, let’s preview your website and post by running the Hexo server locally. Simply enter the following command in your terminal:

hexo server

This command will generate your website and serve the generated files locally. You can then open your preferred browser and navigate to the provided URL (http://localhost:4000) to see how your website and post appear. If no errors occur, you will see the following output:

INFO  Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.

Take this opportunity to explore your website and ensure everything looks as expected.

Congratulations! Your simple Hexo website is now ready to be deployed. You can refer to the Hexo documentation for further information. Alternatively, if you need help with any specific commands, you can use the hexo help command in your terminal to access a list of available commands.

In the next section, we will continue with the deployment process to GitLab Pages.

What is GitLab Pages

When it comes to hosting your static website, GitLab Pages emerges as a convenient and user-friendly option. What sets it apart from traditional hosting services is its seamless integration with your GitLab repository, enabling you to publish your website directly from the repository itself.

In this tutorial, we will utilize GitLab Pages as our chosen hosting solution, leveraging its free web hosting capabilities. Not only will you be able to host your website without incurring any costs, but we will also delve into the process of configuring GitLab Pages to utilize a custom domain and ensure HTTPS encryption for enhanced security.

While GitLab Pages takes center stage in our tutorial, it’s worth mentioning an alternative option that you may find interesting to explore: GitHub Pages. Both GitLab Pages and GitHub Pages provide similar functionality, allowing you to host your static website effortlessly. The choice ultimately depends on your preferences and the specific requirements of your project.

Create a new GitLab repository

Let’s create a new repository (blank project) on the GitLab website. Once you have created the repository, navigate to your project folder and initialize a Git repository locally using the following command:

git init

This command sets up a local Git repository within your project folder, allowing you to manage version control for your files.

Next, you need to connect your local repository to the remote GitLab repository you just created. To do this, run the following command:

git remote add origin <your_repository_link>

Replace <your_repository_link> with the URL of your GitLab repository. You can obtain this link from the GitLab website by navigating to your repository and scrolling down to the “Push an existing folder” section. There, you will find the necessary commands listed. Simply copy the command provided and execute it in your terminal.

To give you an example, here is a screenshot of the commands from my test repository on GitLab:

GitLab initialization commands

With the Git repository now configured, let’s proceed to the next step, which involves setting up the deployment configuration for your website.

Add GitLab Deployment Configuration to the Project

Moving on, let’s move towards preparing a deployment configuration for your Hexo website.

Since Hexo is a static website generator, it doesn’t store the generated HTML files directly in the Git repository. Consequently, we need to ensure that the files are regenerated each time there is an update to the website.

To achieve this, we will leverage the power of GitLab’s Continuous Delivery (CD) tool. With GitLab CD, static files will be automatically generated on the GitLab side whenever you push updates to the remote repository.

To initiate the deployment configuration, create a new file named .gitlab-ci.yml at the root of your project. You can easily add this file by following the steps below:

Open a text editor of your choice I prefer Jetbrains products. If you need a fee editor, I suggest you to use Visual Studio Code.
Create a new file and save it as .gitlab-ci.yml.
Copy and paste the following content into the file:

image: node:18
    - node_modules/

  - npm install hexo-cli -g
  - npm install

    - hexo generate
      - public
    - master

This configuration file specifies the steps that GitLab will perform during the deployment process. In this case, it instructs GitLab to execute the hexo generate command, which regenerates the static files for your Hexo website. The generated files will be stored in the public folder.

Here is a simple explanation for some parameters:

  • image - here we specify Docker image. node:18 is the official Node JS Docker image with NodeJS version 18
  • 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

By following these steps and adding the provided content to your .gitlab-ci.yml file, you will have set up the necessary deployment configuration for your Hexo website on GitLab.

Actual Hexo config
Actual GitLab yaml reference

Save (commit) your Project

Before we proceed with the deployment process, it’s important to save the changes you’ve made to your local repository by committing them. Committing allows you to capture the current state of your project and serves as a way to track and manage your modifications effectively.

To commit your changes, follow the commands below in your terminal:

git add --all
git commit -m "Commit message, describing your changes"

The first command, git add --all, stages all the changes you’ve made, including new files, modified files, and deleted files. This prepares them for the commit.

The second command, git commit -m "Commit message, describing your changes", creates a commit with a descriptive message that summarizes the changes you’ve made. It’s essential to provide a meaningful and concise message to help you and other collaborators understand the purpose of the commit.

Once you’ve committed your changes, you’re now ready to proceed with the deployment process. In the next steps, we will set up the GitLab project to ensure that your website is hosted and made accessible to others.

Enable GitLab Runners

GitLab Runners play a vital role in executing build and deployment jobs within the GitLab CI/CD pipeline. These runners are standalone applications that are responsible for processing the tasks associated with your projects, such as building, testing, and deploying your code.

To enable the shared runners in GitLab and ensure that your build and deployment jobs can be executed, follow the steps below:

  1. Navigate to your GitLab project’s Settings and select CI/CD.
  2. Under the CI/CD settings, locate the Shared Runners section and click on Expand.
  3. Check if the Shared Runners option is already enabled. If it is disabled, toggle the switch to enable it.
  4. Enabling shared runners allows your project to utilize the available GitLab runners, which are responsible for running your build and deployment jobs.

Here is a visual representation of the option to enable shared runners in GitLab:

Enabling Shared Runners in GitLab:

GitLab Enable runners switch

By enabling shared runners, you ensure that your build and deployment jobs can be executed using the available GitLab runners, facilitating the smooth execution of your project’s CI/CD pipeline.

Upload your website to GitLab

To deploy your changes and update your website on GitLab Pages, follow these steps.

  1. Upload your local changes to the remote repository by running the push command:
git push -u origin master

This command will push your local changes to the master branch of your GitLab repository.

  1. Once the changes are pushed, GitLab’s Continuous Delivery (CD) system will automatically generate the static files and update your website. You can monitor the progress of this process by navigating to your project’s Settings and selecting either Pipelines or Jobs. Here, you will be able to see the running job related to the deployment process.
GitLab running pipeline example

Depending on the complexity of your website and the size of the changes, it may take some time for the deployment process to complete. In some cases, it can take up to 30 minutes for the site to become available after the initial deployment.

  1. Once the deployment process is finished, your website should be accessible via your custom domain. You can also check the availability of your website by visiting the URLs provided in the Settings section of your GitLab project under Pages. See the section below on how to set up your custom domain.
GitLab Pages available urls

By following these steps, you can ensure that your changes are successfully deployed to GitLab Pages and that your website is updated accordingly.

Create a Page on GitLab

To configure your GitLab project for deployment and make your website accessible, follow the steps below:

  1. Open your GitLab repository and navigate to the Operate tab. From there, select Pages.
  2. In the Pages settings, ensure that the checkbox labeled “Force HTTPS” is checked. Enabling this option ensures that your website will be served securely over HTTPS.
  3. Next, click the New Domain button to add your custom domain. Enter your desired domain name in the provided field. This allows you to access your website using your own domain instead of the default GitLab Pages URL.
  4. To make your page available to everyone, go to the Settings tab once again and select General. From there, click on Visibility, project features, permissions.
  5. In the configuration options, locate the section related to Pages and change the settings to Everyone. This ensures that your website is accessible to all visitors.
    To assist you in visualizing the steps, here are two screenshots showcasing the respective settings:

Adding a new domain in GitLab Pages:

GitLab Pages New Domain

Setting the visibility of your GitLab Pages:

GitLab Pages visibility

By following these steps and adjusting the necessary settings, you will successfully configure your GitLab project for deployment and make your website available to a broader audience.

Set up DNS records

To configure the DNS records for your domain and ensure it is properly connected to GitLab Pages, follow these steps:

  1. Begin by adding a TXT record in your domain’s DNS configuration. This record is required to verify domain ownership. Refer to your domain registrar or DNS provider’s documentation on how to add a new DNS record. Enter the necessary values provided by GitLab to complete the verification process.
  2. Next, add an A record to map your domain to GitLab Pages. The IP address to use is This allows requests to your domain to be directed to GitLab Pages and serve your website.
  3. It’s important to note that the IP address for GitLab Pages may change, so it’s recommended to check the GitLab Pages documentation for the most up-to-date IP address.

To help you visualize the process, here are examples of how it looks in the Cloudflare Admin panel for adding the TXT and A records:

Adding a TXT record in Cloudflare:

CloudFlare DNS GitLab Pages TXT record example

Adding an A record in Cloudflare:

CloudFlare DNS GitLab Pages A record example

By following these steps and configuring the necessary DNS records, you will successfully connect your domain to GitLab Pages and make your website accessible under your custom domain.

Preview Your Website

Open it in the browser and take a look to ensure that everything is functioning correctly and appears as expected.

If you have successfully completed all the steps outlined above, you will now have the satisfaction of seeing your website come to life. Congratulations on your accomplishment! Your hard work has paid off, and you now have a fully functional website that is ready to be explored by visitors from around the world.

The journey doesn’t end here though. With your website up and running, you have the exciting opportunity to create engaging content and share your thoughts, ideas, and stories with your audience. Take advantage of the knowledge you have gained and leverage the steps mentioned earlier to write captivating blog posts. You can easily upload your newly created content by following the same steps outlined throughout this tutorial.

Embrace this moment and embark on your blogging journey with confidence. The possibilities are endless, and your website is the canvas for your creativity. Happy writing and best of luck on your blogging endeavors!

What are the alternatives to GitLab Pages

In the realm of hosting options for static websites, there are plenty of alternatives to GitLab Pages exists, each with its own unique features and advantages. Popular alternatives include GitHub Pages, Heroku, Netlify, Cloudflare Pages, and many more. While the choice of hosting service largely depends on individual preferences and project requirements, this tutorial focuses on GitLab Pages due to its initial adoption.

However, it’s important to note that over time, I have conducted extensive performance testing and optimization to identify the most suitable hosting solution. As of June 2023, I have made the decision to transition to Cloudflare Pages based on its exceptional performance and feature set.


That brings us to the end of this tutorial. I sincerely hope you found it informative and engaging. If you encountered any challenges or have any feedback to share about the tutorial, I encourage you to reach out and let me know.

If you have any questions, concerns, or simply want to share your thoughts, you can easily connect with me on Twitter. I would love to hear from you and address any queries or issues you may have. Please feel free to leave a comment or send me a tweet describing your experience with the tutorial.