# Template Design: Handling the Markdown H1 / Front Matter Title Conflict
## The Problem
Standard markdown convention — Obsidian, agent-written files, generic `.md` — opens
with a level-1 heading as the document title:
```markdown
# My Note Title
Body text...
```
Hugo templates also render a title from front matter:
```html
{{ .Title }}
```
When both exist, the page gets two `` elements: one from the template,
one from the rendered markdown content. The content one also carries an
auto-generated `id` attribute from Hugo's heading anchor renderer.
## The Two Template Contracts
**Default (`_default/single.html`)** — bare markdown, minimal or no front matter.
The `# Title` in content IS the h1. The template header renders only metadata
(type, date, author, tags). No title rendered from front matter.
**Vault (`vault/single.html`)** — enriched front matter (`title`, `type`, `date`,
`author`, `tags`). Front matter `title` is authoritative. The `# Title` in content
is still present (markdown convention) but must be suppressed.
## The Fix: Engine-Agnostic Regex Strip
When a template owns the title (renders `{{ .Title }}
` from front matter),
strip the first h1 from the rendered content before outputting it.
**Hugo:**
```
{{ replaceRE "]*>.*?
" "" .Content 1 | safeHTML }}
```
**Jinja2 / Flask:**
```python
import re
content = re.sub(r']*>.*?
', '', content, count=1, flags=re.DOTALL)
```
**Nunjucks / Liquid / any engine:** equivalent string replace on the rendered HTML.
This is a string operation on already-rendered HTML, not a template-engine concept.
It ports to any engine without modification.
## Why Not Other Approaches
- **Author convention** (don't write `# Title` in vault files): breaks compatibility
with the entire markdown ecosystem.
- **Hugo render hooks** (`layouts/vault/_markup/render-heading.html`): Hugo-specific,
not portable.
- **CSS `display: none`**: h1 still exists in DOM — screen readers read it,
search engines index it. Semantically wrong.
## Engine-Agnostic Principle
ASW templates are prototyped in Hugo but must be portable to Flask/Jinja2 or
any other engine. Template logic should express *what*, not *how*:
- What: "strip h1 from content if front matter title is present"
- How: engine-specific implementation of the same string operation
Hugo-specific features (render hooks, shortcodes) are acceptable as prototyping
tools but should not become load-bearing parts of the template design.