This is the Markdown syntax reference you can bookmark and come back to. Every element covered with a real example — headings, emphasis, links, images, lists, code blocks, tables, blockquotes, and more. Where a feature is part of standard CommonMark it's marked as such; extensions from GitHub Flavored Markdown (GFM) are called out explicitly so you know what's universally supported and what depends on the renderer.

Headings

Markdown has two heading styles. The ATX style uses hash characters — one # for h1 through six ###### for h6. The setext style uses underlines of = or - characters and only reaches h1 and h2. ATX is the style you should use everywhere — it's explicit, it scales to all six levels, and it's what every tool supports. One common mistake: forgetting the space after the #. Strictly speaking, #Heading is not a heading in CommonMark — the space is required.

markdown
# Page Title (h1)
## Section Heading (h2)
### Subsection (h3)
#### Detail Level (h4)
##### Minor Heading (h5)
###### Smallest Heading (h6)

---

<!-- Setext style — only h1 and h2, rarely used -->
Page Title
==========

Section Heading
---------------

In a real document, you typically use one h1 at the top (the document title), h2 for major sections, and h3 for subsections within those. Going deeper than h3 is a signal your document might need restructuring rather than another level of nesting.

Leave a space after the #. #Heading is silently treated as a paragraph by many strict parsers. The CommonMark spec requires at least one space between the # characters and the heading text.

Text Formatting

Bold uses double asterisks or double underscores. Italic uses single asterisks or single underscores. Bold-italic combines three of either. Strikethrough is a GFM extension and uses double tildes. Inline code uses backticks.

markdown
**Bold text** or __Bold text__
*Italic text* or _Italic text_
***Bold and italic*** or ___Bold and italic___
~~Strikethrough~~ (GFM only)
`inline code`

The * and _ variants are mostly interchangeable, but they differ in one edge case: mid-word emphasis. Asterisks work mid-word (un*believe*able renders as unbelieveable), but underscores do not — un_believe_able renders literally in CommonMark because underscores inside words are treated as word characters, not emphasis markers. This matters in technical writing where underscores appear in identifiers. As a rule: use * for emphasis and reserve _ only if you have a strong style preference. Do not mix * and _ within the same emphasis span — *text_ will not close correctly.

Links and Images

There are three link styles: inline links, reference links, and autolinks. Images follow the same syntax as inline links but with a ! prefix.

