Skimmark / Blog

Markdown syntax guide: every common element, with source and result

Bobby Huang ·

Markdown is a way to format plain text with a few symbols. A # starts a heading, * or _ marks emphasis, - starts a list item, and [text](url) makes a link. Backticks mark code, > starts a quote, and pipes build a table. A renderer turns these symbols into a formatted page. The core rules come from the CommonMark spec. GFM, a widely used superset, adds tables, task lists, strikethrough and bare-URL links.

Key takeaways

  • Markdown is plain text with a few symbols. The file reads fine raw and looks formatted once a renderer shows it.
  • CommonMark defines the core syntax. GFM adds tables, task lists, strikethrough and bare-URL links on top.
  • Blank lines matter. They separate paragraphs, lists and blocks, and a missing one can change how a page renders.
  • Tables, task lists and strikethrough only render in tools that support GFM. Elsewhere you see the raw symbols.
  • When something renders wrong, look at the raw text first. The fix is often a space, a blank line or an escape.

Markdown is a way to write formatted text with plain characters. You type a few symbols, and a renderer turns them into headings, lists, links and tables. The file stays readable even when nothing renders it.

This guide covers the elements you will meet most often. Each one shows the source you type. Most also show the result, or say what it looks like. Where an element only works in some tools, the guide says so.

How Markdown works in one minute

A Markdown file is a plain text file, usually saved with a .md extension. If that part is new, start with what a .md file is.

Two specs define most of the syntax:

  • CommonMark is a precise spec for the core: headings, paragraphs, emphasis, lists, links, images, code, quotes and rules.
  • GFM is a superset of CommonMark. It adds tables, task lists, strikethrough, links from bare URLs, and a filter for a few unsafe HTML tags.

Most modern tools follow CommonMark for the core. Many add GFM. Some add more on top, such as footnotes, math or diagrams. Those extras vary from tool to tool, so this guide leaves them out.

Headings

Start a line with one to six # signs, then a space. One # is the top level. Six is the smallest.

# Project plan
## Goals
### Open questions

The space after the # matters. #Goals with no space is plain text in CommonMark.

There is a second style for the top two levels: underline the text with === or ---. You will see it in older files. The # style is easier to scan, so most people use it.

Paragraphs and line breaks

A blank line starts a new paragraph. A single line break inside a paragraph does not show up. The renderer joins the lines with a space.

This is one line.
This line joins the one above.

This is a new paragraph.

Result:

This is one line. This line joins the one above.

This is a new paragraph.

To force a line break without a new paragraph, end the line with a backslash \ or with two spaces. The backslash is easier to see, since trailing spaces are invisible.

Emphasis: bold, italic and strikethrough

*italic* or _italic_
**bold** or __bold__
~~struck through~~

Result:

italic or italic

bold or bold

struck through

Strikethrough is a GFM feature. In a tool without GFM, the tildes show as text.

Lists

Start each item with -, * or + for a bullet list. Use a number and a period for a numbered list.

- Read the plan
- Check the steps
  - Look at file paths
  - Look at commands

1. Open the file
2. Read the header
3. Read the steps

Result:

  • Read the plan
  • Check the steps
    • Look at file paths
    • Look at commands
  1. Open the file
  2. Read the header
  3. Read the steps

A few rules save a lot of confusion:

  • Nesting. Indent a child item so its marker lines up with the text of the parent. Under - that is two spaces. Under 1. it is three.
  • Numbers. The first number sets the start. The renderer counts up from there, so 1. on every line still renders as 1, 2, 3.
  • Mixed markers. Switching from - to * starts a new list. Pick one marker and keep it.
  • Blank lines. Put a blank line before a list. A numbered list that starts at any number other than 1 cannot break into a paragraph, so without the blank line it stays part of the text above.

Task lists

A task list is a list where items start with a box. [ ] is open. [x] is done.

- [x] Write the plan
- [ ] Review the plan
- [ ] Run the tests

Result:

  • Write the plan
  • Review the plan
  • Run the tests

Task lists are a GFM feature. AI agents use them a lot in plans and to-do files. The rules, common mistakes and a way to count open items from the terminal are in Markdown task lists explained.

Links

