Blog Handbook

On this page

GitLab blog

Our blog is managed by the Content Marketing team. Other team members are encouraged to contribute blog posts, but please see the publishing processes section and follow the steps there to get started.


Blog endboss

Rebecca Dodd is the blog endboss.

If the post author does not know who can do a final review or merge their post, they can assign it to Rebecca. A post author must get at least one review from someone in their immediate team and use a spelling and grammar checker before assigning the merge request to Rebecca.

Publishing processes

Blog editorial team

You may also ask content-related questions in #content on Slack.

Third-party posts

Blog posts concerning third parties or partners, whether they are to be published on the GitLab blog or externally, should be proposed to the blog editorial team before agreeing.

As a rule, any blog post, regardless of the author, should offer some informational, educational, or entertainment value to the reader. We do not publish material that is exclusively promotional in nature.

Guest posts by non-partners

If the author of a guest post is not an official GitLab partner, they may link back to their website or own content with inline links, but may not include a CTA button or promotional copy.

Guest posts by GitLab partners

Official GitLab partners may use our CTA button and include promotional copy, however the blog post must still serve a function (informational or educational) other than simply promoting something.

For either type of guest post, the process and guidelines for publishing are as follows:

  1. Create an issue in the blog posts project and ping @rebecca and @erica.
  2. If technical input is required, we will ask for instructions from the third party; otherwise it is at the discretion of the blog editorial and technical writing teams whether or not to go forward.

We limit media embeds to the following providers:

Team posts

Content Pitch Hour

If you want to pitch or brainstorm ideas for the blog (either to write yourself, or to suggest the content team write something), please join Content Pitch Hour, which takes place every Monday at 9:00 Pacific.

Please come prepared with an idea or angle, or with a topic we can brainstorm. If you'd like coaching or editorial guidance we can help out with that too! Or if you'd like to sit in on the Pitch Hour just to get inspired or to learn about the process, you're welcome to do that too.

Creating your blog post
  1. Choose a topic
  2. Define the target audience, knowledge level, and system requirements (example)
  3. Create an outline (a few items describing what you want to discuss along the post)
  4. Create an issue in the blog posts project and ping @rebecca so she can factor it into the publishing schedule
  5. Write the post according to the editorial style guide and to the Markdown guide
  6. Submit your draft as a WIP MR (Work in Progress Merge Request) to the GitLab website project
  7. Get reviewed by your team, and address their feedback
  8. Get feedback and review from the editorial team and assign to @rebecca to merge
  9. Ask @evhoffmann to promote on social media (Twitter/Facebook)

Important: never write your draft on pre-styled text editors like Google Docs or Microsoft Word. They don't use the same character encoding as markdown does (UTF-8), and it may cause issues when rendering markdown into HTML. Please use one of the recommended code editors.

Publishing process for community writers

The Community Writers Program has changed. Please check the new Terms and Conditions.

Objectives and purposes

What content should go on the blog?

The blog is:

Occasionally, some blog posts are better suited to publishing natively by the author on LinkedIn, or on Medium. We reach slightly different audiences on these channels, and some content will get better exposure and reach if published there. If you submit a blog post and the content team decides it's a better fit for one of these, we will let you know. For now, we will treat this segmentation as an experiment, monitor the performance of different types of content on different channels, and apply our learnings. We may then be able to start planning content for specific outlets and commission stories accordingly.

Anatomy of a blog post

Later sections of this handbook contain granular examples of different types of posts and how to write them, but a few broad things should be true of all posts, no matter the writer or the topic.

Big picture




Post formats

We aim to publish content multiple times a week, with a reliable publishing schedule. The reader will most likely have a pleasant experience if we combine multiple post formats, trying never to be too repetitive. Repetition is boring. We'll alternate between the following formats:

Blog content

Try to think about what our community might be interested in reading before picking up a subject to work on; you should always begin by identifying your target audience for the post. Here are some example topics and categories:

Product-specific topics

User stories

Do you have a better idea? Don't hesitate, create an issue with your proposal and we'll be happy to look into it.

Technical aspects

All blog posts should always have a real author name. When applicable, add a section "Acknowledgments" to the end of the post to thank contributors.

Types of blog posts

Release posts

Find out more about them on the release posts handbook!

Examples: release posts, security release posts.

Team members' posts

Whenever we have something interesting to talk about, we encourage our own team members to write their stories. And there are a lot of awesome ones! Even if you are not a writer, you are very welcome to write, and our reviewers will be happy to help you with the language, the technical aspects, the markup, the concepts and whatever else you might need.

If you are part of the GitLab team, please contribute! The review process is simple, please take a look at the publishing processes.

Guest posts

These posts are specific for community members that want to write about their own tools, features, and software integrations with GitLab. They can be written by the owners, executives or any team members of those companies, and will be reviewed by the GitLab blog editorial team.

