Feature Request
EmDash auto-generates BlogPosting JSON-LD via buildBlogPostingJsonLd() in src/page/jsonld.ts. This is great — it prevents XSS bugs from hand-rolled serialization and ensures every article page has structured data.
However, the generated schema is missing several fields that Google recommends for Article/BlogPosting rich results. This forces developers to add a second, manual BlogPosting block with the missing fields — creating duplicate JSON-LD blocks on every article page.
Currently generated
{
"@type": "BlogPosting",
"headline": "...",
"description": "...",
"image": "...",
"url": "...",
"datePublished": "...",
"dateModified": "...",
"author": { "@type": "Person", "name": "..." },
"publisher": { "@type": "Organization", "name": "..." },
"mainEntityOfPage": { "@type": "WebPage", "@id": "..." }
}
Missing fields (recommended by Google)
| Field |
Why it matters |
@id |
Links this entity to other schema blocks on the page (e.g., https://example.com/blog/post-slug) |
inLanguage |
Required for multilingual sites, helpful for AI citation systems |
articleSection |
Maps to post categories — improves topical signals |
author.@id |
Links to a Person entity defined elsewhere on the site |
author.url |
Author profile page URL |
publisher.@id |
Links to Organization entity |
publisher.logo |
Required by Google for publisher rich results (ImageObject with url) |
Proposal
Extend buildBlogPostingJsonLd() and PublicPageContext to support these fields. Possible approach:
- Add
@id — derive from page.canonical (already available)
- Add
inLanguage — derive from page.locale (already available)
- Add
articleSection — new optional field in articleMeta or PublicPageContext
- Extend
author — allow articleMeta.author to be an object { name, url, id } instead of just a string
- Extend
publisher — allow siteName to include logo URL, or add a publisherLogo field
This way the auto-generated schema would be rich enough that developers don't need to add their own BlogPosting block, eliminating duplicates.
Current workaround
We add a manual <script type="application/ld+json"> with a complete BlogPosting in our [slug].astro template. This works but creates two BlogPosting blocks per page — the EmDash one (id: "primary") and ours (raw script tag). Google handles it but it's noisy.
Related
- The same approach could enrich
buildWebSiteJsonLd() with @id, description, inLanguage, publisher, and potentialAction (SearchAction) — currently it only has name and url.
Feature Request
EmDash auto-generates BlogPosting JSON-LD via
buildBlogPostingJsonLd()insrc/page/jsonld.ts. This is great — it prevents XSS bugs from hand-rolled serialization and ensures every article page has structured data.However, the generated schema is missing several fields that Google recommends for Article/BlogPosting rich results. This forces developers to add a second, manual BlogPosting block with the missing fields — creating duplicate JSON-LD blocks on every article page.
Currently generated
{ "@type": "BlogPosting", "headline": "...", "description": "...", "image": "...", "url": "...", "datePublished": "...", "dateModified": "...", "author": { "@type": "Person", "name": "..." }, "publisher": { "@type": "Organization", "name": "..." }, "mainEntityOfPage": { "@type": "WebPage", "@id": "..." } }Missing fields (recommended by Google)
@idhttps://example.com/blog/post-slug)inLanguagearticleSectionauthor.@idauthor.urlpublisher.@idpublisher.logoImageObjectwithurl)Proposal
Extend
buildBlogPostingJsonLd()andPublicPageContextto support these fields. Possible approach:@id— derive frompage.canonical(already available)inLanguage— derive frompage.locale(already available)articleSection— new optional field inarticleMetaorPublicPageContextauthor— allowarticleMeta.authorto be an object{ name, url, id }instead of just a stringpublisher— allowsiteNameto include logo URL, or add apublisherLogofieldThis way the auto-generated schema would be rich enough that developers don't need to add their own BlogPosting block, eliminating duplicates.
Current workaround
We add a manual
<script type="application/ld+json">with a complete BlogPosting in our[slug].astrotemplate. This works but creates two BlogPosting blocks per page — the EmDash one (id: "primary") and ours (raw script tag). Google handles it but it's noisy.Related
buildWebSiteJsonLd()with@id,description,inLanguage,publisher, andpotentialAction(SearchAction) — currently it only hasnameandurl.