This is my first blog post, and I figured the best way to start is by documenting what I'm learning right now: Markdown. It's the lingua franca of the web for writers, developers, and anyone who needs to format text without fighting with a WYSIWYG editor.
I've known bits and pieces of Markdown for a while, but never sat down to learn it systematically. This post is my attempt to organize everything in one place.
Why Markdown
Markdown was created by John Gruber in 2004 with a simple goal: make writing for the web as readable as possible. The syntax is designed to mirror the way people naturally format plain text emails. A Markdown document should be readable even before it's rendered.
The killer feature is portability. Your Markdown file works everywhere: GitHub, Notion, VS Code, static site generators, note-taking apps. Learn it once, use it forever.
Basic Syntax
Headings
Headings use hash symbols. One # for H1, two for H2, and so on up to H6.
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
I rarely go beyond H3 in practice. Too many heading levels make a document feel fragmented.
Paragraphs and Line Breaks
Paragraphs are separated by blank lines. Just hit Enter twice.
For a single line break without starting a new paragraph, end a line with two spaces before hitting Enter. This is a bit magical and easy to forget. Most of the time, just use blank lines between paragraphs.
Emphasis
Three ways to emphasize text:
*italic* or _italic_
**bold** or __bold__
***bold and italic*** or ___bold and italic___
I prefer asterisks over underscores. Visually cleaner in raw text. There's also ~~strikethrough~~ for deleted text, though not every Markdown parser supports it.
Lists
Unordered lists use dashes, asterisks, or plus signs:
- First item
- Second item
- Nested item
- Another nested item
- Third item
Ordered lists use numbers:
1. First step
2. Second step
3. Third step
The actual numbers don't matter for rendering. You could write all 1. and Markdown will auto-number them. But I like using real numbers for readability in the raw file.
Nested lists indent by two spaces. Some parsers require four, but two is the standard.
Links
Two link styles exist. Inline links are explicit:
[My GitHub](https://github.com/kindredzhang)
Reference links keep URLs at the bottom, cleaner for long documents:
[My GitHub][gh]
[gh]: https://github.com/kindredzhang
I use reference links when a URL appears multiple times or when the paragraph is dense with links. Otherwise, inline is fine.
Links can include a title that shows on hover:
[My GitHub](https://github.com/kindredzhang "kindredzhang's GitHub")
Images
Images are links with an exclamation mark prefix:

Alt text is important for accessibility and SEO. Never leave it empty. You can also use reference-style images:
![My avatar][avatar]
[avatar]: /avatar.jpg "kindredzhang"
Blockquotes
For quoting text, use the > character:
> This is a blockquote.
> It can span multiple lines.
>
> > And it can be nested.
I use blockquotes for actual quotes, not for callout boxes. Some people abuse them for warnings or tips, but that's what admonitions are for in extended Markdown flavors.
Code
Inline code uses single backticks:
Use the `npm install` command.
Code blocks use triple backticks. You can specify the language for syntax highlighting:
```javascript
function hello() {
console.log("Hello, world!");
}
```
For code blocks inside code blocks (like showing Markdown examples), use four backticks to wrap three, or indent by four spaces for the inner block.
Indented code blocks work too—four spaces or one tab—but fenced code blocks with backticks are cleaner and support language labels.
Horizontal Rules
Three ways to create a horizontal line:
---
***
___
I stick with triple dashes. It's the most readable.
Intermediate Syntax
Tables
Tables use pipes and dashes:
| Syntax | Description |
| --------- | ----------- |
| Header | Title |
| Paragraph | Text |
Alignment is controlled by colons:
| Left | Center | Right |
| :--- | :----: | ----: |
| text | text | text |
Tables are great for structured data. I use them for comparing options or listing configurations. Not all Markdown parsers handle complex tables well, so keep them simple.
Task Lists
Checkboxes in lists, popularized by GitHub:
- [x] Completed task
- [ ] Pending task
- [ ] Another pending task
I use these for todo lists in project READMEs and issue descriptions. They're surprisingly useful for project planning.
Escaping Characters
Backslash escapes special characters:
\*not italic\*
\# not a heading
\`not code\`
Characters you can escape: \, `, *, _, {, }, [, ], (, ), #, +, -, ., !, |
Extended Features (Not Standard, But Common)
These aren't in the original Markdown spec, but most modern parsers support them.
Fenced Code Block with Info String
Already covered above, but worth noting this is technically a CommonMark/GFM extension, not original Markdown.
Footnotes
Some parsers (like Pandoc and some static generators) support footnotes:
Here's a sentence with a footnote.[^1]
[^1]: This is the footnote content.
Definition Lists
Term
: Definition
Another Term
: Another definition
I rarely use these. Tables usually work better.
Strikethrough
~~deleted text~~
Standard in GFM, supported almost everywhere now.
Autolinks
Raw URLs automatically become links in most parsers:
Visit https://github.com/kindredzhang for my projects.
Emoji
GFM supports shortcodes:
:warning: :rocket: :heart:
I use these sparingly. They can feel cheap if overused.
My Workflow
Here's how I actually write Markdown day to day:
- VS Code with a Markdown preview extension. WYSIWYG split view, instant feedback.
- Local images go in an
assets/folder next to the post. - Headers structure the outline before I write body text.
- Links use reference style if there are more than two in a paragraph.
- Code blocks always specify the language for highlighting.
For this blog, I write posts in Markdown files, commit them, and the site generator does the rest. No CMS, no database, just text files.
Common Pitfalls
Nested lists and code blocks: Indentation matters. Two spaces for list nesting, four for code blocks inside lists. This trips up everyone at some point.
Blank lines around block elements: Always put blank lines before and after headings, lists, code blocks, and blockquotes. Some parsers are forgiving, others aren't.
Raw HTML: You can mix HTML into Markdown when the syntax doesn't cut it. But it breaks the portability promise. Use it as a last resort.
Different flavors: GitHub Flavored Markdown (GFM), CommonMark, Pandoc Markdown—they're similar but not identical. Know which one your platform uses.
Final Thoughts
Markdown is simple by design. You can learn 80% of it in an afternoon, and that 80% covers 95% of real-world usage. The remaining 20% is for edge cases and specific platforms.
What I appreciate most is that Markdown gets out of the way. You're not thinking about formatting; you're thinking about content. The formatting is just enough structure to make the text readable, nothing more.
This post itself is written in Markdown. Meta, but appropriate.
If you notice any errors or have favorite tricks I missed, reach out. I'm still learning.