markdown
<!-- Inline link: [text](url) or [text](url "title") -->
Read the [CommonMark spec](https://spec.commonmark.org/current/ "CommonMark Specification")
Format Markdown with the [Markdown Formatter](/markdown-formatter)

<!-- Reference link: define the URL separately — cleaner in long documents -->
Check the [GFM spec][gfm] for GitHub-specific extensions.

[gfm]: https://github.github.com/gfm/

<!-- Autolink: angle brackets make a URL or email clickable -->
<https://commonmark.org>
<[email protected]>

<!-- Image: same as inline link but with ! prefix -->
![Project screenshot](./docs/screenshot.png "Dashboard view")
![Alt text for accessibility](https://example.com/logo.png)
Images in Markdown have no width or height attributes. The ![alt](url) syntax maps to a plain <img> tag with no sizing. If you need to control image dimensions, you have to drop into raw HTML: <img src="url" alt="text" width="400">. This is a known limitation — the Markdown Guide covers the workaround.

Lists

Unordered lists use -, *, or + as bullet markers. Ordered lists use numbers followed by a period. Nest lists by indenting two or four spaces. Task lists (GFM) use [ ] for unchecked and [x] for checked items.

markdown
<!-- Unordered list -->
- Install dependencies
- Configure environment variables
- Run the dev server

<!-- Ordered list -->
1. Clone the repository
2. Run `npm install`
3. Copy `.env.example` to `.env` and fill in values
4. Run `npm run dev`

<!-- Nested list (indent 2 or 4 spaces) -->
- Backend
  - Set up PostgreSQL
  - Configure connection string
- Frontend
  - Install Tailwind
  - Configure PostCSS

<!-- Task list (GFM) — great for README checklists -->
## Release Checklist

- [x] Unit tests passing
- [x] End-to-end tests passing
- [ ] Changelog updated
- [ ] Docker image tagged
- [ ] Deployment approved
Common mistake: if a paragraph immediately precedes a list with no blank line between them, some parsers will not render the list correctly. When in doubt, put a blank line before your list. The CommonMark list spec has the exact rules — they are surprisingly nuanced for something that looks simple.

Code — Inline and Fenced

Inline code uses a single backtick on each side. For blocks, use triple backticks (fenced code blocks) and optionally specify the language identifier right after the opening fence — this enables syntax highlighting in GitHub, VS Code previews, and most static site generators. You can also use indented code blocks (4 spaces of indentation), but prefer fenced blocks: they support language hints, they're explicit, and they work even when the surrounding content also has indentation.

markdown
<!-- Inline code -->
Use the `fetch()` API to make HTTP requests.
Set the `Content-Type` header to `application/json`.

<!-- Fenced code block with language hint -->
```python
import json

with open("config.json") as f:
    config = json.load(f)

print(config["database"]["host"])
```

```typescript
interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

async function fetchUser(id: string): Promise<ApiResponse<User>> {
  const res = await fetch(`/api/users/${id}`);
  return res.json();
}
```

```bash
# Install dependencies and start the dev server
npm install
npm run dev
```

```json
{
  "name": "my-project",
  "version": "1.0.0",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build"
  }
}
```

```yaml
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test
```

Common language identifiers: python, js or javascript, ts or typescript, bash or sh, json, yaml, html, css, sql, go, rust, java. Preview how your Markdown renders using the Markdown Preview tool.

Tables (GFM)

Tables are a GitHub Flavored Markdown extension — they are not part of the CommonMark standard. They work in GitHub, GitLab, most static site generators, and VS Code, but not in all Markdown processors. The syntax uses pipe characters to separate columns and a separator row of dashes to mark the header. Colons in the separator row control column alignment.

markdown
| Feature              | CommonMark | GFM       |
| -------------------- | :--------: | :-------: |
| Headings             | ✅         | ✅        |
| Bold / Italic        | ✅         | ✅        |
| Fenced code blocks   | ✅         | ✅        |
| Tables               | ❌         | ✅        |
| Task lists           | ❌         | ✅        |
| Strikethrough        | ❌         | ✅        |
| Autolinks            | ✅         | ✅ (ext.) |

Column alignment is set in the separator row. :--- aligns left (the default). ---: aligns right. :---: centres. You don't need to pad columns with spaces to make them visually aligned in the source — that's cosmetic and has no effect on the rendered output. The pipes at the start and end of each row are technically optional in GFM but including them is the clearer style.

Blockquotes

Blockquotes prefix each line with >. Nested blockquotes use >>. You can include other Markdown elements — headings, lists, code blocks — inside a blockquote, which makes them useful for callout boxes in documentation.

markdown
> **Note:** As of Node.js 18, the `fetch` API is available globally
> without importing anything. No more `node-fetch` dependency.

> This is a quote that spans
> multiple lines.
>
> And has a second paragraph.

> Outer quote.
>
> > Nested quote — useful for "quoting a quote" in changelogs
> > or spec discussions.

<!-- Blockquote containing a code block — useful for quoting error messages -->
> The migration failed with:
>
> ```
> ERROR: relation "users" already exists
> ```

Horizontal Rules, Line Breaks, and Escaping

These three features trip people up because their behavior looks like a bug until you know the rules. Horizontal rules, hard line breaks, and backslash escaping all have specific syntax that isn't obvious.

markdown
<!-- Horizontal rules: three or more of ---, ***, or ___ on their own line -->
---
***
___

<!-- All three render as <hr>. Most common style is --- -->

<!-- Hard line breaks: end a line with two trailing spaces, or use backslash -->
First line with two trailing spaces
Second line (rendered as a new line, not a new paragraph)

First line with backslash\
Second line (same result)

<!-- A single newline in Markdown source is NOT a line break — it's a space.
     Two newlines = a paragraph break. -->

<!-- Backslash escaping: put  before any Markdown character to render it literally -->
*This is not italic*
# This is not a heading
[Not a link](not-a-url)
`Not inline code`

<!-- Characters that can be escaped -->
\ ` * _ { } [ ] ( ) # + - . !
The trailing-spaces-for-line-break trap: many editors strip trailing whitespace on save, which silently removes your hard line breaks. The backslash (\) approach is more robust if your editor or CI pipeline strips trailing spaces. Alternatively, restructure your content so you need fewer hard line breaks — they're most often needed in poetry or addresses, not in documentation.

HTML in Markdown

Most Markdown processors pass raw HTML through unchanged, which unlocks a handful of useful patterns that pure Markdown syntax can't express. The most common use case in GitHub READMEs is the <details>/<summary> collapsible section. Other useful ones: <kbd> for keyboard shortcuts, and custom id attributes on headings for precise anchor links.

html
<!-- Collapsible section — very common in GitHub READMEs -->
<details>
<summary>Click to expand: Advanced configuration options</summary>

You can override the defaults by creating a `config.local.json` file
in the project root. Supported keys:

| Key        | Default | Description             |
| ---------- | ------- | ----------------------- |
| `port`     | 3000    | Dev server port         |
| `logLevel` | `info`  | One of debug/info/warn  |

</details>

<!-- Keyboard shortcuts -->
Press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> to open the command palette.

<!-- Custom heading ID for anchor links -->
<h2 id="configuration-reference">Configuration Reference</h2>

<!-- Link to that heading from anywhere -->
See the [Configuration Reference](#configuration-reference).

One important caveat: the <details> block requires a blank line between the </summary> closing tag and the body content if that body content contains Markdown. Without the blank line, the Markdown inside won't be parsed — it'll render as raw text. You can clean up and format your Markdown files with the Markdown Formatter tool.

Wrapping Up

That covers the full syntax — standard CommonMark and the GFM extensions developers use daily. For the authoritative word on edge cases, the CommonMark spec and the GFM spec are both readable documents, not just reference dumps. The CommonMark quick reference is a handy single-page summary. The Markdown Guide basic syntax and extended syntax pages are also well-organised if you want more prose explanation alongside examples. When you need to see exactly what your Markdown will look like before committing, the Markdown Preview tool renders it live in your browser. To clean up inconsistent formatting across a document, the Markdown Formatter normalises heading styles, list markers, and spacing. And for producing clean HTML from Markdown output, the HTML Formatter prettifies whatever the Markdown processor emits.