From 01dec193ad73f16c90f96b5bcc2cd6f98ba8ea85 Mon Sep 17 00:00:00 2001 From: swissky <30409887+swissky@users.noreply.github.com> Date: Thu, 9 Jul 2026 21:33:29 +0200 Subject: [PATCH 1/2] docs: document rendering SEO panel data via getSeoMeta (#1518) getSeoMeta/getContentSeo were undocumented outside the in-repo skill references, so templates that hand-roll meta tags silently bypass the whole SEO panel, including the noindex toggle. Adds a section to the querying guide with a full example and a caution about the footgun. --- .../content/docs/guides/querying-content.mdx | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/src/content/docs/guides/querying-content.mdx b/docs/src/content/docs/guides/querying-content.mdx index 03718063d4..a82af20c10 100644 --- a/docs/src/content/docs/guides/querying-content.mdx +++ b/docs/src/content/docs/guides/querying-content.mdx @@ -196,6 +196,40 @@ interface ContentEntry { The `data` object within `entry` contains all fields defined for the content type. The `edit` proxy provides visual editing annotations (see below). +## Rendering SEO Panel Data + +For collections with `supports: ["seo"]`, editors can set an SEO title, meta description, OG image, canonical URL, and a "hide from search engines" (noindex) toggle in the admin's SEO panel. That data is delivered on the entry as `entry.data.seo` — but it only reaches the rendered page if your template emits it. Use `getSeoMeta` to resolve the panel fields (with sensible fallbacks to `data.title` / `data.excerpt`) into ready-to-render meta tags: + +```astro title="src/pages/posts/[...slug].astro" +--- +import { getEmDashEntry, getSeoMeta } from "emdash"; + +const { entry } = await getEmDashEntry("posts", Astro.params.slug); +if (!entry) return Astro.redirect("/404"); + +const seo = getSeoMeta(entry, { + siteTitle: "My Site", + siteUrl: "https://example.com", + path: Astro.url.pathname, +}); +--- + + + {seo.title} + {seo.description && } + {seo.ogImage && } + {seo.canonical && } + {seo.robots && } + +``` + + + ## Preview Mode EmDash handles preview automatically via middleware. When a URL contains a valid `_preview` token, the middleware verifies it and sets up the request context. Your query functions then serve draft content without any special parameters: From 9db918333cbfe235190bc39d1173449d0e331ca6 Mon Sep 17 00:00:00 2001 From: swissky <30409887+swissky@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:24:07 +0200 Subject: [PATCH 2/2] docs: check the error result in the getSeoMeta example --- docs/src/content/docs/guides/querying-content.mdx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/querying-content.mdx b/docs/src/content/docs/guides/querying-content.mdx index a82af20c10..8338f61935 100644 --- a/docs/src/content/docs/guides/querying-content.mdx +++ b/docs/src/content/docs/guides/querying-content.mdx @@ -204,7 +204,10 @@ For collections with `supports: ["seo"]`, editors can set an SEO title, meta des --- import { getEmDashEntry, getSeoMeta } from "emdash"; -const { entry } = await getEmDashEntry("posts", Astro.params.slug); +const { entry, error } = await getEmDashEntry("posts", Astro.params.slug); +if (error) { + return new Response("Server error", { status: 500 }); +} if (!entry) return Astro.redirect("/404"); const seo = getSeoMeta(entry, {