Name Last Update
.gitlab Loading commit data...
bin Loading commit data...
data Loading commit data...
doc Loading commit data...
extensions Loading commit data...
generators Loading commit data...
lib Loading commit data...
source Loading commit data...
spec Loading commit data...
.gitignore Loading commit data...
.gitlab-ci.yml Loading commit data...
.rspec Loading commit data...
.ruby-version Loading commit data...
.scss-lint.yml Loading commit data...
CONTRIBUTING.md Loading commit data...
Gemfile Loading commit data...
Gemfile.lock Loading commit data...
LICENCE Loading commit data...
README.md Loading commit data...
Rakefile Loading commit data...
add_member_to_team_page.md Loading commit data...
comparison_pdfs.sh Loading commit data...
config.rb Loading commit data...
config.ru Loading commit data...
md_page.md Loading commit data...
pdf_template.tex Loading commit data...


This is the source for the https://about.gitlab.com/ site. For a guide on how to start editing the website using git, see the handbook page on that topic.

Local development

bundle install

bundle exec middleman

Once the Middleman server is running, you can visit http://localhost:4567 in your browser to see a live, local preview of the site. Any changes to files in the source directory will be detected automatically, and your browser will even reload the page if necessary.

PDF files are not available in development mode. See below for more information.

See the Middleman docs for more information.

Enable livereloading

When running middleman with the livereload option enabled, it watches your repo for changes and reloads the site automatically.

Livereload can result to slow server response times, so it is disabled by default. That means you need to manually refresh the webpage if you make any changes to the source files. To enable it, just set the environment variable ENABLE_LIVERELOAD=1 before running middleman:

ENABLE_LIVERELOAD=1 bundle exec middleman

You can verify that it's enabled from the following line:

== LiveReload accepting connections from ws://

To permanently have livereload enabled without typing the environment variable, just export its value in your shell's configuration file:

# Open your rc file (replace editor with vim, emacs, nano, atom, etc.)
editor ~/.bashrc

# Export the livereload variable

Note: You need to logout and login in order for the changes to take effect. To temporarily use the changes, run source ~/.bashrc.

Next time you login, livereload will be always enabled and you can just run middleman to start the local server to preview the changes.


Blog posts

Please read through the Blog Handbook before you begin.

A new blog post likely needs to be reviewed by others before being published, so it's best to use our standard feature branch workflow and to open a Merge Request. If you're not yet comfortable using the Git command line, you can create a branch in the GitLab UI.

Blog posts go in source/posts/ and must be named to match the following format: yyyy-mm-dd-the-post-title.html.md.

Because the formatting of the filename is important and specific, it's best to generate the file for a new blog post interactively in your terminal by using the new_post Rake task:

bundle exec rake new_post

When prompted, enter the blog post title, without a date, and press Enter. A message will be printed to tell you the path to the new file.

Open the file in your text editor of choice. The file will be empty except for a few lines at the top, surrounded by a pair of three hyphens (---). These lines are called Frontmatter.

The title attribute has already been filled out by the new_post Rake task. Fill in the others as needed, or remove any that aren't applicable to your post (not every post needs an image, for example).

If you need more fine-grained control over blog post ordering, or publication time, add a date attribute to the frontmatter with a UTC-based time. For example:

title: "Example Blog Post"
date: 2017-04-01 15:45

If no date attribute is supplied, it will be inferred from the filename.

When adding timestamps to blog posts, be warned: setting it too far into the future will cause the post to not be published until that time has passed. Because builds are only triggered on new commits to master, you might set a blog post to publish in a few hours, but it might not be published for days if no one makes a new commit after that time has passed.

When in doubt, either don't give it a timestamp, or set it to a time that has already passed.

Fill in the post's content using Markdown. To preview your post locally before publishing, see Local development for instructions.

Adding yourself to the team page

Edit data/team.yml and add a new entry for yourself (or update the placeholder with your initials).

Images should be square, and should be uploaded to source/images/team.

Adding a pet to the team pets page

Edit data/pets.yml and add a new entry.

Images should be uploaded to source/images/team/pets.

Adding an application to the applications page

Adding a new application

Edit data/applications.yml and add a new entry within the correct categories applications list.

Please add a .png image to source/images/applications/apps, the name of the image should be the same as the title, but with underscores instead of spaces.


  - title: My new application
    content: My new application description.
      - url: https://my-new-application.io
        title: my-new-application.io
      - ...

