Skip to main content
Astro has built-in support for Markdown and MDX files, making it easy to write content-focused pages. You can use standard Markdown syntax, add frontmatter for metadata, and even use components within your content.

Markdown Pages

Create Markdown pages by adding .md files to your src/pages/ directory. Each file becomes a route based on its file path.
src/pages/blog/post.md
---
title: My Blog Post
author: Jane Doe
date: 2026-03-03
---

# Welcome to My Post

This is a **Markdown** page in Astro. It supports all standard Markdown syntax.

## Features

- Easy to write
- Familiar syntax
- Fast rendering

```js
console.log('Code blocks work too!');

<Note>
Markdown files in `src/pages/` are automatically converted to HTML pages with Astro's default layout.
</Note>

## Frontmatter

Frontmatter is YAML metadata at the top of your Markdown file, enclosed by `---` delimiters. It's available as the `frontmatter` property in your layouts.

```markdown src/pages/post.md
---
title: Understanding Frontmatter
description: A guide to using frontmatter in Astro
author: John Smith
publishedDate: 2026-03-03
tags: [astro, markdown, frontmatter]
layout: ../../layouts/BlogPost.astro
---

# Content goes here

Accessing Frontmatter

In your layout, access frontmatter data through the frontmatter prop:
src/layouts/BlogPost.astro
---
const { frontmatter } = Astro.props;
---

<html>
  <head>
    <title>{frontmatter.title}</title>
    <meta name="description" content={frontmatter.description} />
  </head>
  <body>
    <article>
      <h1>{frontmatter.title}</h1>
      <p>By {frontmatter.author} on {frontmatter.publishedDate}</p>
      <slot /> <!-- Markdown content rendered here -->
    </article>
  </body>
</html>

MDX Support

MDX extends Markdown by allowing you to import and use components directly in your content. First, add the MDX integration:
npx astro add mdx

Using Components in MDX

Once installed, you can use components in .mdx files:
src/pages/interactive.mdx
---
title: Interactive Content
---
import Button from '../components/Button.astro';
import Counter from '../components/Counter.jsx';

# Interactive MDX Page

Here's a regular paragraph of text.

<Button>Click me!</Button>

And here's a React counter component:

<Counter client:load />

## More Content

You can mix Markdown and components seamlessly.
MDX is perfect for documentation, blogs, and any content that benefits from interactive components.

Markdown Features

Syntax Highlighting

Code blocks support syntax highlighting out of the box:
```js
function greet(name) {
  return `Hello, ${name}!`;
}
```
You can customize the theme in your astro.config.mjs:
astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  markdown: {
    shikiConfig: {
      theme: 'dracula',
      wrap: true
    }
  }
});

GitHub-Flavored Markdown

Astro supports GitHub-Flavored Markdown (GFM) including:
  • Tables
  • Task lists
  • Strikethrough
  • Autolinks
| Feature | Supported |
|---------|----------|
| Tables  | ✓        |
| GFM     | ✓        |

- [x] Task lists work
- [ ] Unchecked items too

~~Strikethrough text~~

https://example.com (autolinked)

Custom Components

Replace HTML elements with custom components using the components prop in MDX:
src/pages/styled.mdx
---
title: Custom Styled Content
---
import CustomHeading from '../components/CustomHeading.astro';
import Note from '../components/Note.astro';

export const components = {
  h1: CustomHeading,
  blockquote: Note
};

# This renders as CustomHeading

> This renders as the Note component

Layouts for Markdown

Specify a layout in frontmatter to wrap your Markdown content:
src/pages/article.md
---
layout: ../layouts/Article.astro
title: My Article
---

Content here...
The layout receives all frontmatter properties plus the rendered content:
src/layouts/Article.astro
---
const { frontmatter } = Astro.props;
---

<html>
  <head>
    <title>{frontmatter.title}</title>
  </head>
  <body>
    <main>
      <slot />
    </main>
  </body>
</html>

Programmatic Access

Import Markdown files in Astro components to access their content and frontmatter:
src/pages/index.astro
---
import * as post from './blog/my-post.md';

const { Content, frontmatter } = post;
---

<html>
  <body>
    <h1>{frontmatter.title}</h1>
    <Content />
  </body>
</html>

Dynamic Imports

Load Markdown files dynamically:
src/pages/blog/[slug].astro
---
export async function getStaticPaths() {
  const posts = await Astro.glob('../*.md');
  
  return posts.map(post => ({
    params: { slug: post.frontmatter.slug },
    props: { post }
  }));
}

const { post } = Astro.props;
const { Content, frontmatter } = post;
---

<html>
  <body>
    <article>
      <h1>{frontmatter.title}</h1>
      <Content />
    </article>
  </body>
</html>

Configuration Options

Customize Markdown processing in astro.config.mjs:
astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  markdown: {
    // Syntax highlighting theme
    shikiConfig: {
      theme: 'github-dark',
      wrap: true
    },
    // Add remark/rehype plugins
    remarkPlugins: [],
    rehypePlugins: [],
    // Draft pages (frontmatter.draft = true)
    drafts: false,
    // Smartypants - smart quotes and dashes
    smartypants: true,
    // GitHub-Flavored Markdown
    gfm: true
  }
});
Remark plugins process Markdown AST before HTML conversion:
import remarkToc from 'remark-toc';

export default defineConfig({
  markdown: {
    remarkPlugins: [remarkToc]
  }
});
Rehype plugins process HTML after Markdown conversion:
import rehypeMinify from 'rehype-minify';

export default defineConfig({
  markdown: {
    rehypePlugins: [rehypeMinify]
  }
});

Best Practices

Content Collections

Use Content Collections for type-safe content management

Layouts

Create reusable layouts for consistent styling
For complex content sites, use Content Collections instead of accessing Markdown files directly. They provide type safety, validation, and better performance.

MDX-Specific Features

Export Variables

Export variables from MDX to use in your content:
export const title = 'My Post';
export const publishedDate = new Date('2026-03-03');

# {title}

Published: {publishedDate.toLocaleDateString()}

JavaScript Expressions

Use JavaScript expressions inline:
The answer is {2 + 2}.

Current year: {new Date().getFullYear()}

Component Props

Pass props to components:
import Alert from '../components/Alert.astro';

<Alert type="warning" title="Important">
  This is a warning message!
</Alert>

Common Use Cases

src/pages/blog/first-post.md
---
layout: ../../layouts/BlogPost.astro
title: My First Blog Post
author: Jane Doe
date: 2026-03-03
tags: [astro, blogging]
---

# Welcome to my blog!

This is my first post using Astro and Markdown.

Content Collections

Type-safe content management

Layouts

Wrap content with layouts

Components

Build reusable components

Assets

Optimize images in Markdown

Build docs developers (and LLMs) love