Deploy docsify.js using Gitlab Pages with a Preview Environment

Adam Ben Shmuel
4 min readDec 18, 2020

--

One of the biggest challenges our engineering team faces is our knowledge management and documentation.
We searched for the right platform that would give us a standard and simple platform for writing documentation while improving the speed of creating and changing documentation used by our team.

We ended up choosing docsify.js as our knowledge management platform of choice for three main reasons:

  1. Single standard: Documentation is written in Markdown which is all complied in a similar manner giving a similar look across all of our documentation.
  2. Reviewable: We want to treat our documentation in the same way that we treat our code. Documentation is added through merge requests and reviewed by other team members in order to keep a high standard when writing documentation.
  3. Costs: Usage of GitLab Pages allows us to deploy a secure website for our documentation without any additional costs (other than running Gitlab CI jobs for deployments which has a free monthly quota as well).

The structure of our knowledge base is quite straightforward and an example repo exists on GitLab: example project.

First: Create a documentation project repo

You may use our setup:

. 
└── documentation/ # Project Repo
├── docs/ # Actual Documentation
│ ├── services/
│ │ ├── example-service.md
│ │ └── another-service.md
│ └── services.md
│ ├── tutorial/
| │ └── _media/ # Images and such
| │ | └── example-tutorial/
│ | | └── example-image.jpg
│ │ └── example-tutorial.md
│ └── tutorial.md
│ ├── _coverpage.md # Landing page
│ ├── _homepage.md # Content of homepage
│ ├── _sidebar.md # Content of sidebar
├── index.html # The sites page
├── README.md # Repo README
└── gitlab-ci.yml # GitLab CI configurations

Second: Configure docsify.js settings

  • Edit the index.html file in order to use docsify.js correctly:
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta charset="UTF-8">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/buble.css" />
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.css" />
<title>Example Docs</title>
</head>

<body>
<div id="app"></div>
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script>
window.$docsify = {
el: "#app",
basePath: "$DOCSIFY_BASE_PATH",
loadSidebar: true,
coverpage: true
}
</script>
</body>

</html>

Notice that we use the token $DOCSIFY_BASE_PATH.
We are going to tokenize the value through the GitLab CI pipeline definition.

  • Bonus: add mermaid.js 🧜‍♀️ (Check out their documentation — they use docsify as well! 🚀) support:
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta charset="UTF-8">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/buble.css" />
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.css" />
<title>Example Docs</title>
</head>

<body>
<div id="app"></div>
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="//cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
var num = 0;
mermaid.initialize({ startOnLoad: false });
window.$docsify = {
el: "#app",
basePath: "$DOCSIFY_BASE_PATH",
loadSidebar: true,
coverpage: true,
markdown: {
renderer: {
code: function(code, lang) {
if (lang === "mermaid") {
return (
'<div class="mermaid">' + mermaid.render('mermaid-svg-' + num++, code) + "</div>"
);
}
return this.origin.code.apply(this, arguments);
}
}
}
}
</script>
</body>

</html>

Third: Configure GitLab CI for GitLab Pages deployments and a Preview environment

  • Deployment to GitLab Pages:
stages:
- test
- deploy

pages:
image:
name: cirocosta/alpine-envsubst:latest
entrypoint: [""]
variables:
DOCSIFY_BASE_PATH: https://GROUP_NAME.gitlab.io/-/PROJECT_PATH/docs
docsify: $docsify
stage: deploy
script:
- mkdir .public
- mv index.html .index.html
- envsubst < ".index.html" > "index.html"
- rm -f .index.html
- cp -r * .public
- mv .public public
- ls
artifacts:
paths:
- public
only:
- master
  • Creation of a Preview Environment:
"Create Preview Environment":
extends: pages
variables:
DOCSIFY_BASE_PATH: https://GROUP_NAME.gitlab.io/-/PROJECT_PATH/-/jobs/$CI_JOB_ID/artifacts/public/docs
script:
- mkdir .public
- envsubst < "index.html" > ".index.html"
- envsubst < ".index.html" > "index.html"
- rm -f .index.html
- cp -r * .public
- mv .public public
stage: test
only:
- merge_requests

With everything together, your gitlab-ci.yml file should look something like this:

stages:
- test
- deploy

pages:
image:
name: cirocosta/alpine-envsubst:latest
entrypoint: [""]
variables:
DOCSIFY_BASE_PATH: https://GROUP_NAME.gitlab.io/-/PROJECT_PATH/docs
docsify: $docsify
stage: deploy
script:
- mkdir .public
- mv index.html .index.html
- envsubst < ".index.html" > "index.html"
- rm -f .index.html
- cp -r * .public
- mv .public public
- ls
artifacts:
paths:
- public
only:
- master

"Create Preview Environment":
extends: pages
variables:
DOCSIFY_BASE_PATH: https://GROUP_NAME.gitlab.io/-/PROJECT_PATH/-/jobs/$CI_JOB_ID/artifacts/public/docs
script:
- mkdir .public
- envsubst < "index.html" > ".index.html"
- envsubst < ".index.html" > "index.html"
- rm -f .index.html
- cp -r * .public
- mv .public public
stage: test
only:
- merge_requests

Fourth: Use Preview environment for a better developer experience:

As done in the previous step, we configured the job: “Create Preview Environment” which uses GitLab’s artifacts feature in order to load the static files that are needed to run our live preview site.
Once a merge request with new changes is created, an automatic job runs. Once the job completes successfully, the preview environment will be available at:

https://GROUP_NAME.gitlab.io/-/PATH_TO_PROJECT/-/jobs/CI_JOB_ID/artifacts/public/index.html

You can find the CI_JOB_ID by:
Click on the pipeline from within the merge request:

Click on the job:

Copy the Job ID:

Now we can review our changes on the preview environment before merging our changes into the production branch that deploys to our documentation website.

--

--

Adam Ben Shmuel

Cloud group manager 🚀. Could talk for hours about the cloud and about management!