The image should be located in source/images/applications/apps/my_new_application.png.

The application content string will be truncated to 100 characters. Please do not include any HTML tags.

The application links list will be truncated to 3 links.

Adding a new category

If you need to create a new category, you can do so.

Please add an .svg image to source/images/applications/categories, the name of the image should be the same as the category id, but with underscores instead of hyphens.


- title: My new category
  id: my-new-category
    - ...
    - ...

The image should be located in source/images/applications/categories/my_new_category.svg.

Updating the promotion link

This link appears at the top of the homepage and can be used to promote new versions or upcoming events.

Edit data/promo.yml to update the link and text properties.

Press releases page

The press releases page follows the same principle like the blog archives. It is automatically populated by the data fed into data/press.yml.

As you can see, there are three values, title, link and date. Here's a short explanation what each does.

Value Description
title The headline of the article, make sure to include it inside double quotes and remove the trailing period if any.
link The URL that links back to the article. If a press release is hosted on our website, you must first create a blog post with the press release. Create it like any other blog post and make sure to include the categories: press in the frontmatter. The category is essential if you want the post to appear in the press category. That way we can have a list of press posts hosted on our website.
date The date should be in ISO format as stated in the handbooks's Writing Style Guidelines (see bullet 4). Make sure to make this right as this value is used make the links listed in descending order (newest to oldest).

Create a new press release page under /press/releases

There are two ways to create a new press release page that will be hosted under /press/releases. You can use the automatic way using the command line or edit the files manually with your text editor.

Using the raketask to create a new press release page

Assuming you have cloned the repository, you have Ruby installed and have ran bundle install, here are the steps needed to create a new press release page automatically:

  1. Go to the root directory of www-gitlab-com
  2. Create a new branch: git checkout -b press-release-branch
  3. Run the following:

    rake new_press

    You will be asked two questions, 1) the date of the press release in ISO format, 2) the title of the press release.

    These data will be used to automatically create a new file source/press/releases/{date}-{title}.html.md and will also populate data/press.yml with the right information.

  4. Add content to the new press release file according to our Markdown guide.

  5. Add the changed files and commit the changes:

    git add data press
    git commit -m "New press release"
    git push origin press-release-branch
  6. Create a new merge request.

Manually create a new press release page

You need to do 2 things:

  1. Create a new file under source/press/releases/ with its filename ending in .html.md. An example of such a page would be source/press/releases/2016-01-01-new-press-release.html.md. Its contents should always start with the following block:

    layout: markdown_page
    title: "New press release!"

    The only thing you may change to your liking is the title. Leave everything else as-is. Once you have created that block you may add the content according to our Markdown guide.

  2. Follow the steps outlined in the section Add an internal URL to the press releases archive manually

Add an existing URL to the press releases archive using the raketask

  1. Go to the root directory of www-gitlab-com
  2. Create a new branch: git checkout -b press-release-branch
  3. Run the following:

    rake add_press

    You will be asked three questions, 1) the date of the press release in ISO format, 2) the title of the press release, and 3) the URL of the press release.

    These data will be used to automatically populate data/press.yml with the right information.

  4. Add the changed file and commit the changes:

    git add data
    git commit -m "New press release"
    git push origin press-release-branch
  5. Create a new merge request.

Add an existing URL to the press releases archive manually

To add an existing URL under about.gitlab.com in the press releases page, follow the steps below:

  1. Open data/press.yml with an editor (do not use Microsoft Word).
  2. Copy paste the previous block leaving a newline between.
  3. Add your own title, date and link.
  4. Visit http://localhost:4567/press/releases/ and make sure it appears in the list.
  5. When ready, commit the changes, push to the repository and open a MR for review.

Update the features page (under /features)

The feature page grabs its content automatically from the file /data/features.yml.

Create or update the comparison pages (under /comparison)

The comparison page grabs its content automatically from the files under data/comparisons/.

There are 3 files in total which you need to create or edit:

  • data/comparisons/gitlab_vs_competitor.yml: Create for new comparisons. Every comparison page has its own yaml file. Use underscores
  • source/comparison/gitlab-vs-competitor.html.haml: Create for new comparisons. Every comparison page has its own html file. Use dashes
  • source/includes/comparison_table.html.haml: Edit for new or existing comparisons.

Step 1