For instance, we've had a post on Integrating GitLab with Microsoft Azure. It was written by one of Microsoft's employees, then reviewed and polished by our own technical writers. A similar process occurred to publish the post on Continuous Delivery with GitLab and Convox.

Note: we do not offer compensation for guest posts.


Check out our style guidelines.

Forked project

Before you write, make sure you forked www-gitlab-com, cloned to your computer, and were able to preview it locally by running bundle exec middleman. Before making any change, create a new branch git checkout -b branchname cloned from master.

Checklist before merging

Reviewer - check these before you publish:

It takes about 15-30 minutes for the blog post to appear as published after merged. As soon as it's live, check the post for broken links using this tool (or similar): Fix anything before sharing in any communication channel or social media network.

Get inspired

Blog style guidelines

How to publish a blog post

These instructions are for publishing to using the UI on You may find it easier to do this in the terminal on your own computer.

Below you will find more details about the required frontmatter for a blog post, as well as markdown formatting, writing style, structure, and adding images to a blog post.


The post frontmatter is the first part of any post. It is standard and cannot be changed, so please make sure to provide the correct information, and do not add nor remove anything from the default template:

title: "This is the post title"
author: Firstname Lastname
author_gitlab: username # included in February, 2017
author_twitter: Twitter username
categories: engineering
image_title: '/images/blogimages/post-cover-image.jpg'
description: "Short description for the blog post" # included in August, 2016
tags: tag1, tag2, tag3 # added June, 2018

New frontmatter! Social Media information: twitter_image, description, CTA buttons, author_gitlab, and guest!

title: "This is the post title"
author: Firstname Lastname
author_gitlab: username
author_twitter: Twitter username
categories: company
image_title: '/images/blogimages/post-cover-image.jpg'
description: "Short description for the blog post"
tags: tag1, tag2, tag3 # added June, 2018
twitter_image: '/images/tweets/post-screenshot-image.png' # optional
cta_button_text: 'Watch the <strong>XXX release webcast</strong> live!' # optional
cta_button_link: '' # optional
guest: true # required when the author is not a GitLab Team Member
ee_cta: false # required only if you do not want to display the EE-trial banner
install_cta: false # required only if you do not want to display the 'Install GitLab' banner
twitter_text: "Text to tweet" # optional

The following sections describe each entry of the frontmatter.


Make sure the post title represents the subject very well, and make it as short as possible. Do the same for headings.

Author name

Use the author's full name. If the name has special chars, type it within double quotes "Full Name". handle

Add the author's handle (username only, without "@"). If your username is johndoe, accessible under, this field should be filled as follows:

author_gitlab: johndoe

This field is required.

Introduced in January, 2017.

Twitter handle

Add the author's Twitter handle (username only, without "@"). If your username is johndoe, accessible under, this field should be filled as follows:

author_twitter: johndoe

If you aren't on Twitter or do not wish to link to your handle, please add gitlab in this field instead.

Twitter text

Add a text to tweet in twitter_text. If no text is provided it will use post's title.

twitter_text: "We just released a new feature!"


Use only one of the following categories per post. Do not change the capitalization, spelling, or anything else, otherwise you'll create another category, which is something we don't want to do accidentally.

We're working on improving category pages and tagging, but for now you can find posts under the same category by navigating to Dashes will be automatically added to multi-word categories and all of them will be lowercased in the URL. For example, the category "company" will be available under

Note that there's a CI test that checks for wrong or missing categories. If one of the above should change or a new category is added, don't forget to edit the following files:

  1. Rakefile (search for CATEGORIES) - responsible for the CI test
  2. source/includes/blog/category-nav.html.haml - responsible for the categories navbar
  3. source/handbook/marketing/blog/ - the handbook which you're currently reading
  4. If a category changes, you need to replace it in all posts. Here's a one-liner command you can run:

     find ./source/posts -type f -exec sed -i 's/categories: old/categories: new/' {} \;

    where old is the old category and new is the new one.

  5. In case of a category change, a redirect should be added in (internal). This is the last step after all the above are merged into master and deployed. Ask a production engineer to help you.

Cover image

Do not leave the post without a cover image (image_title), unless you have a strong reason to do so. Read more about it below.


The description meta tag is important for SEO, and is what appears on the blog index page. It is also part of Facebook Sharing and Twitter Cards. We set it up in the post frontmatter, as a short summary of what the post is about.

It's a way of making the post title shorter, then adding complementary information in the description. It's not meant to repeat the post title; use your creativity to describe what's in the post.

Note: Characters are limited to 150, otherwise the text will be cut off on the index page.

It is mandatory for all the new posts, and it has been included in the default post frontmatter generated by the command rake new_post.

Use this syntax (double quotes included):

description: "This is an example description for a blog post."

Check the Social Marketing Handbook for more information.


