Markdown / MDX Writing Guide
This guide covers common Markdown syntax, Expressive Code integration in Astro Plain, GitHub-style alert blocks, and how to use MDX components from Starlight.
NOTE
This article was translated using AI.
Common Markdown Syntax
Headings
Markdown uses # through ###### to represent heading levels 1~6:
Heading 1 (H1)
Heading 2 (H2)
Heading 3 (H3)
Heading 4 (H4)
Heading 5 (H5)
Heading 6 (H6)
# Heading 1 (H1)
## Heading 2 (H2)
### Heading 3 (H3)
#### Heading 4 (H4)
##### Heading 5 (H5)
###### Heading 6 (H6)Text Formatting
| Preview | Markdown |
|---|---|
| Bold text | **bold text** or __bold text__ |
| Italic text | *italic text* or _italic text_ |
| Bold and italic | ***bold and italic*** |
~~strikethrough~~ | |
Inline code | `inline code` |
| Ctrl + C | <kbd>Ctrl</kbd> + <kbd>C</kbd> |
Blockquotes and Nested Quotes
This is a basic blockquote.
This is a nested second-level blockquote.
Blockquotes also support bold and
inline code.
> This is a basic blockquote.>> > This is a nested second-level blockquote.>> Blockquotes also support **bold** and `inline code`.Lists and Task Lists
Unordered list:
- Item one
- Sub-item A
- Sub-item B
- Item two
Ordered list:
- Phase 1: Environment setup
- Phase 2: Development and build
- Phase 3: Deployment and release
Task Lists:
- Core feature design completed
- Static multilingual routing and i18n
- Documentation improvements in progress
**Unordered list**:- Item one - Sub-item A - Sub-item B- Item two
**Ordered list**:1. Phase 1: Environment setup2. Phase 2: Development and build3. Phase 3: Deployment and release
**Task Lists**:- [x] Core feature design completed- [x] Static multilingual routing and i18n- [ ] Documentation improvements in progressTables and Alignment
| Left-aligned Header | Center-aligned Header | Right-aligned Header |
|---|---|---|
| Astro | SSG / SSR | Fast loading |
| Expressive Code | Syntax highlighting | Multi-theme support |
| Pagefind | Full-text search | Static site support |
| Left-aligned Header | Center-aligned Header | Right-aligned Header || :--- | :---: | ---: || Astro | SSG / SSR | Fast loading || Expressive Code | Syntax highlighting | Multi-theme support || Pagefind | Full-text search | Static site support |Links and Images
External link: Visit the Astro website (opens in a new tab)
Relative site link: View project introduction
Image: 
External link: [Visit the Astro website](https://astro.build/)
Relative site link: [View project introduction](/en-US/blog/sample/intro)
Image: TIP
Using Astro’s Image or Picture components in MDX documents lets you take advantage of Astro’s image optimization features, such as automatic resizing, format conversion, and lazy loading.

import { Image } from "astro:assets";import cover from "@/assets/og.jpg";
<Image src={cover} alt="Cover image" />GitHub-Style Alert Blocks (BlockquoteAlerts)
Based on remark-github-blockquote-alert (opens in a new tab),
you can use the > [!TYPE] syntax to create different types of alert blocks:
NOTE
For recording general background, context, or supplementary knowledge.
TIP
Provides tips that help improve development efficiency or user experience.
IMPORTANT
Highlights critical information that users must know or cannot overlook.
WARNING
Warns about issues that may cause build failures or unexpected behavior.
CAUTION
Alerts about serious risks that could lead to data loss or security vulnerabilities.
> [!NOTE]> For recording general background, context, or supplementary knowledge.
> [!TIP]> Provides tips that help improve development efficiency or user experience.
> [!IMPORTANT]> Highlights critical information that users must know or cannot overlook.
> [!WARNING]> Warns about issues that may cause build failures or unexpected behavior.
> [!CAUTION]> Alerts about serious risks that could lead to data loss or security vulnerabilities.Footnotes
This is a sentence with a footnote[^1].
Footnotes can also span multiple lines[^2].
[^1]: This is the content of a single-line footnote.[^2]: This is the first line of a multi-line footnote. This is the second line of the multi-line footnote.Code Highlighting
This project uses Expressive Code (opens in a new tab) for syntax highlighting.
Code Block Title
Add title="..." to the code block meta to render a title at the top of the block:
export function calculateSum(a: number, b: number): number { return a + b;}```ts title="src/utils/math.ts"export function calculateSum(a: number, b: number): number { return a + b;}```Line Numbers and Line Highlighting
Use showLineNumbers to enable line numbers, and {line range} to highlight specific lines:
export async function fetchData(endpoint: string) { const url = `https://api.example.com/${endpoint}`; try { const response = await fetch(url); const data = await response.json(); return data; } catch (error) { console.error("Fetch failed:", error); throw error; }} ```typescript title="src/services/api.ts" {2, 4-6} showLineNumbers export async function fetchData(endpoint: string) { const url = `https://api.example.com/${endpoint}`; try { const response = await fetch(url); const data = await response.json(); return data; } catch (error) { console.error("Fetch failed:", error); throw error; } } ```Diff and Insertion/Deletion Markers
Use ins={...} and del={...} to mark added or removed lines:
{ "name": "my-astro-blog", "version": "1.0.0", "version": "2.0.0"} ```json title="package.json" del={3} ins={4} { "name": "my-astro-blog", "version": "1.0.0", "version": "2.0.0" } ```Or use a diff code block:
export default { allowRobots: false, allowRobots: true, postsPerPage: 10,}; ```diff title="git diff site.config.ts" export default { - allowRobots: false, + allowRobots: true, postsPerPage: 10, }; ```Text Highlighting
Use ins="text", del="text", or "keyword" to highlight specific text within a code block:
const express = require("express");const app = express();const port = 3000;
app.listen(port, () => { console.log(`Server listening on port ${port}`);});```javascript title="app.js" "port" ins="3000" del="8080"const express = require("express");const app = express();const port = 3000;
app.listen(port, () => { console.log(`Server listening on port ${port}`);});```Code Collapsing
Use collapse={start-end} to collapse a range of lines by default for long code blocks:
import { defineCollection, z } from "astro:content";7 collapsed lines
// Schema with many field definitionsconst baseSchema = z.object({ id: z.string(), createdTime: z.date(), updatedTime: z.date(), status: z.enum(["draft", "published", "archived"]),});
export const collections = { posts: defineCollection({ schema: baseSchema }),};```typescript title="long-script.ts" collapse={2-8}import { defineCollection, z } from "astro:content";
// Schema with many field definitionsconst baseSchema = z.object({ id: z.string(), createdTime: z.date(), updatedTime: z.date(), status: z.enum(["draft", "published", "archived"]),});
export const collections = { posts: defineCollection({ schema: baseSchema }),};```Terminal Style
Use frame="terminal" to render a code block as a terminal window with a title bar and control buttons:
# Clone the template repositorygit clone https://github.com/Aaakul/astro-plain.git my-blog
# Enter the directory and install dependenciescd my-blogpnpm install
# Start the local development serverpnpm dev```bash title="Install and start" frame="terminal"# Clone the template repositorygit clone https://github.com/Aaakul/astro-plain.git my-blog
# Enter the directory and install dependenciescd my-blogpnpm install
# Start the local development serverpnpm dev```Built-in MDX Components
In .mdx files, the following components are globally registered and can be used without manual imports.
Steps Component
<Steps> is used for writing step-by-step guides, automatically numbering each step. It supports nested paragraphs, code blocks, and tabs.
Basic Usage
- Step 1: Clone the repository to your local machine.
- Step 2: Install dependencies in the project root directory.
- Step 3: Run the
devcommand to start live preview.
<Steps>
1. Step 1: Clone the repository to your local machine.2. Step 2: Install dependencies in the project root directory.3. Step 3: Run the `dev` command to start live preview.
</Steps>Combined Usage
-
Edit the configuration file
Edit
site.config.tsin the project root directory:site.config.ts export default {siteUrl: "https://example.com",defaultLanguage: "en-US",}; -
Install dependencies
Choose the package manager you prefer:
Terminal window bun installTerminal window pnpm installTerminal window npm install -
Start the development server
Once the development server starts, the terminal will display the access URL or port. Open it in your browser to preview.
<Steps>
1. **Edit the configuration file**
Edit `site.config.ts` in the project root directory:
```typescript title="site.config.ts" export default { siteUrl: "https://example.com", defaultLanguage: "en-US", }; ```
2. **Install dependencies**
Choose the package manager you prefer:
<Tabs syncKey="pkg-manager"> <TabItem label="Bun" icon="bun"> ```bash bun install ``` </TabItem> <TabItem label="pnpm" icon="pnpm"> ```bash pnpm install ``` </TabItem> <TabItem label="npm" icon="npm"> ```bash npm install ``` </TabItem> </Tabs>
3. **Start the development server**
Once the development server starts, the terminal will display the access URL or port. Open it in your browser to preview.
</Steps>File Tree Component
<FileTree> generates a directory tree with hierarchical indentation and file type icons.
Features:
- Directory indicator: Append a slash
/to the name (e.g.,src/) to mark it as a directory. - Highlight specific files/directories: Use bold syntax
**filename**. - End-of-line description: Add a space and description text after the filename.
- Ellipsis placeholder: Use
...to represent omitted files.
Directoryi18n/
- …
Directorymessages/ Translation dictionaries for each language
- zh-Hans.ts Chinese dictionary
- en-US.ts English dictionary
- ja-JP.ts Japanese dictionary
Directorysrc/content/
Directoryblog/ Blog posts (linked via
translationKey)- …
Directoryauthor/ Author information (organized by language folder)
- …
Directoryproject/ Project introductions (organized by language folder)
- …
Directorymdx/ Other MDX content (organized by language folder)
Directory[lang]/
- hero.mdx Hero section
- site.config.ts Site core configuration file
- …
<FileTree> - i18n/ - ... - messages/ Translation dictionaries for each language - **zh-Hans.ts** Chinese dictionary - **en-US.ts** English dictionary - **ja-JP.ts** Japanese dictionary - src/content/ - **blog/** Blog posts (linked via `translationKey`) - **author/** Author information (organized by language folder) - **project/** Project introductions (organized by language folder) - **mdx/** Other MDX content (organized by language folder) - **[lang]/** - **hero.mdx** Hero section - **site.config.ts** Site core configuration file - ...
</FileTree>Tabs Component
<Tabs> and <TabItem> organize different versions or related options of the same content into tabs.
Icons and Cross-Component Sync (syncKey)
<Tabs> components sharing the same syncKey will share the current selection. When the user switches tabs in one, all others with the same syncKey update in sync.
bun --bun run devpnpm run devnpm run devbun installpnpm installnpm install<Tabs syncKey="pkg-manager"> <TabItem label="Bun" icon="bun"> ```bash bun --bun run dev ```
</TabItem>15 collapsed lines
<TabItem label="pnpm" icon="pnpm"> ```bash pnpm run dev ```
</TabItem>
<TabItem label="npm" icon="npm"> ```bash npm run dev ```
</TabItem></Tabs>