Add a new yaml file named after the comparison using underscores: data/comparisons/gitlab_vs_competitor.yml. You can start by copying an existing one and then changing its content. Yaml files are sensitive to indentation, so be extra careful. Make sure that you follow the structure below:

title: "Competitor vs GitLab"
pdf: gitlab-vs-competitor.pdf
  name: 'GitLab'
  logo: '/images/comparison/gitlab-logo.svg'
  name: 'Competitor'
  logo: '/images/comparison/competitor-logo.svg'
last_updated: 'May 5, 2017'
  - title: "Briefly explain the feature"
    description: |
      Describe the differences in detail. This text can span in multiple
      lines without interfering with its structure. It will always appear
      as one paragraph.
    link_description: "Learn more about Feature Name."
    link: "link to GitLab's feature page documentation or blog post"
    competitor_one: true
    competitor_two: true


  • Although the file is named with GitLab being first, the title should have the competitor name first.
  • The pdf name should be similar to the yaml file name, but with dashes. In short, it has to match the HTML page name in step 2. If you want to omit the PDF link altogether, set its value to null, like: pdf: 'null'.
  • Remember to update the date every time you make a change.
  • The competitor's logo (competitor_two) can be svg or png. Save it in source/images/comparison/competitor-logo.svg.
  • In the features area, competitor_one is always GitLab, and competitor_two is the competitor we are compared against. Values for these two fields are true|false|sortof.

Step 2

Add a new haml file named after the comparison using dashes: source/comparison/gitlab-vs-competitor.html.haml. You can start by copying an existing one and then editing it. The only change you need to make is the name of the yaml file you created above:

layout: comparison_page
trial_bar: true
title: GitLab compared to other tools
suppress_header: true
image_title: '/images/comparison/title_image.png'
  - compared.css
  - comparison.js

- data.comparisons.gitlab_vs_competitor do |comparison_block|
  = partial "includes/comparison_table", locals: { comparison_block: comparison_block }

Step 3

As a last step, you need to add the new page in the dropdown menu. To do that, open source/includes/comparison_table.html.haml and add an entry of your newly added comparison page. Again, you can copy one of the entries you'll find inside and just change its content. Haml files are sensitive to indentation, so be extra careful:

  = highlight_active_nav_link("Competitor vs. GitLab", "/comparison/gitlab-vs-competitor.html#dropdown")

Step 4

If you followed the above 3 steps, the new comparison page should be reachable under /comparison/gitlab-vs-competitor.html and you should see it in the dropdown menu. The last thing you need to do is create the PDF. Follow the info in creating comparison PDFs.

Update the release list page (under /release-list)

The release list page grabs its content automatically by crawling the blog and retrieving the headers from the blog post.

