Markdown in 10 Minutes: The Essential Syntax You Actually Need

Markdown is probably the most productive language youll ever learn -- a few dozen rules, useful for the rest of your career. README files on GitHub, issues on GitLab, messages on Discord, docs in MkDocs, blog posts in Hugo, notes in Obsidian -- Markdown is the common denominator everywhere. This article walks through every essential rule with a small example, explains the difference between CommonMark and GitHub Flavored Markdown, and clears up the classic pitfalls everyone hits at least once.

A short history (two minutes)

Markdown was invented in 2004 by John Gruber with Aaron Swartz. Grubers design goal was uncompromising: the source should read like a cleanly written email, not like code. It should stay legible even if no one ever turns it into HTML. That philosophy explains the seemingly arbitrary decisions -- why lists start with a plain dash instead of a tag, why a blank line defines a paragraph, why a heading is marked with a pound sign.

The problem: Grubers original spec was riddled with ambiguity. Each parser interpreted edge cases differently, fragmenting implementations. In 2014 Jeff Atwood, John MacFarlane, and others started CommonMark, a precise, test-driven spec with more than 600 test cases. Alongside it, GitHub Flavored Markdown (GFM) appeared as a formal extension with tables, task lists, strikethrough, and autolinks. Today most tools follow CommonMark or GFM -- or both.

Headings

