Gitlab hero border pattern left svg Gitlab hero border pattern right svg

Blog Handbook

The GitLab blog is managed by @rebecca the Managing Editor.


On this page


  1. Build credibility and authority.
  2. Increase awareness of GitLab the company, product, and community.
  3. Increase organic search rankings and traffic.
  4. Contribute to lead generation and revenue.


Mission statement: Increase awareness of the benefits of a single application for the entire DevOps lifecycle.

The blog is not the permanent place for tutorials, which should live in the docs and should be linked to when relevant.


We use content definitions to make it faster to track the effectiveness of different types of blog posts. There are three categories we use to differentiate blog content:

  1. Content marketing: Examples, education, reporting, storytelling, thought leadership, and use cases.
  2. Corporate: Company news, announcements, and community updates (ex: issue bash, contributor profiles).
  3. Product: Release posts, critical updates, and partnership announcements.

Use the postType frontmatter option to set the content definition.

Publishing process

We follow the GitLab Workflow. At GitLab, everyone can contribute, and we encourage anyone to submit a blog post idea or write your own. Below are instructions on how to contribute to the GitLab blog.

Time-sensitive posts: Official announcements, company updates, breaking changes, and news

If you need to publish a time-sensitive post, it is critical that you give the content team advance notice. Please follow the process outlined below:

  1. Start by opening an issue in the project, using the Blog post template and applying the priority label. Even if you do not have a draft or a confirmed publish date, it's important to open the issue as far in advance as possible and ping @rebecca so she knows it is coming and can prioritize accordingly.
  2. The issue title should reflect the date on which you expect to publish.
  3. The issue due date should be two working days before the publish date.
  4. If other due dates apply (for example, design assets are required) make sure the entire timeline and all the people responsible are captured in the issue description.
  5. In most cases, we expect that you or one of your team will write the post and create the merge request for it, with all images and other formatting included. See the formatting guidelines for help with creating and formatting your blog post file.
  6. If you need assistance with drafting the post or creating the MR, please make this clear in your issue and we will confirm if this is possible within your timeframe.
  7. Use the Blog post merge request template for your MR and ensure it is set to close the associated issue automatically.
  8. Be sure to check the review app for your blog post or preview it locally to ensure images, headlines, etc. are formatted correctly before handing over.
  9. When your MR is ready for review, please assign it and the corresponding issue to @rebecca (or @erica if Rebecca is OOO) a minimum of two working days ahead of when you expect to publish. Please submit your MR earlier if you can.
  10. When you've assigned your MR and issue to a reviewer, please change the due date on the issue to reflect the publishing date.
  11. Your reviewer may leave comments for you to address, in which case they will assign the MR back to you. When you have resolved all outstanding discussions, assign the MR back to the reviewer for final review and merging.

Continuous delivery mindset: With time-sensitive posts, don't wait to publish a post if you have enough information to go live. It's OK to publish a headline and paragraph to get the news out in a timely matter and add more details later (e.g. add more graphics, charts, etc.). We don't want to miss out on a newscycle because we're waiting for an image or supplementary information.

Pick Your Brain posts

For follow-up posts to Pick Your Brain interviews with the CEO, as soon as an interview or livestream is scheduled, please open an issue in the project, using the PYB blog post template, and fill out the relevant information there.

The blog editorial team will assess the content of the post and decide how best to leverage it. This may mean publishing on the blog, on our Medium site, simply sharing the video on social, or something else.

Once agreed, the blog team will assign and communicate the expected publish date.

Any other blog post ideas

You do not need approval to write for the GitLab blog. If you would like to write a blog post, please follow the process outlined below.

Note: If you're planning to write a tutorial post describing how to do something with GitLab, please ensure that the relevant documentation exists first before you write a blog post about it. A blog post should not replace documentation, but should add more information, context, and color around a technical subject, linking back to the documentation for full instructions.

  1. Open an issue in the project, using the Blog post template.
  2. Review the instructions to create and format a new blog post.
  3. Use the Blog post merge request template for your MR and ensure it is set to close the associated issue automatically.
  4. Assign the issue and associated merge request to yourself and apply the appropriate labels based on what stage of creation you are on. Once it's ready for editorial review, assign both to @rebecca.

