Editors Available on GitLab.com
Regular Code Editors
Markdown editors (type and preview simultaneously)
Complementary Notes
The guide covers usage of Markdown. If you’re looking for something and can’t find it, it may be on the
shortcodes page
.
Markdown Style Guide for the Handbook
The GitLab Handbook
. For styles in the GitLab UI, see the
GitLab Flavored Markdown documentation
.
For the style guide, for the
www-gitlab-com
pages, see
Markdown Guide
.
This website was generated by
Hugo
, a blog-aware Static Site Generator (
SSG
) widely used by web developers.
Markup language
is part of the structure of any SSG. It is a system to write documents making them somehow
syntactically distinguishable from text.
Lightweight markup languages
have a simplified and unobtrusive syntax,
designed to be easily written within any text editor. That’s what we use to write our content. The majority of
SSGs use markdown engines for this purpose. Read through our blog post on
Modern Static Site Generators
to understand how they work.
The GitLab Handbook
we use
Goldmark
, which is an advanced Markdown engine written in Go and comes bundled as part
of Hugo. It implements the
CommonMark
markdown standard, it’s is extensible and very fast at transforming Markdown
to HTML. As such, we encourage use of Markdown as much as possible, though we allow HTML inline (MD033).
If you never have written a single line in markdown markup, don’t worry, it’s easy to learn and even easier to use.
You’ll probably be surprised how handy it is once you get used to it. And you’ll miss it whenever the tech you’re using
doesn’t support markdown.
In most of GitLab text areas you’ll find markdown support. We have a number of markdown engines in GitLab so the markup
will not behave equally “GitLabwide”. For
GitLab.com
,
GitLab CE
and
GitLab EE
text areas, the markdown
engine is currently
CommonMarker
. Here you can find the
markdown style guide
for them. In the
for the handbook projects, you’ll see
Kramdown
used.
This guide has been made to make it easier for everyone to use Hugo and Goldmark features and save a lot of time
writing content for
The GitLab Handbook
There are different possible syntaxes for most of the markups described below, but this guide is to be considered the
standard for
The GitLab Handbook
For information on how markdown is verified in the pipeline, refer to
the development docs
.
Relevant customized markdownlint rules are noted in the format
MD###
.
Headings
Content headings should be descriptive enough to suggest their corresponding content when they or corresponding fragment identifiers are seen out of context.
Fragment identifiers are automatically generated from most headings. Keep that in mind when choosing your headings.
Notes on heading structure:
We don’t use
h1
headings, as they already are displayed on every page as its title, and we should not apply more
than one
h1
per page (MD002, MD041).
Always start with
h2
(
##
), and respect the order h2 → h3 → h4. Never skip the hierarchy level, such as
h2 → h4.
The six heading elements, H1 through H6, denote section headings. Although the order and occurrence of headings is
not constrained by the HTML DTD, documents
should not skip levels
(for example, from H1 to H3), as converting such
documents to other representations is often problematic.
W3C
To prevent confusion, headings at the same level should not be duplicated (MD024).
Notes on individual headings:
Always leave a blank space between the hash
#
and the text next to it, otherwise it won’t render properly.
Have an empty line before and after, to keep the text clear and the markdown consistent.
We enforce using the
atx
style of heading, where the heading starts with one or more hashes (MD003).
While emphasis instead of header is allowed (MD036), it is not recommended.
Headings should be no longer than 100 characters (MD013).
Headings should not end in punctuation (MD026).
Headings should not have links in them. The site automatically makes headings anchor links, but links in headings can override the behavior.
Headings should use
sentence case
.
Paragraphs, breaks, and horizontal lines
Regular paragraphs are obtained by just writing text lines. If you hit
enter
between two lines,
both lines will be joined into a single paragraph, which is called
wrapping text
.
But, if you leave a blank line between them, they will split into two paragraphs.
In some Git tools,
diffs
in future MRs may be easier to understand with additional line breaks, however GitLab’s web
interface as well as many desktop Git tools feature substring change highlighting within lines and side-by-side or
similar version comparison so there is no need for artificial line breaks.
Wrapping Text
Splitting long lines (preferably up to 100 characters) can make it easier to provide feedback on small chunks of text.
Do not leave blank spaces after the last word of the line broken within a paragraph, unless you want it to be
intentionally broken with a
<br>
.
This text is a paragraph.
This won't be another paragraph, it will join the line above it.
This will be another paragraph, as it has a blank line above it.
This text is a paragraph.
This won't be another paragraph, it will join the line above it.
This will be another paragraph, as it has a blank line above it.
In case you need an additional break (or some extra space between lines), you can simply use the HTML break tag <br>
,
leaving blank lines above and below it:
A sequence of three or more dashes will produce a horizontal line, but let’s use always 3 as standard (MD035). Leave blank
lines after and before it:
To display bold or italic text, wrap it in 2 stars (for bold) or underscores (for italic).
For both italic and bold, wrap it in 3 stars:
Markdown doesn’t natively support underlined text. If necessary you can hardcode it with the
HTML tag ins
(<ins>underlined text</ins>
), however, it is inadvisable to do so.
There are a few different ways to display links with markdown markup, but
to keep some standards, let’s try to use the following options only.
Important notes
Don’t take it as a restrictive rule, but avoid using meaningless text for links
as “this article” or “read here.” The link text should be meaningful even if taken out of context; this makes the
links more useful and accessible for people using screen readers.
Inline Links
We’d rather use inline links, such as [Text to display](link)
, as they are easier to maintain. To make an inline link
open in a new tab, you can add {:target="_blank"} to the end. Ex: [Text to display](link){:target="_blank"}
Use relative links when referring to links found on handbook.gitlab.com
.
When linking to a heading on the same page, use [link text](#the-heading)
.
When linking to other pages within the same handbook (or repository), use relative links.
You can either link to the markdown file (which is the easiest when using the editor) or the final version of the link.
Some examples:
Page you’re editing
Page you’re linking to
Link to the markdown file
Link to the final version
/handbook/company/culture/_index.md
/handbook/company/culture/working-remote.md
./working-remote.md
./working-remote/
/handbook/company/culture/_index.md
/handbook/company/culture/all-remote/coffee-chats.md
./all-remote/coffee-chats.md
./all-remote/coffee-chats/
/handbook/company/culture/_index.md
/handbook/company/okrs/cadence.md
../okrs/cadence.md
../okrs/cadence/
/handbook/company/culture/_index.md
/handbook/engineering/infrastructure/_index.md
../../engineering/infrastructure/_index.md
../../engineering/infrastructure/
Alternatively, you can link to the final version of the page link without the domain if it’s in the same handbook.
For example, a link to our blog handbook page
should look like this /handbook/marketing/blog/
and not this /handbook/marketing/blog/
.
Only use the absolute (not relative) link, including the domain https://example.com
, if the page is not in the same repository.
For example, if you are editing the public handbook and need to link to an internal handbook page.
Hugo can reference reference pages
without having to use the full relative path. However, for consistency and easy of use,
we use plain Markdown links, and avoid using the Hugo ref
or relref
shortcodes.
For links to GitLab.com or anywhere else, you must use the entire link, including the https:
.
While reference (identifier) links can be used, they are discouraged.
mailto links
If you’re adding an email address to a page be sure to format your link with mailto
to avoid creating broken links.
For example, [[email protected]](mailto:[email protected])
Both ordered and unordered lists are very straightforward to produce. There are a few ways to produce the same results,
but let’s stick with the following, again, to maintain some standards.
Always start list items with a capital letter.
Always leave a blank line before and after a list. Though this is currently not enforced (MD022).
Begin a line with spaces (not tabs) to denote a nested sub-item. Items nested in lists should always align with the
first character of the list item.
For Unordered lists, use two spaces for each level of indentation.
Though this is not currently enforced (MD007).
For Ordered lists, use three spaces for each level of indentation.
Tip: don’t leave blank lines between the items, unless you have a reason to do so.
Important
Always leave a blank line between Headings and the subsequent list! If you don’t, the list will not render.
The Writing Style Guide recommends using
ordered lists when you have multiple items, because
Numbered lists are easier to reference during a discussion over bulleted lists
.
See the Documentation Style Guide for other
helpful tips.
Ordered lists
Ordered lists are pretty easy to create. Couldn’t be more intuitive:
To be practical and avoid errors on the numbers, use “1” for all the items. The markdown engine will output them
in the correct order.
Let’s say, for some reason, you want to split a list in different parts. To do that, use the
markup ^
to indicate the end of a list and the beginning of the next:
To insert images to your markdown file, use the markup ![ALT](/images/path/image.ext)
. The path can either
be relative to the website, or a full URL for an external image. The supported formats are
.png
, .jpg
, .gif
. You might be able to use some .svg
files too, depending on its structure.
Images should be added to the static/images
folder in the handbook repository, using subdirectories as necessary for organization.
For example, static/images/company/company_hierarchy.png
to be used on the /handbook/company/hierarchy.md
page,
and using the path /images/company/company_hierarchy.png
.
Note that this is enforced for images being added.
As images added in this way will not render in the markdown editor preview, use review apps instead.
All images should be 100KB or less, ideally, 25-50KB. Consider compressing images and using the PNG format. The handbook linter checks for a maximum of 500KB.
![Semantic description of image](/images/path/to/folder/image.png "Image Title")
If you want to add a caption to your image, it’s easily achieved with:
![Semantic description of image](/images/path/to/folder/image.png)*My caption*
For clickable images, simply wrap the image markup into a link markup:
[![Semantic description of image](/images/path/to/folder/image.png "Hello World")*My caption*][handbook.gitlab.com]
Output
Only screenshots and public domain images are permitted.
The text inside the square brackets is an image attribute called ALT
, which stands for alternative text.
Including descriptive alt text helps maintain accessibility for every
visitor and should always be included with an image. When you add alt text, be sure to describe the content and
function of an image. In addition to the accessibility benefits, ALT
is useful for SEO, and it is displayed
when, for some reason, that image is not loaded by the browser.
For the same reasons, the image must contain a name related to it. Example: instead of image-01.jpg
, name it
black-dog.jpg
, if it’s a photo of a black dog.
It’s also recommended to add an image title for a longer description when necessary.
The formatting is shown in the example above with the “Hello World” text.
Mermaid
See the examples in the GitLabm docs
on how to use Mermaid. We have a number of Handbook-specific example in the
Tools and Tips Section.
PlantUML
You can use PlantUML in Markdown blocks. For
example:
```plantuml
!define ICONURL https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/v2.1.0
skinparam defaultTextAlignment center
!include ICONURL/common.puml
!include ICONURL/font-awesome-5/gitlab.puml
!include ICONURL/font-awesome-5/java.puml
!include ICONURL/font-awesome-5/rocket.puml
!include ICONURL/font-awesome/newspaper_o.puml
FA_NEWSPAPER_O(news,good news!,node) #White {
FA5_GITLAB(gitlab,GitLab.com,node) #White
FA5_JAVA(java,PlantUML,node) #White
FA5_ROCKET(rocket,Integrated,node) #White
gitlab ..> java
java ..> rocket
!define ICONURL https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/v2.1.0
skinparam defaultTextAlignment center
!include ICONURL/common.puml
!include ICONURL/font-awesome-5/gitlab.puml
!include ICONURL/font-awesome-5/java.puml
!include ICONURL/font-awesome-5/rocket.puml
!include ICONURL/font-awesome/newspaper_o.puml
FA_NEWSPAPER_O(news,good news!,node) #White {
FA5_GITLAB(gitlab,GitLab.com,node) #White
FA5_JAVA(java,PlantUML,node) #White
FA5_ROCKET(rocket,Integrated,node) #White
gitlab ..> java
java ..> rocket
This method works for any embed video within an <iframe>
tag.
Copy the code below and paste it into your markdown file. Leave a blank line above
and below it. Do NOT edit the code block (such as, remove spaces - the video iframe
may not render properly)
Go the video URL you want to display
Click on “Share”, then “Embed”
Copy the <iframe>
source (src
) URL only, and paste it replacing the src
below:
<!-- blank line -->
<figure class="video_container">
<iframe src="https://drive.google.com/file/d/0B6m34D8cFdpMZndKTlBRU0tmczg/preview" frameborder="0" allowfullscreen="true"></iframe>
</figure>
<!-- blank line -->
Display local videos (HTML5)
We recommend one of the common formats, such as mp4
and mkv
.
Videos should be added to the static/videos
folder in the handbook repository, using subdirectories as necessary for organization.
For example, static/videos/company/company_mission.mp4
to be used on the /handbook/company/_index.md
page,
and using the path /videos/company/company_mission.mp4
.
Note that this is enforced for images being added.
This method works for any video uploaded to somewhere retrievable from the internet from a URL, or from a relative
path like path/to/video.mp4
.
Read through the w3schools HTML5 video guide, or the MDN <video>
guide
Record or export the video in these three formats to achieve cross-browser and cross-device
compatibility: .mp4
or .ogg
.
Get the URL for your video
Choose an image to use as a poster
Copy the code below and paste it to your file
Replace the src
URLs for your video URLs
<!-- blank line -->
<figure class="video_container">
<video controls="true" allowfullscreen="true" poster="path/to/poster_image.png">
<source src="path/to/video.mp4" type="video/mp4">
<source src="path/to/video.ogg" type="video/ogg">
</video>
</figure>
<!-- blank line -->
In case you don’t have all formats recommended by w3schools, you can use just one of them,
but your video most likely won’t be supported in all devices and browsers. The video above (.mp4
only)
worked on Mozilla Firefox for macOS, Android, and Windows, and on Chrome for Android, and for Windows.
But it may not work on other devices/browser, such as Chrome for macOS and iOS, or Safari.
In fact, the best option is using YouTube or Vimeo embed videos in <iframe>
tags.
Display multiple videos
To display multiple videos on the same page, just repeat the figure
code block
where you want them to show up, replacing the video ID with the respective ID
corresponding to your videos.
To display multiple videos in a sequence, just copy the figure
code block and
paste it as many times as necessary. Always leave a blank line between the blocks.
Do NOT remove the spaces, otherwise your videos may not render properly.
<!-- blank line -->
<figure class="video_container">
<iframe src="https://drive.google.com/file/d/0B6m34D8cFdpMZndKTlBRU0tmczg/preview" frameborder="0" allowfullscreen="true"></iframe>
</figure>
<figure class="video_container">
<iframe src="https://drive.google.com/file/d/0B6m34D8cFdpMZndKTlBRU0tmczg/preview" frameborder="0" allowfullscreen="true"></iframe>
</figure>
<figure class="video_container">
<iframe src="https://drive.google.com/file/d/0B6m34D8cFdpMZndKTlBRU0tmczg/preview" frameborder="0" allowfullscreen="true"></iframe>
</figure>
<!-- blank line -->
Tables for markdown are challenging. So, we have two possible approaches: use markdown whenever possible,
but if you need pretty advanced table layouts, you are free to add them in HTML markup instead.
Markdown is not a replacement for HTML, or even close to it. (John Gruber
As explained by John Gruber, the creator of markdown, it was not created to replace HTML,
so there are situations we can’t avoid using HTML. With complex tables, that’s the case.
For very simple 2 column tables it is better to use lists with strong text in preference
to the complexity of using markdown tables.
The following table has a header (first line), then markup to define the desired alignment (dashes and colons),
then the table body.
However you prepare your table, its design will depend upon the CSS styles defined for them.
| Default aligned | Left aligned | Center aligned | Right aligned |
|-----------------|:-------------|:---------------:|---------------:|
| First body part | Second cell | Third cell | fourth cell |
| Second line | foo | **strong** | baz |
| Third line | quux | baz | bar |
The bars, spaces, and dashes were used symmetrically in the previous example to
help future page developers if they need to edit the table’s contents. The
symmetry isn’t required.
Some development tools can help you create your own complex table if you need
to merge lines or columns, or if you require a more complex layout. This
[table generator] may be able to help you do this.
To add a numbered list in a table cell, add a blank line between the heading
and the table to render the table correctly. Otherwise, the text and
formatting won’t appear.
To create more complex tables, you need to use HTML.
Collapse
A collapsed content section is used to hide information until a user chooses to reveal it with a click or tap on the
summary text. The hidden content is revealed inline. For example, this code:
{{% details summary="This is the summary text, click me to expand"%}}
This is the detailed text.
We can still use markdown and <strong>HTML</strong> in this block.
{{% /details %}}
{{% details summary="First level collapsible item" %}}
**Lorem ipsum dolor sit amet...**
{{% details summary="Second level collapsible item" %}}
_Sed ut perspiciatis unde omnis iste natus..._
{{% /details %}}
{{% /details %}}
There are a few options for displaying code blocks with Markdown. Most of them use backticks `
.
There is the in-line
code block. Used this to reference very short bits of code, filenames and folder paths, and
programming symbols and objects in a bit of text. The whole line including the code block should read fluidly.
Note: While indented code formatting is common, we enforce “fenced” for code blocks (MD046).
This is the most common code block you will encounter and use. You can use this to share whole sections of code within
a markdown document. The additional syntax highlighting makes the code easier to read and understand. The highlight
function supports a large number of languages
including Ruby, Python, Rust, Swift, etc.
If a language is not supported, or for text, use text
or plain
as the language.
Markdownlint currently enforces specifying a language.
In lists
Indent the text of each item in 2 white spaces (for unordered lists) or 3 white spaces (for ordered lists).
Leave blank lines between the code block and the list items,
and indent the code block in 5 white spaces:
There are two types of comment which can be used. The first allows you to leave comments in a markdown file which can
only be viewed in the repository and are not rendered to HTML or included in a pages source. The second type is a standard
HTML comment which will be included in the pages source.
See comments shortcode.
It is also possible to use HTML comments. These differ in that they are also included in the rendered pages source.
Typically you shouldn’t need anchors as well structured documents with headings should prove a good route to linking to
text you may want to reference on another page. All headings act as anchors on a page. However there maybe times
when you need it, such as if you have an icon in the header.
There are multiple ways to add an anchor.
This small shortcode will drop an anchor in a page
which you can reference from the same page or another page. The text in quote marks is the name of anchor you’ll use
when linking to it.
One of the more powerful features of using Markdown is the ability to mix HTML and Markdown in the same document. With
this in mind it is also possible to use normal HTML to create an anchor in a page. This is the method you need to use
when adding anchors to markdown documents not in the GitLab Handbook.
Hugo and Docsy provide support for using both Emojis and Font Awesome to provide icons and simple graphics to spice up
your content.
To insert emojis in to content you can use the same syntax as you find on GitLab and Slack. Use a :
followed by the
name of the emoji followed by another :
. Its also possible to look up emojis on the ‘Emoji Cheat Sheet’.
Note: When copying from the cheatsheet it includes the colons for you.
Font Awesome
Font Awesome provides over 2000 free to use and open source glyphs and icons which can be
embedded into handbook content to visually spice things up. The easiest way to use Font Awesome is to copy the HTML for
the glyph directly from the Font Awesome Icon gallery and paste it directly
in to your content.
Splash of color
It is possible to add a splash of color to Font Awesome icons by adding -text-<color>
(for example -text-success
) to the end of the class
definition. Where it says color you can replace this with any of the available shortcode colors.
Embed documents
It’s easy to embed Google Docs, Sheets, Slides, and pretty much everything that
provides an iframe to use with. The only thing you need to do is use the
following code inside your markdown file and replace the iframe from the document
you want to embed:
<iframe IFRAME CONTENT></iframe>
For Google products, with your document opened, click File -> Publish to the web.
For example, here’s what Google sheets will look like:
Choose Embed, check your settings, click on Publish and copy the <iframe>
.
Then go to your markdown file and wrap the iframe into a {{< gdoc >}}
short code.
The shortcode makes the iframes the right size on the page and allows them to be resized
by the user.
Let’s exemplify with this [simple spreadsheet]. Follow the info above to find the iframe:
Copy the code below and paste to your markdown file (leave a blank line above and below it). Then replace the <iframe>
with your own:
{{< gdoc >}}
<iframe src="https://docs.google.com/spreadsheets/d/1jAnvYpRmNu8BISIrkYGTLolOTmlCoKLbuHVWzCXJSY4/pubhtml?widget=true&headers=false"></iframe>
{{< /gdoc >}}
Google Slides
Let’s exemplify with this GitLab slide deck.
Follow the steps above to find the iframe:
Copy the code below and paste to your markdown file (leave a blank line above and below it). Then replace the <iframe>
with your own:
{{< gdoc >}}
<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vS_iuMXnp61wlo4amm5nvHr4Ir8VUzisJSBsr7YEL7fKWAiT-9bmehyngtb9TYaFEsFnRokCyIXwsvY/embed?start=false&loop=false&delayms=3000"
frameborder="0" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
{{</ gdoc >}}
{{< gdoc >}}
<iframe src="https://docs.google.com/document/d/1mHhOhvvrz7xgUPyn5VWCNuKgew5MRRGZp761B9prPqs/pub?embedded=true"></iframe>
{{< /gdoc >}}
X/Twitter changed its usage policy, and might add rate limits. Sometimes, tweets cannot be loaded when embedded,
and fail CI/CD builds or the deployed handbook (see the issue discussion).
Create a screenshot of the tweet instead, and upload the image into the handbook.
Embed GitLab Snippets
To embed GitLab Snippets
to a markdown file, copy the embed code from your public snippet and paste it in the file.
<!-- leave a blank line here -->
<script src="https://gitlab.com/gitlab-org/gitlab-ce/snippets/1717978.js"></script>
<!-- leave a blank line here -->
Other Embeds
Other embeds can be included in the handbook, as outlined in Embed documents.
However, due to privacy (especially cookie) concerns, we recommend only embedding from sites
outlined in our tech stack,
or where “no cookies” can be specified.
Mathematical and other formulae are supported through the use of LaTeX markup.
The Hugo implementation uses the MathJax engine.
The frontmatter parameters must have math:
set to true
.
This is an inline \\(a^\*=x-b^\*\\) equation.
These are block equations:
\\[a^\*=x-b^\*\\]
\\[ a^\*=x-b^\* \\]
a^\*=x-b^\*
This is an inline \(a^*=x-b^*\) equation.
These are block equations:
\[a^*=x-b^*\]
\[ a^*=x-b^* \]
a^*=x-b^*
Line length
We do not enforce a line length (MD013).
Please use the editors available on GitLab.com, one of the following code editors, or your preferred code editor to
write in markdown.
It is not recommended writing your document in a regular text editor like Google Docs, Microsoft Word, or macOS’
Pages, then copy-pasting to markdown, as it most likely will bring some characters with a different encoding
(non UTF-8), which will cause the markdown to not render correctly.
In case you don’t have a choice and need to import a text already written in a text editor, paste it
to your markdown file using command+shift+V on a Mac, or control+shift+V on Windows or Linux.
You might minimize the cause of trouble by pasting without format. But yet, is not guaranteed it
is going to work, so double check your output.
If the document was in Google Docs, you can install the Docs to Markdown
add-on, which helps convert the Google Docs to markdown. You’ll likely need to make minor updates or edits to the
markdown that the add-on generates.
Editors Available on GitLab.com
Web IDE
Web Editor
Regular Code Editors
Visual Studio Code
Sublime Text
NeoVim
Markdown editors (type and preview simultaneously)
Markdown editors for Mac: [MacDown], [iA Writer], [Ulysses]
In-browser markdown editor: [StackEdit]
Markdown Tables Generator
If you’re not used to writing markdown, these editors can be helpful. Many editors offer real time previews and while
these previews may not be exactly the same as the final result they can be a very good approximation, which gives you a
good idea of what the output will be while you type.
[StackEdit] is awesome too, you can work on a markdown file even if you’re away from your computer,
or out of resources. It works from every major browser and automatically saves your work to Google Drive.
Do you want a simple way of copying a hyperlink title and address in markdown? The Format Link
extension offers a quick and easy way to do this, along with allowing you to customize any number of other formats.
View detailed instructions and examples.
If you’re looking for just the ability to copy something as markdown, try
these Firefox add-ons
or Chrome extensions.
Complementary Notes
Words must be separated by one single space only. Do not leave more blank spaces than the necessary,
they can render differently than expected and can cause other issues.
Do not leave blank spaces at the end of sentences.
Always leave a blank line between block-level markup elements, except between list items. Example: