
What Is Markdown?
Markdown is a lightweight markup language — a way of adding formatting to plain text using simple punctuation. The idea is that the source file should be readable as-is, without rendering, and that converting it to HTML (or PDF, or DOCX, or anything else) should be trivial.
You write this:
**This is bold** and *this is italic*.
And a renderer turns it into: This is bold and this is italic.
That’s it. No toolbar, no hidden XML, no format lock-in. Just text.
A Brief History
Markdown was created by John Gruber (of Daring Fireball) in 2004, with significant contributions from Aaron Swartz. Gruber’s stated goal was simple: make it as easy to write for the web as it is to write email.
The design was deliberately inspired by pre-existing email conventions. When people wrote plain-text emails in the 1980s and 90s, they naturally developed conventions: *asterisks around words* for emphasis, > for quoting a previous message, --- for horizontal rules. Markdown codified those habits into a spec.
The original implementation was a Perl script that converted .md files to HTML. It was intentionally minimal — Gruber resisted feature creep, which is why the official Markdown spec stayed small.
Over time, different platforms extended it in different directions: GitHub added tables and task lists (GitHub Flavored Markdown, or GFM), Pandoc extended it for academic writing, and CommonMark emerged as an effort to standardize the ambiguous corners of the original spec. Today “Markdown” really means a family of compatible-but-not-identical dialects. Hugo supports CommonMark via Goldmark by default.
The Syntax That Matters
Headings
Headings are marked with # signs — one for the main heading, two for secondary, and so on.
# One for main heading
## Two for secondary heading
### Three for third level
A few strong opinions worth adopting:
- Keep the
# H1as the first line of the document so it can be parsed easily by tools and feed readers. - Use only one
H1per document. It’s the title, not a recurring decoration. - In practice,
###is about the smallest heading that renders with enough visual distinction to be useful.####and below are hard to distinguish in most renderers. - Never use headings for formatting. Headings carry semantic meaning — they signal document structure to screen readers, search engines, and parsers. Using
##just to make some text big is the equivalent of using<h2>in HTML for the same lazy reason. Don’t.
Block Elements
Paragraphs are just lines of text separated by a blank line. A line break within a paragraph doesn’t produce a <br> — you need a blank line to start a new paragraph.
Unordered lists use - as the bullet character (though * and + also work — pick one and stick with it):
- A thing
- a sub thing
- Another thing
Ordered lists use 1. for every item — the renderer handles the actual numbering. This means you can reorder items without renumbering:
1. One
1. One.One
1. One.Two
1. Two
1. Three
Code fences use triple backticks, with an optional language tag for syntax highlighting:
```sh
#!/bin/sh
echo hello world
```
If you need to include a code fence inside a code fence (say, when writing Markdown documentation), use tildes for the outer fence:
~~~md
```sh
#!/bin/sh
echo hello world
```
~~~
Blockquotes use > at the start of each line, reflecting the old email convention:
> Here is something from an 80s email
> with a bunch of lines.
For long multi-paragraph quotations this gets unwieldy. A practical rule: use blockquotes for single-paragraph pull quotes. For longer quoted passages, just attribute them inline as prose.
Horizontal rules are four dashes:
----
There are other syntaxes (***, ---, ___) but pick one form and be consistent.
Tables are not part of the original Markdown spec but are supported by GFM and most modern renderers including Goldmark:
| Name | Color |
| -: | - |
| Rob | Blue |
| Doris | Red |
Use them sparingly and only when the data is genuinely tabular.
One hard rule: never put raw HTML in your Markdown — except possibly HTML comments when you need to disable a section. Mixing HTML and Markdown breaks portability, complicates rendering pipelines, and usually signals that you’re trying to do something the format isn’t meant for. Find the Markdown way, or question whether Markdown is the right tool at all.
HTML comments are the one exception, and they’re useful:
<!--
This content is disabled and won't appear when rendered.
-->
Inline Elements
*Single asterisk for italic*
**Double asterisk for bold**
***Three for bold italic***
`backtick for inline code`
A few things to watch out for:
- Don’t mix conventions. Some platforms (Slack, notably) use
_underscores_for italic and*single asterisk*for bold — the opposite of standard Markdown. Know your renderer. - Avoid mixing formats when you can help it.
_I am *really* italic!_technically works, but it’s fragile across renderers and hard to read in source. - Use inline code (backticks) for anything that’s a filename, command, variable name, or literal string. It signals “interpret this literally” to the reader, which is often exactly what you want.
Links
Inline links:
[link text](https://example.com)
Bare URLs (auto-linked in most renderers):
<https://example.com>
Reference-style links keep the prose clean when URLs are long:
Check out [this site][myref] for more.
[myref]: https://example.com
The reference label can also match the link text exactly, making it even more concise:
Visit [Example][] for more.
[Example]: https://example.com
If on GitHub or a render platform that supports it, just [Example].
[Example]: https://example.com
Images
Images follow the same syntax as links but with a ! prefix. The text in brackets is the alt text:

Alt text matters — it’s what screen readers use and what appears when an image fails to load. Don’t leave it empty unless the image is purely decorative.
A local image ref could also be used:

The Philosophy in One Paragraph
Markdown’s value is portability and readability. A .md file opened in Notepad twenty years from now will still be readable and its intent will be clear. The formatting conventions are readable as conventions, not as noise. That’s the whole deal. Every time you’re tempted to reach for an HTML tag, a fancy table, or a sixth-level heading, ask whether what you’re trying to do could be expressed more simply in plain prose. Usually, it can.