DEV Community

Noan
Noan

Posted on

How to create a blog with GitLab Pages

If you to need to host a blog, GitLab can help to build and host it with GitLab Pages. In this tutorial we'll use GitLab CI and Jekyll to deploy your blog. This is the configuration I use for my personal website.

Prerequisites

Have a project hosted on GitLab

1. Create and build your blog locally

1.1 Create a homepage and an article

cd my-project
Enter fullscreen mode Exit fullscreen mode

In index.html

---
---
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My first blog</title>
    </head>

    <body>
        <section>
            <h2>
            <!-- {{ link | absolute_url}} is a 'Liquid' expression Jekyll will interpret to prefix the link with the url and the base_url previously defined  -->
                <a href="{{'/articles/my-first-article.html' | absolute_url}}">My first article</a>
            </h2>
        </section>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

The 2 dashed lines at the top of the markdown file define your Front Matter, this is a .yml configuration section for your page we will talk about later

In articles/my-first-article.html

---
---
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My first article</title>
</head>
<body>
    <p>Hi Mom</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

In Gemfile

source "https://rubygems.org"

gem "jekyll"
Enter fullscreen mode Exit fullscreen mode

In _config.yml

baseurl: /<name_of_your_gitlab_project>
Enter fullscreen mode Exit fullscreen mode

1.2 Test locally with Jekyll

So you do not have to run the GitLab pipeline to ensure your blog's code does not have bugs.

This tutorial has been tested on Ubuntu 24.04 (some commands in this section may not be adapted to your OS)
Useful links:

Install ruby (via rbenv) and Jekyll

# Install dependencies to run ruby
sudo apt update && sudo apt install -y git curl build-essential libz-dev libffi-dev libssl-dev libyaml-dev

# Clone rbenv and install it
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
~/.rbenv/bin/rbenv init
source ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
Enter fullscreen mode Exit fullscreen mode

Then find the latest stable release of ruby with

rbenv install -l
Enter fullscreen mode Exit fullscreen mode

We will remember it as RUBY_VERSION, replace RUBY_VERSION in the following commands with the version you have found.

# Install and use a ruby environment
rbenv install RUBY_VERSION
rbenv global RUBY_VERSION

# Install bundler and install the blog's dependencies
gem install bundler
bundle install
Enter fullscreen mode Exit fullscreen mode

Serve the blog

bundle exec jekyll serve
Enter fullscreen mode Exit fullscreen mode

Your changes are visible at http://localhost:4000/

1.3. Ignore the files Jekyll has created

In your .gitignore

_site/
Enter fullscreen mode Exit fullscreen mode

2. Use GitLab CI to build and deploy your website

In your .gitlab-ci.yml

image: ruby:RUBY_VERSION

pages:
  script:
    - gem install bundler
    - bundle install
    - bundle exec jekyll build -d public
  artifacts:
    paths:
      - public
Enter fullscreen mode Exit fullscreen mode

And push

git add .
git commit -m "Gitlab pages setup"
git push
Enter fullscreen mode Exit fullscreen mode

The pipeline deploying your project is visible on your project's home on GitLab, under Build/Pipelines.

3. Visit your website

On your project's home on GitLab, navigate to Deploy/Pages to see your website's URL.

Uncheck Use unique domain if you want your blog to be accessible from a more user-friendly URL, but keep in mind HTTPS won't work for.gitlab.io domains if your username or project name contains a dot (you can still set up your own domain).

4. (Optional) Write your blog in Markdown

One major feature of Jekyll is to translate Markdown files into an HTML website.

4.1. Tell Jekyll you'll be using Markdown

In _config.yml

markdown: kramdown
baseurl: /<name_of_your_gitlab_project>
Enter fullscreen mode Exit fullscreen mode

4.2. Change your article to Markdown

Remove the file articles/my-first-article.html

In articles/my-first-article.md

---
---
# Hi Mom
Hope you're fine
Enter fullscreen mode Exit fullscreen mode