Edit /generators/release_list.rb and modify two elements:

  1. Add the new version to the table listing the versions

    VERSIONS = [
      "8.11", "8.10", "8.9", "8.8", "8.7", "8.6", "8.5", "8.4", "8.3","8.2","8.1","8.0","7.14","7.13","7.12","7.11","7.10",
  2. Update the year and month according to the current date. Note that you should only indicate a month for which we already have a public blog post announcing the release. That means, if we are on Sept 19th and the next release scheduled for the 22th is 8.12, the month should be 8 (i.e August for 8.11), not 9.

    year = 2016
    month = 8
  3. Commit the changes.

The release-list page will be updated after bundle exec rake build.

Update the projects page (under /handbook/engineering/projects)

GitLab Engineering Projects page is generated using information stored in data/projects.yml and data/team.yml files. Edit these files to add a project and assign product owners / maintainers / reviewers.

  • Typically, product owner is a Product Team member whose responsibilities include having a vision of a project's development, scheduling a work and allocating required resources.

  • Maintainer is usually a team member who is responsible for the final review and has ability to merge changes into the master branch / default branch.

  • A reviewer is a team member who is responsible for reviewing changes and providing a quick feedback during multiple review iterations.

To assign someone to a project it is necessary to add a projects section to team member's entry in data/team.yml. See an example below.

- name: Full Name
  locality: Some City
  # [...]
  gitlab: gitlab-com-handle
    some-project: owner
    gitlab-ce: maintainer backend
    gitlab-ee: maintainer backend
    gitlab-shell: reviewer
  story: Bio that appears on the team page.

Note that each project, that user is involved in, is referenced by a key. The key needs to be defined in data/projects.yml as well.

  name: GitLab Community Edition (CE)
  path: gitlab-org/gitlab-ce
  # [...]

If corresponding key does not exist in data/projects.yml then CI pipeline will fail and an appropriate RSpec failure will inform you which key is missing.

Supported roles are only owner, maintainer and reviewer. A text provided after a role name is an arbitrary description, that will appear next to a team member's gitlab.com handle on a generated page.

See Engineering Projects Page in the Handbook.

Production build

Before building the static files, ensure you have a GitLab.com PRIVATE_TOKEN environment variable setup. This is required so that Middleman can automatically build the direction page.

bundle install

bundle exec rake build
# To also build PDFs:
bundle exec rake pdfs

The above command builds the static files and PDFs into the folder public.

PDF files

This site includes some dynamically generated PDF files. For example, terms/print/gitlab_subscription_terms.pdf. Each of these files is derived from a corresponding 'printable' HTML file, such as terms/print/gitlab_subscription_terms.html.

The PDF files are generated by pandoc using LaTeX/XeTeX. Global PDF parameters such as page margins are configured in pdf_template.tex.

Install PDF dependencies

There are two kinds of PDFs created: the comparison pages ones and all the others.

For the comparison PDFs you will need to install wkhtmltopdf.

On macOS:

brew cask install wkhtmltopdf

For all the others you need pandoc. On macOS run:

brew install pandoc

Then, install Basic TeX.

PDF development

You can tweak the 'printable HTML' files in Middleman's development mode if you enter the correct URL in your browser (e.g. http://localhost:4567/terms/print/gitlab_subscription_terms.html). If you want to tweak pdf_template.tex run rake build once, and rake pdfs as often as needed.

If you want to tweak the source HAML/Markdown/HTML and see the changes in the final PDF you have to run rake build pdfs after each source change.

To remove the generated PDFs run:

rake rm_pdfs

Add a new PDF file

In order to make a page be saved as pdf at a location reachable through the website, you have to:

  1. Open Rakefile with your editor and add the location of the generated PDF file (prepend with public/) under the PDFS = %w{ section. Save the file and exit.

  2. Make sure the file exists locally in the location you chose the pdf to be saved. For example, a page in source/my-page/page.html.haml should have an entry of public/my-page/page.pdf in the Rakefile (previous step).

  3. The file to be printed must have the print layout set in the yaml frontmatter. For example:

    layout: print
    title: "The title of the page"

Comparison PDFs


The comparison PDFs are generated in a slightly different way and require a different command to be run. Before the PDFs can be generated the website needs to be built locally by running the following:

bundle exec middleman build

After running that you can now run the following to generate the PDFs:

bundle exec rake comparison_pdfs

Once you have done that you are free to commit and push these to GitLab.com.

Custom Generators

There are a few custom, static generators specified in config.rb. For example, there are generators that produce the direction issue list, release list, and organization chart dynamically.

These pages cannot be viewed directly via the Middleman server (e.g. http://localhost:4567) because there are explicit rules that tell Middleman to defer the generation to other scripts. These special URLs (e.g. /release-list/index.html) usually have two Middleman keywords:

  1. proxy

    This tells Middleman to output a static file based on the provided template.

  2. ignore

    This tells Middleman server not to handle this URL. The external generator will build the static files.

To preview these custom-generated pages locally, you must first rebuild the files:

bundle exec middleman build

To test out the site, you must run another Web server from the public directory:

(cd public; python -m SimpleHTTPServer 8000)

This will start a Web server on port 8000 (you may omit the port number). You can preview the site by pointing your browser to http://localhost:8000.

Review Apps

Thanks to the Review Apps, the www-gitlab-com project supports live reviewing of any website changes with every merge request. When a branch is pushed and the pipeline is successfully run, you can see a link pointing to the live environment in your merge request. The URL will be of the following scheme: <branch-name>.about.gitlab.com.

Beware that:

  • To successfully deploy a Review App, the branch must exist in the www-gitlab-com repository. That means that branches from forks will not deploy a Review App (hence MRs from contributors). For that case, you should have at least Developer access to the www-gitlab-com project or gitlab-com group.
  • The generation of the direction, wishlist and release list pages is omitted in branches and is run only on master. This helps to shave off some time from the build process. That means you won't be able to preview these pages with Review Apps.

Conclusion (please leave this at the bottom of the doc)

In case someone forgot the most important commands and is catting this file from the command line we end by listing them:

bundle exec rake new_post
bundle exec middleman