WritedocsWritedocs

SEO and sitemap

Three related pieces of config live together: the site’s own deployed domain, a sitemap.xml generated automatically at build time, and meta tags (Open Graph, Twitter card, canonical URL) — site-wide defaults in writedocs.json, overridable per page in frontmatter.

domain

{
  "domain": "docs.example.com"
}

The scheme is optional — "docs.example.com" and "https://docs.example.com" both work and resolve to the same https:// origin. This one field turns on everything below:

  • sitemap.xmlwritedocs build only generates one when domain is set. A relative-URL sitemap isn’t meaningful, so a site with no domain configured just doesn’t get one (and a writedocs] No writedocs.json "domain" set - skipping sitemap.xml generation. line is logged during the build, not an error).
  • Canonical URLs — every page gets <link rel="canonical" href="https://docs.example.com/your-page/">.
  • Absolute og:url/og:image/twitter:image — social crawlers generally require absolute URLs, not page-relative ones.

Leave domain unset for local-only builds, fixtures, or a site that hasn’t picked a deployment URL yet — everything else in this page still works, just without absolute URLs or a sitemap.

domain is metadata only — it doesn’t configure hosting, DNS, or routing by itself. It just tells Writedocs what URL the site will be reachable at, so it can generate correct absolute links.

seo — site-wide defaults

{
  "seo": {
    "ogImage": "/social-card.png",
    "ogType": "website",
    "twitterCard": "summary_large_image",
    "keywords": ["docs", "api", "developer-tools"],
    "noindex": false
  }
}
ogImagestring
ogTypestringdefault: "website"
twitterCard"summary" | "summary_large_image"default: "summary_large_image" if ogImage is set, otherwise "summary"
keywordsstring array
noindexbooleandefault: false

ogImage can be a relative path (resolved against domain into an absolute URL) or an already-absolute https:// URL. og:title/og:description/twitter:title/twitter:description aren’t separately configurable — they’re always the page’s own title/description.

Per-page overrides

A page’s frontmatter can set its own seo (and its own description), overriding the site-wide default field by field — a page only needs to set what it wants to change, everything else still falls back to writedocs.json.

---
title: Enterprise SSO
description: How SSO works for Enterprise plan customers.
seo:
  ogImage: /social/enterprise-sso.png
  keywords:
    - sso
    - enterprise
    - authentication
---

seo.noindex

---
title: Internal migration notes
seo:
  noindex: true
---

Renders <meta name="robots" content="noindex, nofollow"> on that page and excludes it from sitemap.xml — the page still builds and is normally linkable/reachable, it’s just not something you want search engines to index or crawl into as canonical content (a draft, an internal-only page kept in the same nav for convenience, a duplicate of content that lives canonically elsewhere).

See docs.json-examples/00-kitchen-sink/ in the Writedocs repo for a complete, buildable example covering all of this — site-wide defaults, about.mdx overriding several fields, and docs/core/2025-09/guides/overview.mdx as a noindex page.