These are included to help readers find similar posts if they are interested in a particular subject. Tags appear at the bottom of each blog post, and clicking on a tag takes you to /blog/tags where you can view all tagged posts and browse by tag.

You can include as many tags as you like, separated by commas. Please only include tags from the following list, and note that they are case sensitive. If you think a tag should exist that isn't on this list, please leave a comment for Rebecca on your MR saying which tag you'd like to use and why it should be included.

Social media sharing image

It's the image which will be displayed on social media feeds. It's defined in the post frontmatter.

twitter_image: '/images/tweets/image-name.png'

Whenever you want to display exactly the cover image in social media feeds, don't add a twitter_image to the frontmatter. The blog cover image you used will render just as is in your social timeline via the card automatically produced on Twitter & Facebook. If you want to preview what your card will look like, or verify that the link you're sharing has cards enabled, use Twitter's card validator tool. This is the approach we use for blog posts with titles longer than one line when viewed on our blog homepage. The release post may be an exception.

Whenever the blog post title fits on one line when viewed on the blog homepage, you may choose to add a twitter image. The standard procedure for this image is:

*This is the portion to take the screenshot from (purple line):

twitter_image for the blog

You can also use another image for social sharing.

For further information, read the Social Media Sharing section at the Social Marketing Handbook.

Call to action (CTA)

There are two new possible entries in the frontmatter:

cta_button_text: 'Watch the <strong>XXX release webcast</strong> live!'
cta_button_link: ''

The first entry is text, referring to the link added to the second one. Therefore, always use them together.

The examples above link to a release webcast, but you can add any pair of text and link to this CTA. Use it wisely.

Do not include any UTM parameters in the link. Always wrap their values with quotes.

The final result is a red button over the cover image of the post.

Hero CTA preview

The CTA entry is optional; if you don't need to add any CTA to the hero, just omit both entries, leaving the frontmatter without them.

This option was introduced in January/2017.

EE trial banner

ee trial banner

To not display the EE trial banner on the blog post, set ee_cta to false in the frontmatter:

ee_cta: false

It is set to true by default, so there's no need to add ee_cta: true to the frontmatter.

Use it wisely; the EE trial banner is important for lead generation, however it is often better to remove it from community-focused posts or security updates.


