Skip to main content

Markdown style guide

Much of what makes Markdown great is the ability to write plain text and get great formatted output as a result. We want to keep our source Markdown as simple and consistent as possible to make it easier for our many authors to contribute to Gruntwork documentation over time. It’s much easier to understand and make edits to a large collection of docs when they all share a consistent style.

We seek to balance three goals:

  1. Legibility. Source text is readable and portable.
  2. Maintainability. Markdown files are maintainable over time and across teams.
  3. Simplicity. The syntax is simple and easy to remember.

Document structure

General outline

In general, most documents benefit from some variation of the following layout:

# Document Title

Short introduction.

## Topic


## Another Topic

More content.
  1. # Document Title: The first heading should be a level one heading, and should ideally be the same or nearly the same as the filename. The first level one heading is used as the page <title>. In nearly all cases, you should only include one level one heading in the file.

  2. Short introduction. 1-3 sentences providing a high-level overview of the topic. Imagine yourself as a complete newbie, who landed on your "Extending Foo" doc and needs to know the most basic assumptions you take for granted. "What is Foo? Why would I extend it?"

  3. ## Topic: The rest of your headings should start from level 2.

Table of contents

Markdown doesn't include native syntax for a table of contents. While a TOC can help readers find relevant content on longer pages more easily, they are difficult to maintain and can easily get out of sync with the content.

Because both GitHub (where our code and READMEs are hosted) and Docusaurus (where our documentation is hosted) provide an auto-generated table of contents based on the headers in the document, you should generally omit a TOC from your document and rely on the rendering context to provide one.

You may make an exception to this rule in order to provide smaller, inline TOCs which enumerate only the items within a given section of the document, as a means of introducing what comes next.

Intermediate line breaks

Unless otherwise indicated, all markdown elements in your document should be separated by exactly one blank line. Preserving a small gap makes it easier to identify individual elements in the source. However, avoid using multiple blank lines as this can lead to inconsistent spacing and longer source files.

Character line limit

Obey projects' character line limit wherever possible. Long URLs and tables are the usual suspects when breaking the rule. (Headings also can't be wrapped, but we encourage keeping them short). Unless instructed otherwise, wrap your text to 120 characters:

Lorem ipsum dolor sit amet, nec eius volumus patrioque cu, nec et commodo
hendrerit, id nobis saperet fuisset ius.

