Tutorials 18 min read

Filename, H1, or Front Matter? Where Each Tool Reads Your Note's Title

MMNMNOTE
markdownnote-takingfront-matterheadingsMkDocsJekyllHugoPandocObsidianmarkdownlintDocusaurus

A Markdown note's title can live in three places: the filename, a first-line # H1 heading, or a front-matter title: key. Inside a single note app any of the three works. The moment a file is published, linted, converted, or opened in a different editor, each tool reads a different place — in a documented, tool-specific order that no forum thread has ever put in one table.

The table below maps seven tools to where they actually look. One conditional rule follows from it.


Three places a title can live

Every Markdown file gives you three slots for a title. Most tools treat them as a priority queue — they check slot one, and if it is occupied they stop. Writing to the wrong slot for your pipeline is invisible inside your note app and broken everywhere else.

The three slots:

The confusion starts when two slots are filled at once. Obsidian has shown the filename as an inline title since v1.0 — the 2022 changelog introduced it as: "Show inline title — Notes now display the full note title inline with the note contents as an Inline Title. You can disable this in settings."1 A writer who also types # My Note on the first line now sees the title twice. Whether that is cosmetic or structural depends entirely on where the file goes next.


How each tool reads the title

Seven tools, each with its own lookup order. The chain is strict: every tool stops at the first slot it finds populated and ignores the rest. A slot that looks occupied to you but does not match the tool's exact syntax requirement is treated as empty.2

The behavior below is sourced from each tool's first-party documentation and, where it differed, from the source code — both accessed 2026-10-14 on pinned commits. Behavior may change in future releases.

ToolFirstSecondThirdFourthNotes
MkDocsnav entry (explicit)Front-matter title:First H1 body headingFilename (hyphens/underscores → spaces; all-lowercase → capitalised)"Upon finding a title for a page, MkDoc does not continue checking."2 The H1 is taken only if it is the first block element in the body — an H1 preceded by a blank line does not count.3
GitHub Pages (Jekyll)Front-matter title:First H1, H2, or H3 via jekyll-titles-from-headingsFilename-derived title (Jekyll default)—The plugin is "enabled by default and cannot be disabled" on GitHub Pages.4 Applies to pages only; posts keep the filename-derived title unless collections: true is set. Self-hosted Jekyll can disable it; GitHub Pages cannot.5
markdownlint MD041Front-matter title: (rule passes silently if present)First line must be an H1 — otherwise a violation——Rationale: "The top-level heading often acts as the title of a document."6 Configurable via front_matter_title (default regex ^\s*title\s*[:=]).
markdownlint MD025Front-matter title: counts as the document's one H1One body H1 is allowed — but only if no front-matter title is set——Setting both a front-matter title: and a body # H1 is a lint violation under default config.7 "there can not be more than one title for the document."7
Pandoc (no flags)H1 stays in the body; <title> = filename stem———Without --shift-heading-level-by=-1, the H1 is a body element, not the document title.
Pandoc (--shift-heading-level-by=-1)Level-1 heading at document start → metadata title———"with a shift of -N, a level-N heading at the beginning of the document replaces the metadata title."8 If a front-matter title is also set, the shifted H1 appears twice in output — once from front matter, once from the promoted body heading. No warning is emitted.8
ObsidianFilename (shown as inline title since v1.0)Body # H1 is a normal heading, visible but separate from the inline title——Obsidian acknowledges "you might notice some redundancy" when a body H1 is present.1 Disable the inline title in Settings → Appearance.
Hugo (file-backed page)Front-matter title:———For any page with a backing file, Hugo reads only front-matter title:. Neither the H1 nor the filename is consulted.9 Without a front-matter title, Hugo falls to the section name or site title — not your H1.
DocusaurusFront-matter title:First Markdown heading in the bodyFile-path-derived id (path from docs root, without extension)—The id fallback is not the bare filename — it is the full path relative to the docs root, including any directory segments.10 hide_title: true hides only the front-matter title, not a body H1.