[Example](https://www.example.com/)
[Plan notes](notes/plan.md "Optional title")
<https://www.example.com>

The first and last lines render like this:

Example

https://www.example.com

The middle line becomes a link named "Plan notes" that opens notes/plan.md. The text in quotes shows as a tooltip.

The text goes in square brackets, the address in round brackets. Most viewers read a relative path such as notes/plan.md from the file's own folder. A leading / starts from a root, but whether that is the site or the disk depends on the viewer. Angle brackets turn a full web address, one that starts with a scheme such as https://, into a link in any CommonMark tool. GFM also links a bare https:// or www. address with no brackets at all.

For long documents, reference links keep the text clean:

See the [setup notes][setup].

[setup]: docs/setup.md

The definition can come before or after the link. Keep it outside code blocks, and put a blank line before it if it follows a paragraph. A valid definition does not show on the page.

Images

An image is a link with a ! in front. The text in square brackets is the alt text.

![Diagram of the build steps](images/build.png)

Three things trip people up:

  • Relative paths. Most viewers read them from the folder the Markdown file is in, so images/build.png is a folder named images next to the file. The Markdown spec leaves that to the viewer.
  • Alt text is what a screen reader says and what shows if the image fails. Describe what the image shows.
  • Remote images load from another server. Some viewers block them for privacy, since loading one sends a request to that server. If an image from a URL does not appear, that may be why.

Code

Wrap a short piece of code in single backticks for inline code: `npm test` renders as npm test.

For a block, put three backticks on the line before and the line after. Add a language name after the opening backticks to get syntax highlighting in tools that support it.

```bash
pnpm install
pnpm test
```

Result:

pnpm install
pnpm test

Three tildes ~~~ work the same way as three backticks. An older style indents every line by four spaces. It still works, but it cannot name a language.

Block quotes

Start a line with >. Add a second > to nest.

> The agent stopped here.
>
> > Waiting on Jane Doe for the API key.

Result:

The agent stopped here.

Waiting on Jane Doe for the API key.

Agents often use quotes for notes, warnings and quoted output.

Tables

| Step | Owner    | Status |
|:-----|:--------:|-------:|
| Plan | Agent    | Done   |
| Review | Jane Doe | Open |

Result:

Step Owner Status
Plan Agent Done
Review Jane Doe Open

How it works:

  • The first row is the header. The second row is dashes, one cell per column.
  • A colon on the left of the dashes aligns left. Colons on both sides center. A colon on the right aligns right.
  • The pipes do not need to line up. The table above renders the same either way.
  • To put a pipe inside a cell, escape it as \|.

Limits worth knowing: a cell holds one line of text. GFM tables have no way to merge cells, and a cell holds only inline text, so a Markdown list cannot go inside one. For anything bigger, use a list or split the table.

Tables are a GFM feature. Without GFM, you see the pipes as text.

Horizontal rules

Three or more dashes, asterisks or underscores on a line of their own draw a line across the page.

Above the line.

---

Below the line.

Leave a blank line above ---. Without it, dashes right under a line of plain text turn that text into a heading.

Escaping special characters

Put a backslash in front of a symbol to show it as text instead of formatting.

\*not italic\*
1\. not a list item
\# not a heading

Result:

*not italic*

1. not a list item

# not a heading

Raw HTML

CommonMark lets you mix HTML tags into Markdown. GFM keeps that but filters a short list of risky tags, such as <script> and <iframe>.

In practice, support varies a lot. Some tools render the HTML. Some strip it. Some show it as plain text. If a file depends on HTML to look right, check it in the tool your readers use.

Front matter

Many Markdown files start with a block of YAML between two --- lines. This is front matter. It holds fields such as a title, a date or a status.

---
status: in-progress
owner: Jane Doe
---

Front matter is not part of CommonMark or GFM. Tools that know about it hide it or show it as data. Tools that do not may show the first --- as a line and the fields as a large heading, because the closing --- underlines them. AI agents often put a front matter block at the top of handoff files.

Quick reference

You want Type this
Heading ## Heading
Bold **bold**
Italic *italic*
Strikethrough (GFM) ~~text~~
Bullet list - item
Numbered list 1. item
Task (GFM) - [ ] task
Link [text](url)
Image ![alt](path.png)
Inline code `code`
Code block three backticks before and after
Quote > text
Table (GFM) pipes and a dash row
Line --- with a blank line above
Literal symbol \*

When it renders wrong

These three things cause many rendering problems:

  1. A missing blank line. A blank line before any block is the safe habit. Without one, a numbered list that starts at 2 or higher, or an indented code block, joins the paragraph above.
  2. A missing space. #Heading and -item stay plain text. So does a task box written [] with no space inside.
  3. A symbol read as formatting. An asterisk, or an underscore at the edge of a word, can start italics. A pattern like *.md can trip this. Wrap paths and patterns in backticks or escape the symbol.

Look at the raw text when a page looks off. The cause is usually visible there in a few seconds.

Where Skimmark fits

Skimmark is a Markdown reader and editor for people whose AI agents write Markdown. It is in development and has not been released. The app itself has no AI features.

Planned for v1: a live render of headings, lists, check-box lists, tables, code blocks, links, local images and block quotes. Remote images are not fetched, and raw HTML is shown inert. A Frontmatter Table shows the YAML header as key and value rows instead of raw text.

You can see what Skimmark is and follow along at skimmark.com.

Questions

What is the difference between CommonMark and GFM?
CommonMark is a precise spec for core Markdown, such as headings, lists, links, code and quotes. GFM is a superset of CommonMark. It adds tables, task lists, strikethrough, links from bare URLs, and a filter that blocks a few unsafe HTML tags.
How do you make a table in Markdown?
Write a header row with cells split by pipes, then a row of dashes under it, then one row per line of data. Colons in the dash row set the alignment. Tables are a GFM feature, so they need a renderer that supports GFM.
How do check boxes work in Markdown?
Start a list item with "- [ ]" for an open box or "- [x]" for a ticked one. A GFM renderer shows real check boxes. Other tools show the brackets as text.
How do I add an image by relative path?
Write ![alt text](images/diagram.png). Most viewers read the path from the folder the Markdown file sits in. The Markdown spec leaves that to the viewer. Keep the image next to the file or in a subfolder, and use forward slashes.
Why does my Markdown look different in two apps?
Each app uses its own renderer and its own set of extensions. Core syntax renders the same almost everywhere. Tables, task lists, footnotes, math and diagrams depend on the app.

View as Markdown