---
title: Fix "has an H1 in its body" or "skips a heading level" (DS-A02)
description: The page title is the H1. Start body headings at ## and never skip a level, even on the first heading.
---

## Symptom

`reed check` or `reed build` fails with one or more of these:

```txt
  ✗ [DS-A02] content file "guides/setup.mdx" has an H1 in its body (the H1 comes from frontmatter "title")
  ✗ [DS-A02] content file "guides/setup.mdx" skips a heading level (h2 → h4)
  ✗ [DS-A02] content file "guides/setup.mdx" skips a heading level (h1 → h3)
check failed.
```

The last form confuses people most: the page has no `#` heading anywhere, yet the
message says `h1 → h3`. That is a page whose first heading is `###`.

## Cause

Reed renders frontmatter `title` as the page's H1. The body's headings are checked as if
that H1 sits directly above them, so two rules apply:

1. **No `#` in the body.** A second H1 gives the page two competing top-level headings,
   and a screen reader announces both.
2. **Each heading may go at most one level deeper than the one before it.** Going back
   up, `####` to `##`, is always fine; going down more than one step is not.

Because the implied H1 counts, rule 2 applies to your **first** body heading too. A page
that starts at `###` has skipped `h2`, which is the `h1 → h3` message.

Some common ways to get here:

- A page imported from another platform keeps its old `# Title` line under the new
  frontmatter.
- A short page begins at `###` because `##` "looked too big".
- A section is deleted and its `####` children are left under a `##`.
- Headings inside components count. A `###` inside an `Accordion`, `Tab` or `Step` is
  part of the same outline as the headings around it.

A `#` line inside a fenced code block is code, not a heading, and is never reported.

## Fix

### Remove the body H1

Delete the `#` line and move its text into `title` if the title is not already right:

```mdx
---
title: Set up your project
description: Install Reed and build your first site.
---

# Set up your project

## Install
```

becomes:

```mdx
---
title: Set up your project
description: Install Reed and build your first site.
---

## Install
```

### Start at `##`

If the page begins with `###`, promote every heading one level, keeping their relative
structure:

```mdx
### Install
#### From npm
#### From source
### Configure
```

becomes:

```mdx
## Install
### From npm
### From source
## Configure
```

Promote them all, not just the first — promoting only `### Install` would leave
`## Install` followed by `#### From npm`, which is a new `h2 → h4` error.

### Close a skipped level

For `h2 → h4` in the middle of a page, either promote the deeper heading or add the
missing level between them, if the content really has that extra layer:

```mdx
## Configure

#### Environment variables
```

becomes:

```mdx
## Configure

### Environment variables
```

### Find them quickly

The message names the file and the two levels, but not the line. List a page's headings
with their line numbers:

```sh
grep -nE '^#{1,6} ' content/guides/setup.mdx
```

Read the level column top to bottom. The first line must be `##`, and no line may be
more than one `#` longer than the line before it. This also lists `#` lines inside code
fences; ignore those, since the check does.

## Verify

```sh
reed check 2>&1 | grep -c 'DS-A02'
```

Expect `0`, and a final `check passed.` After fixing, glance at the page's table of
contents in `reed dev`. It is built from the same headings, so an outline that looks
flat or oddly nested there usually means a heading is still at the wrong level.

## Related

- [Pages](/docs/authoring/pages) — frontmatter and headings
- [MDX pitfalls](/docs/authoring/mdx-pitfalls) — the H1-in-the-body section
- [Accessibility](/docs/guides/accessibility)
- [Diagnostics](/docs/reference/diagnostics)
