Markdown
Markdown content is commonly used to author text-heavy content like blog posts and documentation. Astro includes built-in support for Markdown with some added features like support for JavaScript expressions and Astro components right in your Markdown.
Markdown Pages
Section titled Markdown PagesAstro treats any .md file inside of the /src/pages directory as a page. Placing a file in this directory, or any sub-directory, will automatically build a page route using the pathname of the file.
📚 Read more about Astro’s file-based routing.
Basic Example
Section titled Basic ExampleThe easiest way to start using Markdown in Astro is to create a src/pages/index.md homepage route in your project. Copy the basic template below into your project, and then view the rendered HTML at the homepage route of your project. Usually, this is at http://localhost:3000.
---
# Example: src/pages/index.md
title: Hello, World
---
# Hi there!
This is your first markdown page. It probably isn't styled much, although
Markdown does support **bold** and *italics.*
To learn more about adding a layout to your page, read the next section on **Markdown Layouts.**Markdown Layouts
Section titled Markdown LayoutsMarkdown pages have a special frontmatter property for layout that defines the relative path to an Astro layout component. This component will wrap your Markdown content, providing a page shell and any other included page template elements.
---
layout: ../layouts/BaseLayout.astro
---A typical layout for Markdown pages includes:
- the content prop to access the Markdown page’s frontmatter data.
- a default
<slot />to indicate where the page’s Markdown content should be rendered.
---
// src/layouts/BaseLayout.astro
// 1. The content prop gives access to frontmatter data
const { content } = Astro.props;
---
<html>
<head>
<!-- Add other Head elements here, like styles and meta tags. -->
<title>{content.title}</title>
</head>
<body>
<!-- Add other UI components here, like common headers and footers. -->
<h1>{content.title} by {content.author}</h1>
<!-- 2. Rendered HTML will be passed into the default slot. -->
<slot />
<p>Written on: {content.date}</p>
</body>
</html>The content prop also contains an astro property with additional metadata about the page such as the complete Markdown source and a headers object.
An example blog post content object might look like:
{
/** Frontmatter from a blog post
"title": "Astro 0.18 Release",
"date": "Tuesday, July 27 2021",
"author": "Matthew Phillips",
"description": "Astro 0.18 is our biggest release since Astro launch.",
"draft": false,
"keywords": ["astro", "release", "announcement"]
**/
"astro": {
"headers": [
{
"depth": 1,
"text": "Astro 0.18 Release",
"slug": "astro-018-release"
},
{
"depth": 2,
"text": "Responsive partial hydration",
"slug": "responsive-partial-hydration"
}
/* ... */
],
"source": "# Astro 0.18 Release\nA little over a month ago, the first public beta [...]"
},
"url": ""
}💡
astroandurlare the only guaranteed properties provided by Astro in thecontentprop. The rest of the object is defined by your frontmatter variables.
Frontmatter as Props
Section titled Frontmatter as PropsAny Astro component (not just layouts!) can receive the values defined in your Markdown frontmatter as props. You can specify several types of data using YAML frontmatter, and capture even richer meta information from each blog post to use throughout your Astro site.
Access these values in any .astro file as you would in a layout, as described above.
Markdown Drafts
Section titled Markdown Draftsdraft: true is an optional frontmatter value that will mark an individual .md page or post as “unpublished.” By default, this page will be excluded from the site build.
Markdown pages without the draft property or those with draft: false are unaffected and will be included in the final build.
src/pages/post/blog-post.md
---
layout: ../../layouts/BaseLayout.astro
title: My Blog Post
draft: true
---
This is my in-progress blog post.
No page will be built for this post.
To build and publish this post:
- update the frontmatter to `draft: false` or
- remove the `draft` property entirely.⚠️ Although
draft: truewill prevent a page from being built on your site at that page route,Astro.glob()currently returns all your Markdown files.
To exclude the data (e.g. title, link, description) from a draft post from being included in your post archive, or list of most recent posts, be sure that your Astro.glob() function also filters to exclude any draft posts.
⚙️ To enable building draft pages:
Add drafts: true to buildOptions in astro.config.mjs
//astro.config.mjs
export default /** @type {import('astro').AstroUserConfig} */ ({
< ... >
buildOptions: {
site: 'https://example.com/',
drafts: true,
},
});💡 You can also pass the —drafts flag when running astro build to build draft pages!
Authoring Markdown
Section titled Authoring MarkdownIn addition to supporting standard Markdown syntax, Astro also extends Markdown to make your content even more expressive. Below are some Markdown features that only exist in Astro.
Using Variables in Markdown
Section titled Using Variables in Markdownfrontmatter variables can be used directly in your Markdown as properties of the frontmatter object.
---
author: Leon
age: 42
---
# About the Author
{frontmatter.author} is {frontmatter.age} and lives in Toronto, Canada.Using Components in Markdown
Section titled Using Components in MarkdownYou can import components into your Markdown file with setup and use them alongside your Markdown content. The frontmatter object is also available to any imported components.
---
layout: ../layouts/BaseLayout.astro
setup: |
import Author from '../../components/Author.astro'
import Biography from '../components/Biography.jsx'
author: Leon
---
<Author name={frontmatter.author}/>
<Biography client:visible>
{frontmatter.author} lives in Toronto, Canada and enjoys photography.
</Biography>Markdown Component
Section titled Markdown ComponentAstro has a dedicated component used to let you render Markdown in .astro files.
You can import the built-in Astro Markdown component in your component script and then write any Markdown you want between <Markdown> </Markdown> tags.
---
import { Markdown } from 'astro/components';
import Layout from '../layouts/Layout.astro';
const expressions = 'Lorem ipsum';
---
<Layout>
<Markdown>
# Hello world!
**Everything** supported in a `.md` file is also supported here!
There is _zero_ runtime overhead.
In addition, Astro supports:
- Astro {expressions}
- Automatic indentation normalization
- Automatic escaping of expressions inside code blocks
```js
// This content is not transformed!
const object = { someOtherValue };
```
- Rich component support like any `.astro` file!
- Recursive Markdown support (Component children are also processed as Markdown)
</Markdown>
</Layout>Remote Markdown
Section titled Remote MarkdownIf you have Markdown in a remote source, you may pass it directly to the Markdown component through the content attribute.
---
import { Markdown } from 'astro/components';
const content = await fetch('https://raw.githubusercontent.com/withastro/docs/main/README.md').then(res => res.text());
---
<Layout>
<Markdown content={content} />
</Layout>Nested Markdown
Section titled Nested Markdown<Markdown> components can be nested.
---
import { Markdown } from 'astro/components';
const content = await fetch('https://raw.githubusercontent.com/withastro/docs/main/README.md').then(res => res.text());
---
<Layout>
<Markdown>
## Markdown example
Here we have some __Markdown__ code. We can also dynamically render remote content.
<Markdown content={content} />
</Markdown>
</Layout>⚠️ Use of the Markdown component to render remote Markdown can open you up to a cross-site scripting (XSS) attack. If you are rendering untrusted content, be sure to sanitize your content before rendering it.
Markdown Parsers
Section titled Markdown ParsersAstro comes with Markdown support powered by remark.
The @astrojs/markdown-remark package is included by default with the following plugins pre-enabled:
⚙️ You can include a custom Markdown parser inside
astro.config.mjsby providing a function that follows theMarkdownParsertype declared inside this file.
// astro.config.mjs
export default {
markdown: {
// ...
},
};Remark and Rehype Plugins
Section titled Remark and Rehype PluginsAstro supports third-party plugins for Markdown. You can provide your plugins in astro.config.mjs.
Note: Enabling custom
remarkPluginsorrehypePluginsremoves Astro’s built-in support for the plugins previously mentioned. You must explicitly add these plugins to yourastro.config.mjsfile, if desired.
Add a Markdown plugin in Astro
Section titled Add a Markdown plugin in Astro-
Install the npm package dependency in your project.
-
Update
remarkPluginsorrehypePluginsinside the@astrojs/markdown-remarkoptions:
// astro.config.mjs
export default {
markdown: {
remarkPlugins: [
// Add a Remark plugin that you want to enable for your project.
// If you need to provide options for the plugin, you can use an array and put the options as the second item.
// ['remark-autolink-headings', { behavior: 'prepend'}],
],
rehypePlugins: [
// Add a Rehype plugin that you want to enable for your project.
// If you need to provide options for the plugin, you can use an array and put the options as the second item.
// 'rehype-slug',
// ['rehype-autolink-headings', { behavior: 'prepend'}],
],
},
};You can provide names of the plugins as well as import them:
// astro.config.mjs
import autolinkHeadings from 'remark-autolink-headings';
export default {
markdown: {
remarkPlugins: [[autolinkHeadings, { behavior: 'prepend' }]],
},
};Syntax Highlighting
Section titled Syntax HighlightingAstro comes with built-in support for Shiki and Prism. This provides instant syntax highlighting for:
- all code fences (```) used in a markdown (
.md) file and the built-in<Markdown />component. - content within the built-in
<Code />component (powered by Shiki), or the<Prism />component (powered by Prism).
Shiki is enabled by default, preconfigured with the github-dark theme. The compiled output will be limited to inline styles without any extraneous CSS classes, stylesheets, or client-side JS.
If you opt to use Prism, we will apply Prism’s CSS classes instead. Note that you need to bring your own CSS stylesheet for syntax highlighting to appear! See the Prism configuration section for more details.
Choose a syntax highlighter
Section titled Choose a syntax highlighterShiki is our default syntax highlighter. If you’d like to switch to ‘prism’ or disable syntax highlighting entirely, you can use the markdown config object:
// astro.config.mjs
export default {
markdown: {
// Can be 'shiki' (default), 'prism' or false to disable highlighting
syntaxHighlight: 'prism',
}
};Shiki configuration
Section titled Shiki configurationWhen using Shiki, you’ll configure all options via the shikiConfig object like so:
// astro.config.mjs
export default {
markdown: {
shikiConfig: {
// Choose from Shiki's built-in themes
// https://github.com/shikijs/shiki/blob/main/docs/themes.md#all-themes
theme: 'dracula',
// Manually specify langs
// Note: Shiki has countless langs built-in, including .astro!
langs: ['astro'],
// Enable word wrap to prevent horizontal scrolling
wrap: true,
},
},
};We also suggest diving into their theme documentation to explore loading custom theme, light vs dark mode toggles, or styling via CSS variables.
Prism configuration
Section titled Prism configurationWhen using Prism, you’ll need to add a stylesheet to your project for syntax highlighting. If you’re just getting started and prefer to use Prism over Shiki, we suggest:
- Setting
syntaxHighlight: ‘prism’from your@astrojs/markdown-remarkconfig. - Choosing a premade stylesheet from the available Prism Themes.
- Adding this stylesheet to your project’s
public/directory. - Loading this into your page’s
<head>via a<link>tag.
You can also visit the list of languages supported by Prism for options and usage.