What is Markdown and why has it conquered the developer world?
Markdown is a lightweight markup language created by John Gruber and Aaron Swartz in 2004. The design goal was deceptively simple: a plain-text format that reads naturally as-is, and converts cleanly to HTML when needed. Two decades later, Markdown is the universal write-once-render-everywhere format for technical content — README files on every GitHub repo, posts on Reddit and Stack Overflow, documentation on Notion and Obsidian, blog posts on Substack, slides in Marp, papers in Pandoc, even chat messages in Slack and Discord.
Why did Markdown win where heavier alternatives (HTML, AsciiDoc, RST, BBCode) didn't?
- Readable in raw form. A markdown file is meaningful as plain text — you don't need to mentally render it.
- Tiny syntax surface. Headings (
#), bold (**), italic (*), links ([text](url)), lists (-), code blocks (```) — that's 90% of what you'll ever use. Five minutes to learn. - Plays well with version control. Plain-text diffs are clean. Code review on Markdown is sane in a way that Word docs or Notion exports aren't.
- Render targets are everywhere. Every static site generator (Hugo, Jekyll, Eleventy, Astro, Next.js MDX), every developer platform (GitHub, GitLab, Bitbucket, Codeberg), every documentation system (Docusaurus, MkDocs, GitBook, ReadTheDocs).
The trade-off: fragmentation. The original 2004 spec was incomplete and ambiguous. Different parsers produced different output for the same input. CommonMark (2014) standardized 80% of the syntax; GitHub Flavored Markdown extends it with practical features. This editor renders GFM, the dominant variant in 2026.
The Markdown family — CommonMark vs GFM vs MultiMarkdown
"Markdown" today is an umbrella term. Knowing which dialect your platform uses prevents formatting surprises.
| Variant | Year | What it adds | Used by |
|---|---|---|---|
| Original Markdown | 2004 | Headings, emphasis, lists, links, code blocks, blockquotes | Historical artifact — most parsers extend it |
| CommonMark | 2014 | Strict, unambiguous spec. Edge cases formally defined. | Reddit, Discourse, Discord, Stack Overflow (basis) |
| GitHub Flavored Markdown (GFM) | 2017 | Tables, task lists, strikethrough, autolinks, fenced code with language tags | GitHub, GitLab, Codeberg, Discord, Slack (subset), most blog platforms |
| MultiMarkdown | 2005 | Footnotes, citations, definition lists, math (MathJax), metadata | Academic writing, Pandoc |
| MDX | 2018 | Embed JSX/React components in markdown | Next.js, Docusaurus, Storybook docs |
| Obsidian / Notion / Roam Markdown | 2018+ | Wikilinks ([[Page]]), block references, embeds |
Personal knowledge management apps |
For 95% of writing in 2026: use GFM. It's understood by every platform, supports the practical features you need, and degrades gracefully when something doesn't render in CommonMark-only parsers.
Markdown syntax cheatsheet
Headings
# H1 — page title (use only once)
## H2 — main section
### H3 — sub-section
#### H4 — sub-sub-section
# Alternative for H1 / H2:
H1 with underline
=================
H2 with underline
-----------------
Emphasis
*italic* or _italic_
**bold** or __bold__
***bold italic***
~~strikethrough~~
`inline code`
==highlighted== (some parsers, e.g. Obsidian)
Lists
- Unordered list (also: * or +)
- Item 2
- Nested (indent 2 spaces)
- Another nested
1. Ordered list
2. Item 2
1. Nested ordered
- [ ] Unchecked task (GFM)
- [x] Checked task
Links and images
[link text](https://example.com)
[link with title](https://example.com "Hover title")
[reference style][1]
<https://autolink.com> (GFM auto-detects URLs without angle brackets)


[1]: https://example.com (defined anywhere in the document)
Code
Inline `code` uses single backticks.
```js
// fenced block with language hint for syntax highlighting
function add(a, b) {
return a + b;
}
```
Indented 4 spaces is also a code block (legacy)
Tables (GFM only)
| Column 1 | Column 2 | Column 3 |
|----------|:--------:|---------:|
| left | center | right |
| aligned | aligned | aligned |
Blockquotes
> This is a quote.
> Multiple lines stay quoted.
>
> > Nested quote.
> **Bold inside quote** still works.
Horizontal rules & line breaks
--- (or *** or ___)
End a line with two spaces
to get a soft line break.
Empty line above creates a new paragraph.
GFM-specific features you need to know
Task lists with checkboxes
GitHub renders - [ ] and - [x] as actual interactive checkboxes in issues and PRs. Used everywhere for to-do tracking.
Tables with alignment
The colon position in the separator row controls alignment: |---| = default, |:---| = left, |:---:| = center, |---:| = right.
Autolinks
Bare URLs (https://example.com) and email addresses become clickable automatically — no need for <...> brackets.
Strikethrough
~~struck through~~ renders with a line through it. Originally a Slack/GFM extension; now widely supported.
Fenced code blocks with language tags
Triple-backtick code blocks accept a language hint (```js, ```python, ```yaml) which most renderers use for syntax highlighting via Prism.js, highlight.js, or Shiki.
GitHub-specific extras (rendered only on github.com)
- Mermaid diagrams —
```mermaidblocks render flowcharts, sequence diagrams, ER diagrams. - Math expressions —
$E = mc^2$for inline;$$...$$for blocks (since 2022). - Alerts —
> [!NOTE],> [!WARNING],> [!IMPORTANT]render as styled callouts. - Issue and PR mentions —
#123linkifies to the issue/PR. - User mentions —
@usernamenotifies the user. - Emoji shortcodes —
:rocket:renders as 🚀.
Markdown processors in 8 languages
JavaScript (marked, markdown-it, remark)
// marked — the simplest, fastest
import { marked } from 'marked';
const html = marked.parse(mdString);
// markdown-it — most extensible (used by VS Code)
import MarkdownIt from 'markdown-it';
const md = new MarkdownIt({ html: true, linkify: true, typographer: true });
md.use(require('markdown-it-task-lists'));
const html = md.render(mdString);
// remark — AST-based, used by MDX, Astro, Docusaurus
import { remark } from 'remark';
import remarkHtml from 'remark-html';
const html = String(await remark().use(remarkHtml).process(mdString));
Python (markdown / markdown-it-py)
import markdown
html = markdown.markdown(md_string, extensions=['fenced_code', 'tables', 'extra'])
# markdown-it-py — port of JS markdown-it, more features
from markdown_it import MarkdownIt
md = MarkdownIt('gfm-like').enable('table').enable('strikethrough')
html = md.render(md_string)
Go (Goldmark)
import (
"bytes"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
)
md := goldmark.New(goldmark.WithExtensions(extension.GFM))
var buf bytes.Buffer
md.Convert([]byte(source), &buf)
fmt.Println(buf.String())
Rust (pulldown-cmark)
use pulldown_cmark::{Parser, Options, html};
let mut opts = Options::empty();
opts.insert(Options::ENABLE_TABLES);
opts.insert(Options::ENABLE_TASKLISTS);
opts.insert(Options::ENABLE_STRIKETHROUGH);
let parser = Parser::new_ext(md, opts);
let mut html_output = String::new();
html::push_html(&mut html_output, parser);
PHP (Parsedown)
// composer require erusev/parsedown
$parsedown = new Parsedown();
$parsedown->setSafeMode(true); // sanitize HTML
echo $parsedown->text($mdString);
Ruby (Redcarpet / kramdown)
require 'redcarpet'
renderer = Redcarpet::Render::HTML.new(filter_html: true, safe_links_only: true)
md = Redcarpet::Markdown.new(renderer, fenced_code_blocks: true, tables: true)
html = md.render(md_string)
# Or kramdown — more features, slightly slower
require 'kramdown'
html = Kramdown::Document.new(md_string, input: 'GFM').to_html
Java (CommonMark-Java + extensions)
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.commonmark.ext.gfm.tables.TablesExtension;
List<Extension> extensions = Arrays.asList(TablesExtension.create());
Parser parser = Parser.builder().extensions(extensions).build();
HtmlRenderer renderer = HtmlRenderer.builder().extensions(extensions).build();
String html = renderer.render(parser.parse(mdString));
Pandoc (the Swiss Army knife)
# Convert markdown to HTML
pandoc input.md -o output.html
# Markdown to PDF (via LaTeX)
pandoc input.md -o output.pdf --pdf-engine=xelatex
# Markdown to Word
pandoc input.md -o output.docx
# Specific markdown variant
pandoc input.md --from=gfm --to=html --standalone -o output.html
Real-world Markdown use cases
README files (~80% of all markdown)
Every GitHub repo expects README.md at the root. It's the project's landing page — for both humans and the GitHub algorithm. Standard structure: project name + tagline, badges, install, quick start, usage, license. Tip: add an <img> tag with an alt attribute at the top to render a hero image without breaking text-mode cat README.md.
Documentation sites (Docusaurus, MkDocs, Astro)
Modern docs systems take markdown source, run it through plugins (link rewriting, ToC generation, syntax highlighting, mermaid diagrams), and produce static HTML. The result: docs are version-controlled with the code, contributors edit them like any other file, and review happens via PR.
Static blog posts
Hugo, Jekyll, Eleventy, Astro, Next.js MDX — all read markdown files with frontmatter (YAML metadata block at the top) and render to HTML. The author writes in markdown; the build pipeline produces SEO-optimized HTML with structured data.
Pull request descriptions and issue templates
GitHub renders the body of every issue, PR, and comment as GFM. Use checklists for PR todos, code blocks for stack traces, links to other issues with #123, mentions with @username.
Slack & Discord messages
Both apps support a subset of markdown. **bold**, *italic*, ~~strike~~, code blocks, and links work in both. Discord additionally supports headings, block quotes, and lists; Slack stops at inline formatting.
Note-taking apps (Obsidian, Joplin, Logseq)
Plain-text markdown files in a folder = your knowledge base. Vendor lock-in is gone — your notes work in any markdown editor.
Common Markdown mistakes
- Forgetting blank lines around blocks. Markdown often merges blocks if there's no blank line between a paragraph and a list/heading/code block. Insert a blank line before and after every block-level element.
- Mixing tabs and spaces in nested lists. Some parsers handle either, but the offside rule for nested lists is space-sensitive. Pick one style site-wide.
- Hard-wrapping prose at 80 chars manually. GFM treats single newlines as soft breaks (rendered as spaces); double newlines as paragraphs. Many editors render hard wraps as ugly mid-sentence breaks. Let prose flow.
- Using
**bold**and__bold__inconsistently. They're equivalent in GFM, but Reddit's old parser only supported**. Pick one for portability. - Forgetting language tags on code blocks. A bare
```block won't get syntax highlighting. Always add the language:```js,```python,```yaml. - HTML inside markdown. Most renderers allow it (
<sup>,<br>,<img>), but linters and platforms (npm, PyPI) often strip it. Use markdown syntax where possible. - Relative paths in a README that gets reposted. If your README is shown on PyPI, npm, GitHub, and your blog, relative links break in 3 of 4 places. Use absolute URLs.
- Inline images without dimensions. Markdown's
doesn't support dimensions. For width/height, fall back to<img src="..." width="400">HTML. - Long tables. GFM tables are great for short reference tables, terrible for long data — they don't scroll. Convert to CSV with our JSON to CSV tool and link to it.
Best Markdown editor for 2026 — what to compare
Search results for "markdown editor online", "markdown preview", and "md to html" return many tools but most fail on real-world use: they don't support GFM tables (the most-used GFM feature), they break on fenced code blocks with curly braces, they don't sanitize HTML in the rendered output (XSS risk), or they upload your draft content to a server. Here's how the most-used Markdown editors compare in 2026:
| Tool | GFM (tables, tasks, strikethrough) | Live split preview | Browser-only | HTML export | Cost |
|---|---|---|---|---|---|
| FreeDevTool Markdown Preview | Yes (CommonMark + GFM) | Yes | Yes | Yes | Free |
| dillinger.io | Yes | Yes | Mostly browser, cloud-save server-side | Yes | Free, ad-funded |
| stackedit.io | Yes | Yes | Browser + cloud sync | Yes | Free + paid |
| markdownlivepreview.com | Limited | Yes | Yes | Yes | Free |
| VS Code "Open Preview" (Ctrl+K V) | Yes | Yes | Local IDE | Via export extensions | Free |
| Obsidian / Typora (apps) | Yes | WYSIWYG | Local | Yes | Free / Paid |
What's the difference between CommonMark, GFM, and MultiMarkdown?
| Feature | CommonMark | GitHub Flavored Markdown (GFM) | MultiMarkdown |
|---|---|---|---|
| Standardized | Yes (2014, current 0.31) | Yes (superset of CommonMark) | de-facto only |
| Tables | No | Yes (pipe syntax) | Yes |
| Task lists | No | Yes (- [ ] / - [x]) | Yes |
| Strikethrough | No | Yes (~~text~~) | Yes |
| Autolinks | Limited | Yes (URLs auto-detected) | Yes |
| Footnotes | No | No (rendered as text) | Yes |
| Math (LaTeX) | No | No (GitHub adds via MathJax) | Yes |
| Used by | Spec baseline | GitHub, GitLab, Discourse | Pandoc, academic writing |
Decision rule: writing for GitHub/GitLab/blog → use GFM. Writing for a tool that says "CommonMark" → stick to CommonMark. Writing academic papers with footnotes/math → MultiMarkdown via Pandoc. This editor renders GFM (and thus CommonMark) — the most widely-supported variant in 2026.
How do I preview Markdown locally without uploading my draft?
Three options. 1) This page: paste Markdown in the left pane; the right pane renders live via a CommonMark+GFM JavaScript parser running in your browser. Source never leaves the page. 2) VS Code: Ctrl+K V opens a side preview of the active .md file — works offline. 3) CLI: pandoc input.md -o output.html or npx markdown-to-html input.md. For drafts containing internal product names, customer references, or unannounced features, browser-only / local-only is the only safe choice. Avoid online editors with cloud-sync (StackEdit, Dillinger save-to-cloud) for sensitive drafts.
Markdown editor alternative to dillinger.io — 4 reasons writers switched
- No cloud-save risk. Dillinger and StackEdit offer Dropbox/Google Drive sync — convenient, but uploads your draft. This page is browser-only with no save service.
- Sanitized HTML output. Default rendering strips inline
<script>,<iframe>, and dangerous attributes — safe to paste rendered output into a CMS without re-sanitization. - GFM-correct rendering. Tables, task lists, fenced code blocks, autolinks, strikethrough all match GitHub's rendering exactly. Useful when previewing READMEs before commit.
- Both .md and .html download. One-click export for either source or rendered output, ready to drop into Hugo/Jekyll/Astro/Eleventy content directories.
Pair the Markdown editor with the Word to Markdown Converter for migrating Word documents, the HTML Entity Encoder for special characters in MD, the Character Counter for hitting blog-platform limits, and the Code & Text Tools hub for the broader writing toolkit.
Markdown best practices
- Stick to GFM. It's understood by every platform you'll publish on.
- Use the most semantic syntax available.
### Headingnot**heading**;1. Itemnot1) Item; lists for lists, blockquotes for quotes. - Lint your markdown.
markdownlint-clicatches missing blank lines, wrong list indentation, and other portability issues. Add it to CI. - Preview before pushing. Use this tool, your IDE's preview, or
grip(locally renders GFM as GitHub would) to catch broken layouts. - Keep README focused. Top of the file is the most-read part. Hero (badge, name, tagline) → install → quick start → link to full docs. The wiki is for everything else.
- Use frontmatter for metadata. Static-site generators read YAML at the top of MD files for title, slug, date, tags. Keeps prose clean.
- Don't paste from Word/Google Docs. Hidden formatting characters break rendering. Use our Word to Markdown converter first.
- Add alt text to images. Accessibility, SEO, and graceful degradation when images fail to load.