The variable guest indicates whether the author is a guest (anyone who's not a GitLab team member). It should be only included in the frontmatter when that's the case. Technically, it's a conditional variable (true or false) to link the author's name their profile in the Team page.

For guest posts, partner posts, and cross posts, it must be present:

guest: true

For team posts, please do not add it at all (instead of setting it to false).

Introduced in February, 2017.


Comments are present in all posts by default. Set it to false only if you have a strong reason to do so (comments: false). They are our best source of feedback on posts.


The variable date: yyyy-mm-aa hh:mm:ss is not necessary in the frontmatter, unless you want to set a specific time. If you do, just make sure that the date in the file name matches with the date in the frontmatter, otherwise the build will fail. It's going to be necessary when publishing more than one post per day. The latest will stay on the top of the blog landing page.

Create a new post

You can create a new post however you prefer: adding a new file to /source/posts/, duplicating an existing post, or using the command line, which is the safest way to do so. Just type into your terminal (opened in your local project directory):

rake new_post

Hit enter or return, then you'll be prompted to enter the post title. Type in the title exactly as you want it, for example "Hello World – I'm a new post" and rake will take care of the file name for you. Then you just open the file, fill in with your name, Twitter handle, and the post category, then you'll be good to start writing.


All posts are written in markdown Kramdown. Please read through the Markdown guide for reference.

Writing style

At GitLab, we use American English as the standard written language. Please see the editorial style guide for details.

GitLab content primarily follows AP Style, which is searchable online. However we use sentence case for all titles and subheadings, as it is easier to apply consistently and helps readers to scan titles more easily.

Any questions that cannot be answered by the AP Stylebook may be resolved by referring to the Chicago Manual of Style. To learn about GitLab's advanced formatting system, check out our Markdown guide.

Body structure

Just below the frontmatter, start writing your post, including the sections as follows:

If the article is part of a series, make sure to link back among all articles in the series to each one after they get published.

Click to tweet

Consider adding pull quotes as click-to-tweet boxes, to encourage and make it easier for readers to share key points from your blog post.

To add a click-to-tweet box, copy the below partial and enter the text and author fields. If the author doesn't have a Twitter account you can use gitlab instead.

<%= partial "includes/blog/tweet", locals: { text: '', author: '' } %>


<%= partial "includes/blog/tweet", locals: { text: 'The Operations experience then should really just be that I go to work in the morning and see an email summary of what has happened, without me having to do anything', author: 'MarkPundsack' } %>


Click to tweet

Note: this only works for blog post files with the extension ``.

Newsletter sign-up form

We can now embed a CTA for readers to sign up for our newsletter directly from the blog post page. There are two different designs. Use the following:

<%= partial "includes/blog/content-newsletter-cta", locals: { variant: "a" } %>


Newsletter sign-up CTA variant A


<%= partial "includes/blog/content-newsletter-cta", locals: { variant: "b" } %>


Newsletter sign-up CTA variant B

Note: this only works for blog post files with the extension


As explained on the Professional Writing Techniques, always provide a source for your statements.


Illustrate your examples, with code blocks or screenshots. Be consistent along your examples. E.g., if you are using a generic URL to exemplify your steps, be consistent and keep it, throughout the post.

Important security point: Do not expose your personal details by using your real tokens or security credentials. Use placeholders such as [project's CI token] stub instead. Or blur them if displayed on screenshots.


Creating images

Preparing images

For the blog, images should be cropped in a 1.7 width/height pixel proportion (ideally 1275px x 750px) so the image doesn't get clipped when displayed as a lead image in the blog list. This includes the cover image. Compress the image, for example using or any other image editor. All images should be at least smaller than 1MB. JPEGs tend to be smaller than PNGs so use JPEGs when possible. To preserve the harmony along the post, try to keep all the images with the same width (e.g., the ones used in this post).

The only images accepted for are public domain images and screenshots. Whenever you choose an image which is not a screenshot, add a link to the original image to the merge request description and as an HTML comment:

<!-- image: image-url -->

Do the same for cover images, adding a link to the original image to the end of the post as a comment and to the MR description:

<!-- cover image: image-url -->

How to add images to blog posts

Instructions for adding images to blog posts on

Images used to illustrate articles should be placed in the /source/images/blogimages/ directory.

Naming images

If you are using a set of images, create a new directory under /source/images/blogimages/, name it according to your post's title and add all the images there. For example, if your post has a file name, your new folder should be named /my-awesome-post/.

If you use just a couple images, you can add them directly to /source/images/blogimages/, but make sure they begin with the same name as you post's. This way it's easy to anyone know which image is related to each post. Name the files according to the previous example. So, following the same logic, your cover image would be named my-awesome-post-cover.png, accessed under /source/images/blogimages/my-awesome-post-cover.png.

Adding inline images

To add an image inline, insert the following into your markdown file, where you want the image to appear:

![Alt text for your image](/images/blogimages/your-image-filename.jpg){: .shadow}

The alt text for your images should describe the content and function of your image for visitors using a screen reader.

Sizing and aligning images

There are new classes for sizing and positioning blog post images. They should be added to blog post images similar to how the shadow class is added already:

![Your image alt text](/images/blogimages/your-image-filename.jpg){: .shadow.small.left.wrap-text}

The new classes are grouped into:




.wrap-text: Only applies to images that are positioned left or right. Makes text wrap around the image.

These classes are only applied for screens 992px wide and and wider.

If a Position class is used without an Effect class then there will simply be empty space where the image isn't. Similarly, using a Position class without a Size class will have little-to-no effect.

Image captions

Insert the following beneath an inline image to include a caption:

  *<small>Insert caption text here</small>*

Cover image

For the cover, create an image or choose one from any public domain resource. It should reflect your post's subject (even if it's in an abstract way). Unsplash is our preferred resource for public domain images. In the absence of a custom cover image, you can use one of these:

Please only use the default images where there is genuinely no other option.

Please add a reference to the cover image source, owner, and license at the end of the blog post, even if it doesn't require attribution:


Cover image: ["Image title"](link-to-original-image) by [owner name and surname](link), licensed
under [CC X](link-to-licence).
{: .note}

If the image does not have a title, default to the following format:


[Cover image](link-to-original-image) by [owner name and surname](link), licensed
under [CC X](link-to-licence).
{: .note}

The cover image has the following proportions:

Try to have them harmonically aligned with the title, which overlays the background image in both cases.

To crop the image, use the size of 1275x750 px. If you want to align the background image with the title overlay, use the widescreen proportion.

Creating GIFs

Animated GIFs are very useful to illustrate short dynamic processes, which might be easier to understand with this kind of resource. There are a few ways to create animated GIFs, one of them is using Giphy Capture, a light-weight app for Mac.

Avoid GIFs with a huge file size, they will be difficult to load for users with bad internet connection. In those cases, you can either cut the GIFs in smaller pieces, or record a video, or use a sequential image (e.g., the ones used in this post).

Read more on Making Gifs in the Product Handbook.

Artwork and editable image files

If you have used a bitmap or vector editing software to create illustrations, diagrams, or any other kind of images for your blog post, save the editable files in the General Marketing project. To do that, create a directory under /design/web-design/about-gitlab-com/blog/images/ using the same naming logic from Naming images and place your files there.

GitLab-specific terms

Quick guide for release posts

Update (April, 2017): check the release posts handbook.