Own receipts (markdownlint and Pandoc)

R1 — markdownlint 0.41.1 (npm, default config), five test fixtures:

(a) H1-only                             → clean
(b) front-matter title only             → clean
(c) front-matter title + body # H1      → MD025 violation on line 5
(d) no title at all                     → MD041 violation on line 1
(e) first line H2, no H1               → MD041 violation on line 1

Setting both a front-matter title: and a body # H1 triggers MD025 under default config. This is a violation, not a style disagreement. (node v20.19.5; markdownlint 0.41.1; 2026-10-14.)

R2 — Pandoc 3.12.1, -s -t html:

(a) H1-only (no shift flag)             → <title> = filename stem; H1 stays a body heading
(b) H1 + --shift-heading-level-by=-1   → <title>Meeting notes</title>; H1 promoted to title
(c) front-matter title + body H1 + flag → title shown TWICE: h1.title from front matter
                                          AND h1 from the promoted body H1; no stderr warning

The duplication in case (c) is silent. No flag, no warning, two H1 elements in the rendered output. (Pandoc 3.12.1; 2026-10-14.)


The corrections the docs don't mention

The table resolves four common misconceptions that appear in forum answers on this topic — each sourced to a tool's own first-party documentation or source code, not to community convention. Three of the four have no currently-published correction anywhere on the web as of 2026-10-14. Read the tool's doc, not the thread.

Hugo reads neither the H1 nor the filename for a file-backed page. Most writers expect Hugo to fall back to the H1 when front matter is absent. It does not.9 For any page that has a backing file, .Title is the front-matter title: value — and nothing else. If that key is missing, Hugo uses the section name or site title instead of your H1. This is the most surprising finding in the table, and it is absent from every forum answer on the question as of 2026-10-14.

Setting both a front-matter title: and a body # H1 is a lint error, not a style choice. MD025 defaults to treating the front-matter title: as the document's one allowed H1.7 A body H1 after it is a violation — confirmed in the R1 receipt above. The common advice is to keep both titles consistent. The markdownlint position is that both should not exist simultaneously unless front_matter_title is set to empty in your config.

MkDocs requires the H1 to be the very first block element. The user guide says the H1 must be on "the first line of the document body."2 The source code is stricter: it checks only the first block element and breaks after it.3 An H1 preceded by a blank line, a YAML comment, or any other block content is not taken. The filename fallback activates instead.

Docusaurus's title fallback is the id, not the bare filename. For a file at docs/tutorials/notes/getting-started.md, the id fallback is tutorials/notes/getting-started — not getting-started.10 In nested docs trees this matters. The plugin also uses the front-matter title for <title> in the browser tab and can show a body H1 as the page hero separately — hide_title: true only hides the former.

One more: the jekyll-titles-from-headings plugin takes H2 and H3 headings, not only H1.5 Its rationale: it "allows you to store the title semantically, in the document itself so that it's readable, both as Markdown and when rendered."5 A note that opens with ## Context and has no front-matter title gets the H2's text as its page title on GitHub Pages.


The conditional rule

No single title convention is universally right for Markdown files. The correct rule depends on one fact: whether the file ever leaves the app that is currently displaying it. The table above makes that fact actionable — each tool's lookup order tells you exactly which slot it will use.

If the file stays inside the app that shows filenames as titles — the filename is already the title. A body H1 is visible in the note but duplicates the inline title in Obsidian and similar apps. You can leave it out. Nothing downstream breaks because there is no downstream.

If the file is published to a static site, linted, converted, or opened in any editor that does not surface filenames — write one first-line # H1 that matches the filename. Do not also set a front-matter title: unless the specific tool requires it. For GitHub Pages, markdownlint, and most static site generators, the first-line H1 is the portable solution.

Hugo and Docusaurus are the exception: both read front-matter title: before the body heading, and Hugo ignores the body heading entirely for file-backed pages. If your pipeline includes either, set front-matter title: explicitly. You can then leave the body H1 out, or keep it for human readability — but if you keep it, disable front_matter_title in your markdownlint config to avoid the MD025 violation.

