# 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.