---
title: Markdown
description: How to write documents
---

import { Building, HomeIcon, Rocket } from 'lucide-react';

## Introduction

Fumadocs provides many useful extensions to MDX, a markup language. Here is a brief introduction to the default MDX syntax of Fumadocs.

> MDX is not the only supported format of Fumadocs. In fact, you can use any renderer such as headless CMS.
>
> See [Custom Content Source](/docs/integrations/content/custom) for details.

## MDX

We recommend MDX, a superset of Markdown with JSX syntax.
It allows you to import components, and use them in the document, or even writing JavaScript.

See:

- [MDX Syntax](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax).
- GFM (GitHub Flavored Markdown) is also supported, see [GFM Specification](https://github.github.com/gfm).

```mdx noCopy
import { Component } from './component';

<Component name="Hello" />

## Heading

### Heading

#### Heading

Hello World, **Bold**, _Italic_, ~~Hidden~~

1. First
2. Second
3. Third

- Item 1
- Item 2

> Quote here

![alt](/image.png)

| Table | Description |
| ----- | ----------- |
| Hello | World       |
```

### Frontmatter

Fumadocs support YAML-based frontmatter by default, `title` represents the page title (`h1`) in Fumadocs UI.

```mdx
---
title: This is a document
---

...
```

For this reason, h1 title (`# Heading`) is usually unused when writing Markdown/MDX unless you have custom logic for page title rendering.

<Callout title='In Fumadocs MDX'>

You can use the [`schema`](/docs/mdx/collections#schema-1) option to add frontmatter properties.

</Callout>

### Auto Links

Internal links use the `<Link />` component of your React framework (e.g. `next/link`) to allow prefetching and avoid hard-reload.

External links will get the default `rel="noreferrer noopener" target="_blank"` attributes for security.

```mdx
[My Link](https://github.github.com/gfm)

This also works: https://github.github.com/gfm.
```

### Cards

Useful for adding links.

```mdx
import { HomeIcon } from 'lucide-react';

<Cards>
  <Card
    href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
    title="Fetching, Caching, and Revalidating"
  >
    Learn more about caching in Next.js
  </Card>
  <Card title="href is optional">Learn more about `fetch` in Next.js.</Card>
  <Card icon={<HomeIcon />} href="/" title="Home">
    You can include icons too.
  </Card>
</Cards>
```

<Cards>
  <Card
    href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
    title="Fetching, Caching, and Revalidating"
  >
    Learn more about caching in Next.js
  </Card>
  <Card title="href is optional">Learn more about `fetch` in Next.js.</Card>
  <Card icon={<HomeIcon />} href="/" title="Home">
    You can include icons too.
  </Card>
</Cards>

#### "Further Reading" Section

You can do something like:

```tsx title="page.tsx"
import { getPageTreePeers } from 'fumadocs-core/page-tree';
import { source } from '@/lib/source';

<Cards>
  {getPageTreePeers(source.getPageTree(), '/docs/my-page').map((peer) => (
    <Card key={peer.url} title={peer.name} href={peer.url}>
      {peer.description}
    </Card>
  ))}
</Cards>;
```

This will show the other pages in the same folder as cards.

<DocsCategory url="/docs/ui/navigation" />

### Callouts

Useful for adding tips/warnings, it is included by default. You can specify the type of callout:

- `info` (default)
- `warn`/`warning`
- `error`
- `success`
- `idea`

```mdx
<Callout>Hello World</Callout>

<Callout title="Title" type="warn">
  Hello World
</Callout>

<Callout title="Title" type="error">
  Hello World
</Callout>

<Callout title="Title" type="idea">
  Hello World
</Callout>
```

<Callout>Hello World</Callout>

<Callout title="Title" type="warn">
  Hello World
</Callout>

<Callout title="Title" type="error">
  Hello World
</Callout>

<Callout title="Title" type="idea">
  Hello World
</Callout>

### Headings

An anchor is automatically applied to each heading, it sanitizes invalid characters like spaces. (e.g. `Hello World` to `hello-world`)

```md
# Hello `World`
```

#### TOC Settings

The table of contents (TOC) will be generated based on headings, you can also customize the effects of headings:

```md
# Heading [!toc]

This heading will be hidden from TOC.

# Another Heading [toc]

This heading will **only** be visible in TOC, you can use it to add additional TOC items.
Like headings rendered in a React component:

<MyComp />
```

#### Custom Anchor

You can add `[#slug]` to customize heading anchors.

```md
# heading [#my-heading-id]
```

You can also chain it with TOC settings like:

```md
# heading [toc] [#my-heading-id]
```

To link people to a specific heading, add the heading id to hash fragment: `/page#my-heading-id`.

### Codeblock

Syntax Highlighting is supported by default using [Rehype Code](/docs/headless/mdx/rehype-code).

````mdx
```js
console.log('Hello World');
```

```js title="My Title"
console.log('Hello World');
```
````

#### Line Numbers

Show line numbers, it also works with Twoslash and other transformers.

````mdx tab="Input"
```ts twoslash lineNumbers
const a = 'Hello World';
//    ^?
console.log(a); // [!code highlight]
```
````

```ts twoslash lineNumbers tab="Output"
const a = 'Hello World';
//    ^?
console.log(a); // [!code highlight]
```

You can set the initial value of line numbers.

````mdx tab="Input"
```js lineNumbers=4
function main() {
  console.log('starts from 4');

  return 0;
}
```
````

```js lineNumbers=4 tab="Output"
function main() {
  console.log('starts from 4');

  return 0;
}
```

#### Shiki Transformers

We support some of the [Shiki Transformers](https://shiki.style/packages/transformers), allowing you to highlight/style specific lines.

````md tab="Input"
```tsx
// highlight a line
<div>Hello World</div> // [\!code highlight]

// highlight a word
// [\!code word:Fumadocs]
<div>Fumadocs</div>

// diff styles
console.log('hewwo'); // [\!code --]
console.log('hello'); // [\!code ++]

// focus
return new ResizeObserver(() => {}) // [\!code focus]
```
````

```tsx tab="Output"
// highlight a line
<div>Hello World</div> // [!code highlight]

// highlight a word
// [!code word:Fumadocs]
<div>Fumadocs</div>

// diff styles:
console.log('hewwo'); // [!code --]
console.log('hello'); // [!code ++]

// focus
return new ResizeObserver(() => {}) // [!code focus]
```

#### Tab Groups

````mdx
```ts tab="Tab 1"
console.log('A');
```

```ts tab="Tab 2"
console.log('B');
```
````

```ts tab="Tab 1"
console.log('A');
```

```ts tab="Tab 2"
console.log('B');
```

To add a persist ID, define `tab-group` at the first codeblock:

````mdx
```ts tab="Tab 1" tab-group="my-custom-group"
console.log('A');
```

```ts tab="Tab 2"
console.log('B');
```
````

```ts tab="Tab 1" tab-group="my-custom-group"
console.log('A');
```

```ts tab="Tab 2"
console.log('B');
```

Another group:

```ts tab="Tab 1" tab-group="my-custom-group"
console.log('A');
```

```ts tab="Tab 2"
console.log('B');
```

#### MDX in Tab Groups

While disabled by default, you use MDX in tab values by configuring the remark plugin:

```ts tab="Fumadocs MDX" title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';

export default defineConfig({
  mdxOptions: {
    remarkCodeTabOptions: {
      parseMdx: true, // [!code ++]
    },
  },
});
```

```ts tab="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkCodeTab } from 'fumadocs-core/mdx-plugins';

await compile('...', {
  remarkPlugins: [
    [
      remarkCodeTab,
      {
        parseMdx: true, // [!code ++]
      },
    ],
  ],
});
```

````mdx
```ts tab="<Building /> Tab 1"
console.log('A');
```

```ts tab="<Rocket /> Tab 2"
console.log('B');
```
````

```ts tab="<Building /> Tab 1"
console.log('A');
```

```ts tab="<Rocket /> Tab 2"
console.log('B');
```

### Include

> This is only available on **Fumadocs MDX**.

Reference another file (can also be a Markdown/MDX document).
Specify the target file path in `<include>` tag (relative to the MDX file itself).

```mdx title="page.mdx"
<include>./another.mdx</include>
```

See [other usages of include](/docs/mdx/include).

### NPM Commands

Useful for generating commands for installing packages with different package managers.

````md tab="Input"
```npm
npm i next -D
```
````

```npm tab="Output"
npm i next -D
```

See [`remark-npm`](/docs/headless/mdx/remark-npm) for details.

### Steps

Useful for denoting steps for guides, see [`remark-steps`](/docs/headless/mdx/remark-steps) for enable & configure.

```md
### Installation [step]

### Write Code [step]

### Deploy [step]
```

#### Installation [step]

#### Write Code [step]

#### Deploy [step]

### Other Components

You can configure & use the [built-in components](/docs/ui/components) in your MDX document, such as Tabs, Accordions and Zoomable Image.

## Additional Features

You may be interested:

<DocsCategory />