The one pattern to avoid in every pipeline: two titles that disagree. A front-matter title: Meeting Notes plus a body # Team Standup Summary is a lint violation (MD025), a Pandoc duplication waiting to trigger, and a Hugo source of invisible title loss — all at once. Once you have decided to write an H1, keep it consistent with the filename and you avoid all three at once. See Navigate a Long Note by Its Outline for the heading-hygiene discipline that follows from there.11


A three-line check for your notes folder

These shell commands find title inconsistencies across a notes folder in one pass. Run them from your notes root. They are diagnostic, not corrective — each one shows you which files have a problem and leaves the fix to you. A lint run with markdownlint handles the same ground with better error messages.

# 1. Files with no H1 and no front-matter title line
grep -rL "^# " *.md | xargs grep -L "^title:" 2>/dev/null

# 2. Files where the H1 text does not match the filename
for f in *.md; do
  h1=$(grep -m1 "^# " "$f" | sed 's/^# //')
  base="${f%.md}"
  [ "$h1" != "$base" ] && echo "MISMATCH: $f — H1: '$h1'"
done

# 3. Files with both a front-matter title and a body H1 (potential MD025 violation)
awk 'FNR==1{hasfm=0;infront=0} /^---/{infront=!infront} infront && /^title:/{hasfm=1} !infront && /^# / && hasfm{print FILENAME; hasfm=0}' *.md

For a complete lint run against MD025 and MD041, markdownlint --config .markdownlint.json '**/*.md' catches both violations in one pass with no custom configuration required.67


Frequently Asked Questions

Should my Obsidian notes have a # H1 if the filename is already the title?

Only if the note ever leaves Obsidian. Inside the app, the inline title (from the filename) and the body H1 are two separate things — you see both, which is redundant. If the note is published to a static site, linted, or converted with Pandoc, the H1 is what most downstream tools read first. Keep one H1 that matches the filename; disable the Obsidian inline title in Settings → Appearance if the duplication bothers you.1

Does markdownlint require an H1 if I have a front-matter title?

No. MD041 checks for an H1 on the first line but passes silently when front matter contains a title: property.6 You do not need both. With a front-matter title in place, MD041 will not flag a missing body H1, and MD025 will not flag you for having only the front-matter one — it already counts as the document's single title.

Can I have both a front-matter title: and a body # H1 in the same file?

Under markdownlint's default configuration, no — MD025 treats the front-matter title: as the document's one H1, so a body H1 is a violation.7 Under Pandoc with --shift-heading-level-by=-1, a body H1 alongside a front-matter title causes the title to appear twice in the rendered output with no warning.8 If your toolchain genuinely needs both (some Docusaurus layouts do), set front_matter_title: "" in your .markdownlint.json to disable the MD025 check for that directory.

How does MkDocs decide what to show as the page title?

MkDocs checks four places in order: an explicit nav entry, front-matter title:, the first H1 body heading, and the filename.2 It stops at the first match. The H1 is only read if it is the very first block element in the body — an H1 preceded by a blank line does not count and MkDocs falls through to the filename instead.3

How does Hugo find the title of a file-backed page?

For any file-backed page, Hugo reads only the front-matter title: key.9 It does not fall back to the H1 or the filename. If front matter is absent or the title: key is missing, Hugo uses the section name or the site title — not the H1. This is different from every other tool in the table and is the most common source of unexpectedly blank or wrong titles in Hugo-published note vaults.

What happens if I run Pandoc on a file that has both a front-matter title and a body H1?

Without --shift-heading-level-by=-1, the H1 stays a body heading and the front-matter title controls the document <title> — no duplication. With the shift flag, the H1 is promoted to a second document title and both appear in the output as separate H1 elements with no warning.8 If you use the shift flag in a pipeline, use front-matter titles exclusively and omit the body H1, or strip it before converting.

