diff --git a/docs/unreleased.md b/docs/unreleased.md
new file mode 100644
index 0000000..ecafdfd
--- /dev/null
+++ b/docs/unreleased.md
@@ -0,0 +1,10 @@
+# Unreleased changes
+
+Changes on `development` not yet merged to `main`.
+
+## Fixes
+
+- **`mdcms build` now patches `
` in `index.html` with `sitename` from `config.yml`.**
+ Previously the HTML `` tag was a hardcoded blank (or "MD-CMS" in older templates),
+ so link previews in apps like WhatsApp showed the wrong name. After each build the tag
+ reflects the configured site name, which crawlers and preview scrapers read directly.
diff --git a/mdcms.py b/mdcms.py
index 7050c9e..6ca43cd 100644
--- a/mdcms.py
+++ b/mdcms.py
@@ -412,6 +412,19 @@ def validate_assets(site_path: Path, cfg: dict) -> list:
# ─── Core build logic ─────────────────────────────────────────
+_TITLE_RE = re.compile(r"[^<]*")
+
+
+def _patch_html_title(site_path: Path, sitename: str) -> None:
+ index = site_path / "index.html"
+ if not index.exists():
+ return
+ html = index.read_text(encoding="utf-8")
+ new_html = _TITLE_RE.sub(f"{sitename}", html, count=1)
+ if new_html != html:
+ index.write_text(new_html, encoding="utf-8")
+
+
def run_build(site_path: Path):
"""Scan pages/ and posts/, write nav.yml and search.json. Raises ClickException on failure."""
if not site_path.is_dir():
@@ -491,6 +504,8 @@ def run_build(site_path: Path):
)
click.echo(f" Wrote search.json ({len(live_pages) + len(post_records)} entries)")
+ _patch_html_title(site_path, cfg.get("sitename", ""))
+
pwa_enabled = str(cfg.get("pwa", "no")).lower() in ("yes", "true")
if pwa_enabled:
generate_pwa(site_path, cfg)