If you have a blog post idea but do not intend to write it yourself, simply label the issue blog post and the content team will review during triage.

Blog post ideas and proposals for Content Hack Day should be created in the Content Hack Day project. We keep these issues in a separate project because not all ideas and proposals that come from Hack Day will be worked on.

Issue triaging

The Content Marketing team is responsible for triaging blog post issues and reviews the blog post backlog every Monday morning.


Publishing schedule

With the exception of time-sensitive announcements and news, we are aiming to have blog posts scheduled two weeks ahead.

Blog calendar

The calendar below documents when posts will be published, as well as industry awareness days and anniversaries we may cover. Please bear this in mind when requesting a specific publish date for a post.

Please note that all dates are subject to change to accommodate urgent posts and announcements.

Writing blog posts

The Content Marketing team is responsible for increasing sessions on the GitLab blog month over month. We use data-driven insights to decide what to write on using the content marketing dashboard. In order to hit our goals, we aim to publish at least 3 blog posts that will garner 10,000+ sessions.

*From 2018 blog analysis conducted in 2018-10

  1. Average sessions per month on the blog: ~30,000
  2. Average sessions per post in published month: 3,792
  3. Average sessions per content marketing post in published month: 3,500
  4. 55% of posts get <1,000 sessions in a month
  5. 27.47% of posts hit our expected outcome of 1,000-4,999 sessions in published month
  6. 28.57% of posts garner less than 499 sessions in published month
  7. 9% of posts are "hits" (10K+ sessions in published month); "Hits" don't consistently perform well over time

Breakdown by category of "hits":


  1. There is not a strong correlation between # of sessions and topic
  2. Strong performing content marketing posts focus on show and tell engineering stories
  3. Posts really fall into the 5,000-9,999 session bracket (3.3%)
  4. Content hack day posts tend to perform well (>1,000 sessions in published month)

Identifying and qualifying a high-performing blog post

Qualifying story ideas:

Look for the following patterns:

  1. Team implementing a new technology, process, or coding language
  2. Deep dive into how a popular feature is made
  3. Chronicling a performance improvement
  4. Covering a controversial decision that was made

Who and how to interview:

  1. Contact the technical subject matter expert. This can be someone who created the issue, or managed the project.
  2. Set up a 30 minute interview and dig into:
    • What was the challenge?
    • What was the solution?
    • How did you go from point a to point b? Walk me through your thought process.
    • How was the solution implemented and what is a realistic use case of the solution?
    • What lessons were learned?
    • How did this make the GitLab product / development community better?
  3. Optional: Contact the business subject matter expert. This could be a product manager or a product marketing manager.
  4. Set up a 30 minute interview and dig into:
    • How does this solution help a user?
    • What business value does this solution bring?
    • How does this solution relate to our product?

Attributes of a successful blog post:

  1. Deep dive into a hard technical challenge.
  2. Puts the reader in the shoes of the person who faced the challenge; reader learns via compelling example.
  3. Intellectually satisfying; learning component.
  4. Allows the reader to learn from someone else's mistake, and follows a problem/trials and triumphs/solution story arch.
  5. Taking a controversial or unpopular stance on a topic, back by hard evidence.

Examples of high-performing posts (20K+ sessions in published month):

  1. Meet the GitLab Web IDE
  2. How a fix in Go 1.9 sped up our Gitaly service by 30x
  3. Hey, data teams - We're working on a tool just for you
  4. Why we chose Vue.js
  5. How we do Vue: one year later

Conducting a blog analysis

Pull information on all blog posts to document how many sessions each post received in the month, and how many sessions they received of all time. Categorize them by type, bracket, total sessions in month, total sessions to date, category, theme, and topic. Eventually add first touch point revenue data. Search Google Drive for Blog Performance to find the appriopriate sheet to work from.

Column explanations:

Preparing confidential blog posts

In the event that we have a big announcement to make and the information must remain confidential until, use the forked project to prepare your merge request.

Editorial reviews

Editorial reviews are mandatory for every merge request. Please familiarize yourself with our editorial style guide. Before you assign your merge request to a content editor, please ensure you've removed the WIP label, and include the following in the description:

All GitLab content editors can perform an editorial review on blog-post merge requests of colleagues and community contributors. You can find someone to review your own blog-post merge requests by looking on the team page. Merging blog posts is restricted to the managing editor and management.

Content marketers who are writing about any organizational changes in the company should ask the leader of the function to do a quick review of their post.

Checklist before merging

Reviewer – check these before you publish:

When you have double checked, you can assign to @rebecca to merge. If Rebecca is OOO, assign to @erica.

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.

Publishing natively on LinkedIn and Medium

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.

Third-party posts

We will promote anyone integrating with GitLab, even if we compete with them. It is very important to demonstrate to our customers that we do not lock them in.

If you are a partner or industry-adjacent third party who wants to write for our blog, please contact the Partner Marketing team before proceeding.

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 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 www-gitlab-com project and label it blog-post and guest/partner post.
  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.

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.

Cross posts

We do not republish posts from other publications verbatim.

If you spot a tweet, post, or feedback anywhere detailing an interesting use case for GitLab which you think could make a good story, open an issue and ping @kimlock to help determine whether we should pursue an interview for a blog post or case study (we will not ask the original author to create something for us).

If we're doing a joint announcement and a partner wants to cross-post a GitLab post:

  1. The cross-posted blog must open with a disclaimer about the original post and link back to the original post.
  2. The post should also add a canonical link to the metadata in the <head> of cross-posted articles: <link rel="canonical" href="" />


This post was originally published by GitLab on

Formatting guidelines

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

Create a new post

Please see the publishing process before you get started. 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.

Creating a post from the UI

Add a new file to /source/posts/ using the filename format If you aren't sure when the post will be published, just choose an arbitrary date in the future – we will update it before publishing.

Creating a post from the command line

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.


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 # if name includes special characters use double quotes "First Last"
author_gitlab: username # ex: johndoe
author_twitter: Twitter username or gitlab # ex: johndoe
categories: company
image_title: '/images/blogimages/post-cover-image.jpg'
description: "Short description for the blog post"
tags: tag1, tag2, tag3
cta_button_text: 'Watch the XXX release webcast 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;  If no text is provided it will use post's title.
featured: yes # reviewer should set
postType: content definition # i.e.: content marketing, product, corporate

Cover image

For the cover, create an image or choose one from any public domain resource. Unsplash is our preferred resource for public domain images.

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.

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.

Add featured: yes to the frontmatter of a post to create a featured post. The two most recent featured posts will be shown at the top of the blog in the featured section (even if more are tagged). To remove a post from being featured, remove the featured: yes line from the frontmatter.


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.


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. Description is 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.


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 the reviewer on your MR saying which tag you'd like to use and why it should be included.

Call to action

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. 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

EE trial banner

To not display the EE trial banner on the blog post, set ee_cta to false in the frontmatter. It is set to true by default, so there's no need to add ee_cta: true to the frontmatter. Only set to false on the rare occasion you have a strong reason to not display the banner (usually in the case of posts that are for developers and our open source community).

Post type

See Definitions for guidance.

Media embeds

We limit media embeds to the following providers:

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

### 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. This only works for blog post files with the extension

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](/images/handbook/marketing/click-to-tweet.png){: .shadow}


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.

Images and illustration

Blog images are stored in the source/images/blogimages/ directory. If your post contains many images, create a sub-directory for your post: source/images/blogimages/name-of-post/.

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.

Preparing images

Image attribution

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:

Cover image by [owner name and surname](link) on [Unsplash](link)
{: .note}

You can paste this from the box that appears on Unsplash when you have downloaded an image. For images not from Unsplash:

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

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 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>*

Embedding videos

Please see the Markdown Guide.

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.

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.