- Malorum moderatius vim eu. In vix dico persecuti. Te nam saperet percipitur
interesset. See the [foo docs](

Often, inserting a newline before a long link preserves readability while minimizing the overflow:

Lorem ipsum dolor sit amet. See the
[foo docs](
for details.

Ending newline

All files should end with a single empty line to avoid any potential tool incompatibilities. But, let's be honest — do it because we don't like seeing \ No newline at end of file in our diffs.


To create paragraphs, use a single blank line to separate one or more lines of text.

This is a paragraph. Make it as long as you want,
and wrap text as needed.

This is the beginning of a second paragraph.

Don't indent the first line of a paragraph unless it part of a list. This can cause unexpected formatting issues, and makes it harder to read.

    The first line of this paragraph is indented, which may
cause it to be interpreted incorrectly.

No trailing whitespace

Don't use trailing whitespace, use a trailing backslash.

The CommonMark spec decrees that two spaces at the end of a line should insert a <br /> tag. However, many directories have a trailing whitespace presubmit check in place, and many IDEs will clean it up anyway.

Best practice is to avoid the need for a <br /> altogether. Markdown creates paragraph tags for you simply with newlines: get used to that.


ATX-style headings

## Heading 2

Headings with = or - underlines can be annoying to maintain and don't fit with the rest of the heading syntax. The user has to ask: Does --- mean H1 or H2?

Heading - do you remember what level?

Add spacing to headings

Prefer a single space after # and newlines before and after:

...text before.

# Heading 1

Text after...

Lack of spacing makes it a little harder to read in source:

...text before.

#Heading 1
Text after...


Double asterisks for bold text

For clarity, always bold text by surrounding it with double asterisks. This also ensures that it works properly when attempting to bold a portion of a longer word.

**bold text**

Avoid using double underscores for bold text, as it's harder to distinguish from italics at a glance.

__This is also bold.__

Single underscores for italics

For clarity, always italicize text by surrounding it with single underscores.

_italicized text_

Avoid using single asterisks for italicized text, as it's harder to distinguish from bold text at a glance.

*This is also italicized.*


Dashes for bulleted lists

Prefer dashes (-) for all bulleted lists over asterisks (*) or plus signs (+).

- Foo.
- Bar.
- Baz.

They're a touch easier to type and make it easier to recognize what's going on if the list item opens with bold text. This has reasonable legibility:

- **Foo.** foo foo
- **Bar.** bar bar
- **Baz.** baz baz

Whereas this does not:

* **Foo.** foo foo
* **Bar.** bar bar
* **Baz.** baz baz

Lazy numbering for long lists

Markdown is smart enough to let the resulting HTML render your numbered lists correctly. For longer lists that may change, especially long nested lists, use "lazy" numbering:

1.  Foo.
1. Bar.
1. Foofoo.
1. Barbar.
1. Baz.

However, if the list is small and you don't anticipate changing it, prefer fully numbered lists, because it's nicer to read in source:

1.  Foo.
2. Bar.
3. Baz.

Consistent indentation

When nesting lists, use a 4 space indent for both numbered and bulleted lists:

1.  Two spaces after a numbered list.
Four space indent for wrapped text.
2. Two spaces again.

- Three spaces after a bullet.
Four space indent for wrapped text.
1. Two spaces after a numbered list.
Eight space indent for the wrapped text of a nested list.
2. Looks nice, right?
- Three spaces after a bullet.

The following works, but it's very messy:

- One space,
with no indent for wrapped text.
1. Irregular nesting...

Even when there's no nesting, using the 4 space indent makes layout consistent for wrapped text:

-   Foo,

1. Two spaces after the numeral,
and four space indenting.
2. Two spaces again.

However, when lists are small, not nested, and a single line, one space can suffice for both kinds of lists:

- Foo
- Bar
- Baz

1. Foo
2. Bar

Inter-item spacing

For lists with concise items most or all of which fit on one line, do not leave an empty line between list items:

- Foo
- Bar
- Baz

Leaving gaps like this produces gaps in the rendered output also, which leads to lists which appear to lack structure:

- Foo

- Bar

- Baz

However, if many of your list items are longer and wrap onto multiple lines, a blank line between list items improves legibility by making it easy to see where each one begins:

1.  This is a list item that's long enough to wrap onto multiple lines when
rendered on the page.

2. In circumstances like these, it's helpful to leave a blank line between each
list item to help distinguish one from the next and improve legibility in
both the source and the output.

3. A third list item helps make the point, even if it doesn't wrap itself.
1.  This is a list item that's long enough to wrap onto multiple lines when
rendered on the page.
2. In circumstances like these, it's helpful to leave a blank line between each
list item to help distinguish one from the next and improve legibility in
both the source and the output.
3. A third list item helps make the point, even if it doesn't wrap itself.



`Backticks` designate inline code, and will render all wrapped content literally. Use them for short code quotations and field names:

You'll want to run ` arg`.

Pay attention to the `foo_bar_whammy` field in that table.

Use inline code when referring to file types in an abstract sense, rather than a specific file:

Be sure to update your ``!

Backticks are the most common approach for "escaping" Markdown metacharacters; in most situations where escaping would be needed, code font just makes sense anyway.


For code quotations longer than a single line, use a codeblock:

def Foo(self, bar): = bar

Declare the language

It is best practice to explicitly declare the language, so that neither the syntax highlighter nor the next editor must guess.

Indented codeblocks are sometimes cleaner

Four-space indenting is also interpreted as a codeblock. These can look cleaner and be easier to read in source, but there is no way to specify the language. We encourage their use when writing many short snippets:

You'll need to run:

bazel run :thing -- --foo

And then:

bazel run :another_thing -- --bar

And again:

bazel run :yet_again -- --baz

Escape newlines

Because most commandline snippets are intended to be copied and pasted directly into a terminal, it's best practice to escape any newlines. Use a single backslash at the end of the line:

bazel run :target -- --flag --foo=longlonglonglonglongvalue \

Nest codeblocks within lists

If you need a codeblock within a list, make sure to indent it so as to not break the list:

- Bullet.

int foo;

- Next bullet.

You can also create a nested code block with 4 spaces. Simply indent 4 additional spaces from the list indentation:

- Bullet.

int foo;

- Next bullet.


Include > on every line

To create a blockquote, add a > in front of each line of a content block, (including any blank lines):

> Our mission at Gruntwork is to make it 10x easier to understand, build, and
> deploy software.
> Your Entire Infrastructure.
> Defined as code.
> In about a day.

Don't omit the > even in contexts where the Markdown syntax supports it, such as a single paragraph. Including it on each line improves clarity in the source and retains consistency with multi-paragraph blockquotes or those that contain formatted content like lists, which require it.

> Our mission at Gruntwork is to make it 10x easier to understand, build, and
deploy software.


Use admonitions to call attention to particular details within the body of a doc, such as a cautionary warning, or a bit of supplemental information that isn’t essential to its primary reading. Our documentation supports a custom syntax for this purpose. Below, we also provide a means of simulating admonitions in native Markdown syntax.

Docusaurus admonitions

Docusaurus admonitions come in several flavors depending on the type or severity of the information being communicated: note, tip, info, caution, and danger.

Use the following custom syntax in documentation:


Keep in mind that…


You can also provide a custom title:

:::tip Did you know…

I'll bet you didn't!


See the Docusaurus documentation for additional details.

Simulated admonitions

When writing Markdown that won't appear in our documentation site the above syntax will be rendered in plain text. In such cases, you can approximate the same appearance using a blockquote with bold text on the first line:

> **NOTE**
> This text appears like a callout on the page.

When a simulated admonition of this kind is imported into our documentation, it will be automatically translated into the Docusaurus admonition syntax and appear rendered in the same style.

Feel free to use phrasing like "Note that…" in the body of a paragraph, but avoid using it to open a paragraph with a colon:

Note: This text won't appear with any custom styling.

Expandable details

Although you should generally avoid HTML, the <details> element enables readers to expand and collapse sections of content on the page. This is useful when content needs to be made available, but needn't be presented in the default view of the page where it could make it needlessly long or distract from the main message.

You may use this native HTML element directly in your Markdown, as it is supported by both GitHub and Docusuarus:

<summary>Details toggle example</summary>

Expandable markdown content. Take note of:

1. The blank line above this content
2. The blank line below this content


Use an informative title in the summary to make clear what it contains. In order to utilize Markdown within the body, ensure that you leave a blank line both after the summary and before the closing </details> tag.

Use inline links within your document. This makes it easier for authors to see where a link leads in context. However, long links make source Markdown difficult to read and can break the line limit. Wherever possible, shorten your links.

Markdown link syntax allows you to set a link title, just as HTML does. Use it wisely.

Titling your links as "link" or "here" tells the reader precisely nothing when quickly scanning your doc and is a waste of space:

See the syntax guide for more info: [link](
Or, check out the style guide [here](

Instead, write the sentence naturally, then go back and wrap the most appropriate phrase with the link:

See the [syntax guide]( for more info.
Or, check out the [style guide](

Avoid bare links without any syntax, as these won't be rendered reliably in all contexts:

This is a bare link to

If you wish to present a link as its own link text, wrap it in angle brackets:

This is a proper link to <>

If you're using the text of a link purely informatively and do not want it to function as a link, use backticks to treat it as inline code:

This link to `` is for informational purposes only.

Email addresses

Use angle brackets to automatically create mailto links for any emails:

Contact <>.


Feel free to use images to support your text. Diagrams and illustrations can aid visual learners and help explain difficult concepts; and screenshots can provide clarity when explaining how to interact with software. However, avoid superfluous imagery or photography that doesn't directly help you communicate your message.

Provide Alt Text

Always specify alt text for your images to improve accessibility by providing text in the brackets preceding the link:

![Describe the image briefly](/img/path/to/image.png)

Omitting the alt text is bad for accessibility.



Markdown doesn't support captions natively. However, you can approximate captions by placing italicized text on the line immediately after your image (omit a blank line). This provides basic formatting that looks good in most Markdown rendering contexts, and also enables custom styling in our documentation platform.

![Describe the image briefly](/img/path/to/image.png)
_This is a custom caption_

In documentation, you don't need to supply a caption unless you want it to differ from the provided alt text. The documentation platform will automatically create a caption using the alt text for you, which you can then override by using the technique described above.


Our documentation platform automatically enables a feature which allows users to zoom in on an image with a click. Disable this feature for any images which don't require it, or have sufficiently small size/resolution so as to make the resulting scaled image unhelpful.

To do so, surround the image syntax itself in underscores:

_![This image cannot be zoomed](/img/path/to/image.png)_

Currently, automatic captions are not supported on images which can't be zoomed.

Horizontal rules

Avoid horizontal rules when possible. Instead, focus on creating a clean outline using multi-level headers. If you need to isolate a section of content, consider linking to it on a separate page.

When you do decide to use a horizontal rule, always use three dashes (---) on a line by themselves, surrounded by blank lines. Don't use three underscores (___) or three asterisks (***).

Always put a blank line before…


…and after a horizontal rule.

Using mixed characters and/or omitting spaces makes rules harder to identify.

Without a gap…
…the rule is harder to spot.


Any tables in your Markdown should be small. Large, complex tables are difficult to read in source and most importantly, a pain to modify later (although online tools and IDE features like those for Vim and VSCode can help).

Keep two considerations in mind when deciding if a table is appropriate:

  1. Number of columns. Tables with too many columns can exceed the width of text editors, causing individual rows to wrap onto multiple lines and making them virtually impossible to read in the source. Prefer tables with only a few columns.

  2. Length of cell content. Text within cells can't wrap, so even short sentences in any of your cells can cause the width of the table to explode quicky. Prefer tables with concise data.

Consider lists for complex content

Lists and subheadings often suffice to present the same information in a slightly less compact, though much more edit-friendly way. This can also keep all relevant information for a particular item visible to readers at once, without requiring horizontal scrolling.

## Fruits

### Apple

- [Juicy](https://SomeReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongURL)
- Firm
- Sweet

Apples keep doctors away.

### Banana

- [Convenient](
- Soft
- Sweet

Contrary to popular belief, most apes prefer mangoes.
| Fruit  | Attribute                                                                                                             | Notes                                                 |
| ------ | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| Apple | [Juicy](, Firm, Sweet | Apples keep doctors away. |
| Banana | [Convenient](, Soft, Sweet | Contrary to popular belief, most apes prefer mangoes. |

However, there are times when a small table is called for:

| Transport        | Favored by     | Advantages                    |
| ---------------- | -------------- | ----------------------------- |
| Swallow | Coconuts | Otherwise unladen |
| Bicycle | Miss Gulch | Weatherproof |
| X-34 landspeeder | Whiny farmboys | Cheap since the X-38 came out |

Use reference style links in tables to keep the contents of each cell as short as possible. Include the link definitions immediately beneath the table (not at the end of the file) where readers can find them in context.

| Fruit  | Attribute                    | Notes                          |
| ------ | ---------------------------- | ------------------------------ |
| Apple | [Juicy][1], Firm, Sweet | Apples keep doctors away. |
| Banana | [Convenient][2], Soft, Sweet | Actually, apes prefer mangoes. |

[1]: https://SomeReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongURL

Strongly prefer Markdown to HTML

Please prefer standard Markdown syntax wherever possible and avoid HTML hacks. If you can't seem to accomplish what you want, reconsider whether you really need it. Except for big tables, Markdown meets almost all needs already.

Every bit of HTML or Javascript hacking reduces the readability and portability. This in turn limits the usefulness of integrations with other tools, which may either present the source as plain text or render it.

CC iconCC by iconLicense

This Markdown style guide is adapted from one provided by Google under a Creative Commons 3.0 Attribution License. It may be freely shared and further adapted according to the license terms.