Run bundle exec jekyll build and you should find your translated HTML file under _site/articles/my-first-article.html

<h1 id="hi-mom">Hi Mom</h1>

<p>Hope you’re fine</p>
Enter fullscreen mode Exit fullscreen mode

This page is missing basic HTML structure and metadata. We could write our Markdown inside an HTML canvas, but this would lead in repetitions in our code, let's take advantage of Jekyll layout features.

4.3 Define a layout for your posts

In _layouts/default.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>{{ page.title }}</title>
    <!--
        You may add any stylesheet or script you'd like to use
        <link rel="stylesheet" href="'/assets/main.css'"> 
        -->
</head>

<body>
    <header>
    <nav><a href="{{'/' | absolute_url}}">My first blog</a></nav>
    </header>
    <main>
        {{ content }} <!-- Your content will go here -->
    </main>

</body>

</html>
Enter fullscreen mode Exit fullscreen mode

And then edit the file articles/my-first-article.md and make use of the Front Matter

---
title: My first article
layout: default
---

# Hi Mom

Hope you're fine
Enter fullscreen mode Exit fullscreen mode

Test it with bundle exec jekyll build or bundle exec jekyll serve, once you're confident in your changes push them and let GitLab do the rest.

5. (Optional) Preview your changes before publishing them

In a development process, we usually want to review changes we have made before publishing them. This could also apply to a blog.

5.1. Prevent the pages' publication if the pipeline does not belong to the main branch

In .gitlab-ci.yml

image: ruby:RUBY_VERSION

pages:
  script:
    - gem install bundler
    - bundle install
    - bundle exec jekyll build -d public
  artifacts:
    paths:
      - public
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # This rule prevents the pages job from being executed for a commit that is not made on the main branch

Enter fullscreen mode Exit fullscreen mode

5.2. Create another job only for MR which will upload a preview version of the blog

Add a file named generate_pipeline_config.sh

# Outputs a configuration which will later be used by jekyll to generate the website and make links that points to the website-as-artifact generated
echo "url: https://$CI_PROJECT_NAMESPACE.gitlab.io"
echo "baseurl: /-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public"
Enter fullscreen mode Exit fullscreen mode

And make it executable

chmod +x generate_pipeline_config.sh
Enter fullscreen mode Exit fullscreen mode

In .gitlab-ci.yml

stages: # This is new
  - staging
  - pages
pages:
  stage: pages
  script:
    - gem install bundler
    - bundle install
    - bundle exec jekyll build -d public
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # This rule prevent the pages job to be executed for commit not made on the main branch
  artifacts:
    paths:
      - public

preview-pages: # This is almost the same job, as it is not named 'pages' the job will not publish its result on GitLab Pages
  stage: staging
  script:
    - gem install bundler
    - bundle install
    # The 2 following lines are modified
    - ./generate_pipeline_config.sh > pipeline_config.yml
    - bundle exec jekyll build -c _config.yml,pipeline_config.yml -d public # pipeline_config.yml redefines some variable from _config.yml
  rules:
    - if: $CI_MERGE_REQUEST_IID # This rule to execute the job only if it is part of a merge request
  environment:
    name: $CI_COMMIT_REF_NAME
    # The environment is a link to the artifact produced by the pipeline
    url: https://$CI_PROJECT_NAMESPACE.gitlab.io/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public/index.html
  artifacts:
    paths:
      - public
Enter fullscreen mode Exit fullscreen mode

Create an MR with your changes.
The environment section tells GitLab you have deployed something at a certain URL.
On the MR overview it suggests the reader to visit the website you have just deployed.
Overview of the MR in GitLab

Some links will not work in the preview. The artifact browsing server we are using is not made to be a web server. Contrary to the GitLab Pages server it will not return /index.html if you ask for /, neither will it return /articles/my-first-article.html you requested /articles/my-first-article. You can choose between writing exclusively explicit links or rewrite the url in your browser when browsing the preview

Top comments (0)