Is there a fast way to find all title mismatches across a large notes folder?

The three-line script above finds the main patterns. For lint violations specifically, running markdownlint '**/*.md' with default config catches MD025 and MD041 in one pass.67 For large vaults, fd --extension md | xargs grep -L '^# ' finds every file without an H1 faster than the recursive grep.


The title you write at the top of a note is a promise — to you, and to every tool that will ever open that file. Write it once, put it first, keep it consistent with the filename. The portability of the file depends on it.


MNMNOTE keeps your notes as open Markdown files on your own device — the same files a linter, a static-site generator, or a converter reads directly, without export, without conversion, without lock-in. mnmnote.com


References


Footnotes

  1. Obsidian, changelog/2022-10-13-desktop-v1.0.0, accessed 2026-10-14. https://obsidian.md/changelog/2022-10-13-desktop-v1.0.0/ ↩ ↩2 ↩3

  2. MkDocs, "Writing Your Docs," writing-your-docs.md, pinned commit 2862536, accessed 2026-10-14. https://raw.githubusercontent.com/mkdocs/mkdocs/2862536793b3c67d9d83c33e0dd6d50a791928f8/docs/user-guide/writing-your-docs.md ↩ ↩2 ↩3 ↩4

  3. MkDocs, mkdocs/structure/pages.py, pinned commit 2862536, accessed 2026-10-14. https://raw.githubusercontent.com/mkdocs/mkdocs/2862536793b3c67d9d83c33e0dd6d50a791928f8/mkdocs/structure/pages.py ↩ ↩2 ↩3

  4. GitHub Docs, "About GitHub Pages and Jekyll," about-github-pages-and-jekyll.md, pinned commit d67ced7, accessed 2026-10-14. https://raw.githubusercontent.com/github/docs/d67ced7268844cdf7d856f4eb0b9b2018406da29/content/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll.md ↩

  5. Ben Balter, jekyll-titles-from-headings README, pinned commit 457264d, accessed 2026-10-14. https://raw.githubusercontent.com/benbalter/jekyll-titles-from-headings/457264d4c3a46766999ceea174b2b28a5b323be4/README.md ↩ ↩2 ↩3

  6. David Anson, markdownlint, doc/md041.md, pinned commit 3f1f479, accessed 2026-10-14. https://raw.githubusercontent.com/DavidAnson/markdownlint/3f1f479322e863a53e56c94b01266b9785cd3bfd/doc/md041.md ↩ ↩2 ↩3 ↩4

  7. David Anson, markdownlint, doc/md025.md, pinned commit 3f1f479, accessed 2026-10-14. https://raw.githubusercontent.com/DavidAnson/markdownlint/3f1f479322e863a53e56c94b01266b9785cd3bfd/doc/md025.md ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  8. John MacFarlane, Pandoc MANUAL.txt, pinned commit 8727b74, accessed 2026-10-14. https://raw.githubusercontent.com/jgm/pandoc/8727b74a1c888632b3fc0082600e72bb26eb60ef/MANUAL.txt ↩ ↩2 ↩3 ↩4

  9. Hugo, hugoDocs/methods/page/Title.md + hugolib/page__meta.go, pinned commits b3da63b / 00fe8db, accessed 2026-10-14. https://raw.githubusercontent.com/gohugoio/hugoDocs/b3da63b4ea9ad7f372c50e6db6fb1573e19c832a/content/en/methods/page/Title.md ↩ ↩2 ↩3

  10. Facebook / Meta, Docusaurus plugin-content-docs.mdx, pinned commit c245217, accessed 2026-10-14. https://raw.githubusercontent.com/facebook/docusaurus/c245217563f6491fdb79bf5ac91bfa16536e5de9/website/docs/api/plugins/plugin-content-docs.mdx ↩ ↩2

  11. MNMNOTE, "Navigate a Long Note by Its Outline (No App Feature Needed)." https://blog.mnmnote.com/posts/navigate-a-long-note-by-its-outline ↩