Headings come in six levels, marked by one to six pound signs at the start of the line, followed by a space. CommonMark also accepts the older Setext notation (underlining with equals signs for H1 or dashes for H2), but the ATX form (with #) is clearer and effectively universal in practice.

# H1 heading
## H2 heading
### H3 heading
#### H4 heading
##### H5 heading
###### H6 heading

Important rule: a blank line before and after every heading -- many parsers tolerate the absence, but consistent readability wins. More than six pound signs are no longer a heading and render as text.

Emphasis: italic, bold, strikethrough

Markdown uses asterisks or underscores for emphasis. One character around text makes italic, two make bold, three make bold italic. GFM adds strikethrough with double tildes. Watch out for underscores inside identifiers -- snake_case_variable would otherwise go half italic. CommonMark guards against this heuristically; older parsers do not.

*italic* or _italic_
**bold** or __bold__
***bold italic***
~~strikethrough~~ (GFM)

Lists, ordered and unordered

Unordered lists start with -, *, or + followed by a space. Ordered lists start with a number and a period. Crucially: the renderer renumbers anyway -- you can write every item as 1. and get a correctly numbered list 1, 2, 3, 4. Nesting uses two or four spaces of indentation.

- first item
- second item
  - nested
  - another nested
- third item

1. step one
1. step two
1. step three

Classic bug: missing blank line between the previous paragraph and a list -- the parser treats the list as a continuation of the paragraph and the dash shows up as text. Always leave a blank line before a list.

Links and images

Links consist of the link text in square brackets followed by the URL in parentheses. An optional title in quotes follows as a browser tooltip. Reference-style links separate text and URL -- handy for long documents where the same URL appears multiple times. Autolinks simply wrap a URL in angle brackets and the parser turns it into a clickable link. Images work like links with a leading exclamation mark and alt text in the square brackets.

[CalcSI](https://calcsi.com "Online tools")

[reference][1]

[1]: https://example.com

<https://autolink.example>

![alt text](https://example.com/image.png)

SEO and accessibility tip: alt text isnt optional. Screen readers read it aloud, search engines read it as a content description. An empty alt (![](url)) is only justified for purely decorative images.

Code: inline and blocks

Inline code goes in backticks -- ideal for function names, variables, or short commands in running text. Code blocks span multiple lines and are wrapped in three backticks at the start and end. An optional language identifier after the opening backticks enables syntax highlighting in most renderers (GitHub, Prism, Highlight.js). If your code itself contains backticks, just use four or more backticks around the block.

Inline: `let x = 42;`

Fenced block with language:

```javascript
function greet(name) {
  return `Hello, ${name}`;
}
```

Alternative: four spaces of indentation also define a code block (classic notation), but fenced blocks with backticks are the de-facto standard everywhere because they also support language hints.

Tables (GFM)

Tables are not part of CommonMark, but GitHub Flavored Markdown defines them cleanly -- and every relevant tool supports them. Cells are separated by pipes, and the second row of dashes marks the header. Alignment is controlled by colons: :--- left, :---: center, ---: right.

| Format | Speed       | Readability |
|:-------|:-----------:|------------:|
| JSON   | very high   |         low |
| YAML   | medium      |        high |
| TOML   | high        |        high |

Source columns dont need to line up -- the renderer takes care of that -- but neatly aligned Markdown source reads like a table even unrendered. Thats exactly what Markdown was invented for.

Blockquotes, horizontal rules, tasks, footnotes

Five building blocks that come up in real-world writing and often get overlooked:

  • Blockquotes: > at the start of a line. Nest with >>, >>>. Any Markdown can live inside, including lists and code blocks.
  • Horizontal rule: three or more dashes, asterisks, or underscores on their own line, surrounded by blank lines. Renders as <hr>.
  • Task lists (GFM): - [ ] for open, - [x] for done. Perfect for issue templates, TODO lists, release checklists. Clickable on GitHub.
  • Footnotes (GFM extension): in the body [^1], somewhere below [^1]: footnote text. The renderer collects them at the end of the document.
  • Escaping: a backslash protects any Markdown special character. \*not italic\* renders literally. Useful in documentation where asterisks should remain text.
> This is a blockquote.
>
> > Nested.

---

- [x] Learn Markdown
- [ ] Write your own cheatsheet

This sentence has a footnote[^1].

[^1]: Here is the explanation.

Classic pitfalls

Three mistakes almost everyone makes once. First: line break behavior is not intuitive. A single newline in the source ends up in the same paragraph in the output. To get a real break (<br>), end the line with two spaces or insert a blank line. On GitHub and in many chat apps, however, the single newline is honored -- thats a GFM deviation from the standard, made because it feels more natural for chat-style input.

Second: lists need a blank line before them or they become paragraph text. Third: ordered lists dont always start at the expected number when you write 3. as the first item -- in CommonMark the list actually starts at 3, but many older parsers silently restart at 1. Test your specific renderer if you intend to rely on this. Safe default: always start at 1..

Where Markdown lives today

Markdown is the default language for technical writing on the web. GitHub and GitLab use it for READMEs, issues, pull requests, and wikis. Discord renders a reduced variant in messages; Slack uses its own subset. Static site generators -- Hugo (Go), Jekyll (Ruby), Astro and Next.js (JavaScript) -- take Markdown as source and produce HTML. Documentation systems like MkDocs, Docusaurus, Sphinx (via MyST), and VitePress follow the same pattern.

Beyond the web, Markdown won too: Obsidian, Notion (with extensions), Bear, iA Writer, Typora all store notes as Markdown files. Upside: your writing belongs to you and stays readable in ten years no matter which tool survives. For a quick preview without an editor, use the Markdown-to-HTML converter on CalcSI -- input on the left, rendered HTML on the right, all in the browser.

Frequently asked questions

Whats the difference between Markdown and MDX?

MDX is Markdown plus JSX. You can drop React components directly into Markdown source, like <Chart data={...} /> in the middle of a paragraph. Popular in modern docs systems like Docusaurus and Next.js because interactive demos and prose live in the same file. Downside: MDX files no longer render in every Markdown renderer -- without a JSX toolchain you just have source. For pure docs and blogs, plain Markdown or GFM is enough -- only reach for MDX when you actually need components.

How safe is it to render arbitrary Markdown to HTML?

Markdown itself allows raw HTML -- an attacker can write a <script> tag directly into Markdown and the default renderer would emit it. Any app that renders user-supplied Markdown (forum, comments, CMS) must sanitize the HTML output with a library like DOMPurify or a server-side allowlist. GitHub, GitLab, and CalcSI all do this -- its a hard security rule, not a comfort question. Render raw and you have an XSS hole.

Can I embed diagrams in Markdown?

On GitHub and many modern renderers (Obsidian, GitLab, MkDocs with a plugin): yes, via Mermaid in a code block tagged mermaid. You write the diagram definition there (flowchart, sequence diagram, class diagram) and the renderer turns it into SVG. Upside: diagrams live in the same repo as the code and get versioned. Downside: not every Markdown parser knows Mermaid -- for maximum portability, an embedded image is still safest.

Disclaimer: This article describes standard Markdown per CommonMark 0.31 and GitHub Flavored Markdown. Individual renderers (Discord, Slack, Notion) implement a subset or their own extensions -- when in doubt, check the specific tool youre writing in.

Comments