Markdown and Code Blocks
How Astro processes markdown, renders code with syntax highlighting, and supports MDX.
On this page
Markdown Processing Pipeline
Prereq: content collections — markdown rendering rides on collection schemas. After this, build and deploy is the final step. For the big-picture, see the mental model.
When Astro encounters a .md file in a content collection, it runs this pipeline:
Astro extracts and validates frontmatter, parses the body with remark, transforms it to HTML with rehype, highlights code with Shiki, and hands the finished HTML to the Content component — all at build time.
graph TD
accTitle: How a markdown file becomes HTML
accDescr: Astro extracts and validates frontmatter, parses the body with remark, transforms it to HTML with rehype, highlights code with Shiki, and hands the finished HTML to the Content component — all at build time.
md["your-article.md"] --> fm["Frontmatter extracted + validated against schema"]
fm --> remark["Markdown body parsed (remark)"]
remark --> rehype["Transformed to HTML (rehype)"]
rehype --> shiki["Code blocks syntax-highlighted (Shiki)"]
shiki --> out["Finished HTML for the Content component"]
your-article.md
→ frontmatter extracted + validated against schema
→ markdown body parsed (remark)
→ transformed to HTML (rehype)
→ code blocks syntax-highlighted (Shiki)
→ final HTML ready for <Content /> component
All of this happens at build time. The browser receives finished HTML — no JavaScript markdown parser runs in the browser.
This is identical to LaTeX compiling a .tex file to a .pdf. The source is human-readable markup, the output is rendered output. The reader never sees the source.
Real Example: Blog Post Pipeline
Here’s the actual welcome post from krowdev — toggle to see how markdown becomes HTML:
content/kb/welcome-to-krowdev.md
---title: "Welcome to krowdev"description: "A practitioner's knowledge base for agentic coding, DNS, and TLS fingerprinting."published: 2026-03-15kind: articletags: [meta]maturity: buddingorigin: ai-drafted---
This is krowdev — a developer knowledge base and blog.
## What You'll Find Here
- **How-to guides** for common dev tasks- **Concepts** explained from first principles- **Agentic coding** patterns — the unique angle
## The Stack
Built with Astro 6, themed with Catppuccin Mocha.<!-- Frontmatter stripped out (used as data, not rendered) --><!-- Markdown body compiled to HTML: -->
<p>This is krowdev — a developer knowledge base and blog.</p>
<h2 id="what-youll-find-here">What You'll Find Here</h2>
<ul> <li><strong>How-to guides</strong> for common dev tasks</li> <li><strong>Concepts</strong> explained from first principles</li> <li><strong>Agentic coding</strong> patterns — the unique angle</li></ul>
<h2 id="the-stack">The Stack</h2>
<p>Built with Astro 6, themed with Catppuccin Mocha.</p>
<!-- This HTML is then placed inside KBEntry.astro's <slot /> --><!-- Which is inside Base.astro's <slot /> -->Notice what happened:
- Frontmatter was extracted as structured data (
entry.data.title,entry.data.published, etc.) — not rendered ## Headingbecame<h2 id="what-youll-find-here">— with auto-generated anchor IDs for the ToC**bold**became<strong>bold</strong>- listbecame<ul><li>...</li></ul>- The KBEntry layout wraps this in a header (date, tags) + ToC sidebar
- The Base layout wraps that in the full page shell
The frontmatter published: 2026-03-15 is used by KBEntry.astro to display “March 15, 2026” in the header — computed at build time.
Code Blocks — Shiki
Astro uses Shiki for syntax highlighting. Shiki uses the same grammar files as VS Code, so highlighting looks identical to your editor.
In markdown, use fenced code blocks with a language tag:
```pythondef greet(name: str) -> str: return f"Hello, {name}!"```Astro’s built-in Markdown highlighting (Shiki) takes a light/dark theme pair directly in config:
// astro.config.mjs — Astro's built-in Shiki highlightingmarkdown: { shikiConfig: { themes: { light: 'catppuccin-latte', dark: 'catppuccin-mocha', }, },},Shiki embeds both themes’ colors as CSS custom properties, and the CSS in global.css switches between them based on data-theme. (krowdev itself layers the astro-expressive-code integration on top — it wraps Shiki to add features like collapsible sections, and is configured under integrations rather than markdown.shikiConfig — but the dual-theme idea is identical.)
html[data-theme='light'] pre.astro-code span { color: var(--shiki-light) !important;}html[data-theme='dark'] pre.astro-code span { color: var(--shiki-dark) !important;}Supported Languages
Shiki supports 200+ languages out of the box. Some examples:
// JavaScriptconst result = await fetch('/api/data').then(r => r.json());# Shellnpm run build && npx pagefind --site dist-- SQLSELECT title, date FROM posts WHERE difficulty = 'beginner' ORDER BY date DESC;# YAML frontmattertitle: "My Article"difficulty: beginnertags: [astro, webdev]MDX — Markdown + Components
Files ending in .mdx can import and use Astro components inside markdown:
---title: Interactive Demo---
import Chart from '../../components/Chart.astro';
Here's a regular paragraph.
<Chart data={[1, 2, 3, 4, 5]} />
And more text after the component.MDX is markdown that can embed components. Use it when you need interactive elements or custom layouts inside article content. Use plain .md when you don’t — it’s simpler and faster to process.
For krowdev, the @astrojs/mdx integration is installed but most articles use plain .md since they don’t need embedded components.
HTML in Markdown
Standard markdown allows raw HTML. This is how the interactive elements in this course work:
<div class="callout callout-key"><span class="callout-label">Key Insight</span>
Content here with **markdown** formatting.</div>The <div> and <span> pass through as-is. The markdown inside them still gets processed. The styling comes from global.css.
Challenge: Create a syntax-highlighted article
Create a new kb entry at content/kb/git-basics.md:
---title: "Git Basics Cheatsheet"description: "Essential git commands for daily use."kind: snippetcreated: 2026-03-20tags: [git]maturity: seedlingorigin: humanconfidence: high---Add 3-4 code blocks using different languages (bash, diff, text). For example:
```bashgit statusgit add -pgit commit -m "message"```
```diff- old line that was removed+ new line that was added```Run npm run dev and check that:
- Syntax highlighting matches the Catppuccin theme
- Toggling dark/light mode switches the code colors too
- The article appears on the site under the reference section
Sources
- Astro Docs, Markdown content
- Astro Docs, MDX integration
- Shiki, Syntax highlighter