Releases: jdevalk/emdash-plugin-seo
v0.10.0 — content-enumeration features now work
Requires emdash@^0.5.0
peerDependencies.emdash is now pinned to ^0.5.0. The three upstream PRs this plugin's content-enumeration features were waiting on all ship in that release:
- emdash-cms/emdash#536 —
slug/status/publishedAtonContentItem - emdash-cms/emdash#539 —
localeonContentItem - emdash-cms/emdash#540 —
where: { status?, locale? }onContentListOptions
Upgrade EmDash to ^0.5.0 before upgrading this plugin, or the peer check will complain.
Fixed
llms.txt(v0.6.0) now returns a real body with every published entry, grouped by collection. Previously returned an empty body on every real site because the iteration was reading stripped fields.- Schema map (v0.7.0) now returns the full list of published URLs. Previously returned
{items: []}for the same reason. - Fuzzy Redirects (v0.8.0) candidate list is now populated, so the suggester actually suggests. The other half (capturing original 404 URLs rather than the rewritten
/404) is still tracked in emdash-cms/emdash#525.
Removed
- Transient
@ts-expect-erroron the NLWebrelcontribution and per-call type casts inllms.ts/schema/endpoints.ts. - The "known broken" README warning.
Full Changelog: v0.9.0...v0.10.0
v0.9.0 — NLWeb link tag
Added
- NLWeb
<link>tag. When the NLWeb endpoint URL setting (new Agent discovery admin section) is populated, every rendered page carries<link rel=\"nlweb\" href=\"…\">advertising the site's conversational endpoint for agent discovery.
Requirements
Needs the EmDash release that contains emdash-cms/emdash#523 (merged upstream). On older EmDash versions the sandbox allowlist rejects the rel value and the contribution is silently dropped.
The contribution site carries a transient @ts-expect-error against the currently-published emdash types — it auto-unblocks once the new emdash version hits npm.
Status of other experimental features
Still blocked on upstream — see README warning table. No change since v0.8.0 for llms.txt, schema/map, or Fuzzy Redirects. Tracked at #530 (ContentItem missing slug/status/locale) and #525 (404 middleware captures wrong URL).
Full Changelog: v0.8.0...v0.9.0
v0.8.0 — Fuzzy Redirects
Added
-
Fuzzy Redirects admin tool. New admin page at SEO → Fuzzy Redirects that turns the core 404 log into a prioritized redirect work queue. For every logged 404, the tool fetches the current list of published URLs (via the plugin's own
schema/maproute), ranks live URLs against the missing path by path similarity, and lets you one-click create a 301 redirect for the chosen target.Scoring combines three signals:
- Levenshtein distance on the full normalized path (catches typos in inbound links).
- Token overlap (Jaccard index) on path segments (catches reordering and punctuation drift).
- Tokenized last-segment match bonus (catches slugs that survived a prefix rewrite like
/blog/old/hello→/posts/hello).
A minimum-score slider tunes aggressiveness. Created redirects are grouped under
seo-fuzzy-suggesterfor later audit. -
Exported
rankCandidates()andscoreSlugMatch()fromsrc/fuzzy.ts— reusable for the upcoming automatic-on-404 flow once thenotfoundhook lands upstream.
Companion upstream work
- emdash-cms/emdash#525 — proposed
notfoundhook that will let this tool run automatically on every 404 instead of requiring manual admin review. Same matching logic, automatic trigger.
Full Changelog: v0.7.0...v0.8.0
v0.7.0 — Schema map (experimental)
Added
- Schema map (experimental). New public plugin route
schema/mapreturning the list of every published URL backed by schema markup ({ items: [{ url, collection, updatedAt }] }). Wire it to/schemamap.xmlat your site root with the Astro snippet in the README so agents and crawlers can enumerate structured-data URLs without scraping HTML.
Per-URL schema endpoints (/schema/<slug>.json) are deferred pending an upstream helper for building page contexts from plugin routes — see emdash-cms/emdash#527.
Companion upstream work
- emdash-cms/emdash#523 — adds
nlwebto thepage:metadatalink-rel allowlist (unblocks a future NLWeb<link>tag contribution from this plugin). - emdash-cms/emdash#524 — proposed
page:robotshook (will let this plugin emit aSchemamap:directive inrobots.txt). - emdash-cms/emdash#525 — proposed
notfoundhook (foundation for a FuzzyRedirect feature). - emdash-cms/emdash#526 — proposed
content:validatehook (foundation for H1 / duplicate-title / schema-shape validation at save time).
Full Changelog: v0.6.0...v0.7.0
v0.6.0 — llms.txt (experimental)
Added
- llms.txt (experimental). Generates a small-form
llms.txtindex of all published content across every collection with aurlPattern, grouped by collection label. Exposed on the plugin routellms/txt; serve it from Astro by proxying that route at/llms.txt. Enabled by default — flip the llms.txt (experimental) toggle to disable. Only the plainllms.txtis implemented; thellms-full.txtvariant is out of scope. buildLlmsTxt()exported for consumers who want to assemble the body fromgetEmDashCollection()results with custom sectioning or ordering.
v0.5.0 — IndexNow
What's new
- IndexNow submission — on publish/unpublish transitions, the canonical URL of the affected content item is submitted to IndexNow so Bing, Yandex, Seznam, Naver, and Yep recrawl immediately. Opt-in via a single toggle in the SEO settings UI; a 32-character hex key is generated and persisted in plugin KV on first use.
Setup
Wire the IndexNow key-verification file into your Astro site using createIndexNowKeyRoute from @jdevalk/astro-seo-graph — see the README for details.
Dependency updates
- Requires
@jdevalk/seo-graph-core^0.6.0 - Requires
@jdevalk/astro-seo-graph^0.7.0
v0.4.2
Dependency-range bump for transitive dedup.
Changes
- Bump
@jdevalk/seo-graph-corerange from^0.2.0to^0.3.0 - Bump
@jdevalk/astro-seo-graphrange from^0.2.1to^0.2.4
Why
@jdevalk/astro-seo-graph@0.2.4 pins @jdevalk/seo-graph-core@0.3.0 as a direct dep. The plugin's previous ^0.2.0 range excluded 0.3.0 (pre-1.0 caret semver: ^0.2.0 means >=0.2.0 <0.3.0), so consumers ended up with two parallel copies of seo-graph-core in their node_modules — one for astro-seo-graph, one for this plugin. Widening the range to ^0.3.0 lets both resolutions converge on a single installed copy.
No behavioural change
seo-graph-core@0.3.0 ships three additive improvements (no inLanguage default on piece builders, optional WebPageInput.breadcrumb, generic type parameter on buildOrganization) that this plugin doesn't exercise directly. The plugin's rendered JSON-LD output is unchanged.
See CHANGELOG.md for details.
🤖 Generated with Claude Code
v0.4.1
Dependency-bump patch release.
Changes
- Bump
@jdevalk/seo-graph-corerange from^0.1.0to^0.2.0to match what@jdevalk/astro-seo-graph@^0.2.1pulls in transitively. Avoids duplicateseo-graph-corecopies in consumernode_modules.
Context
@jdevalk/seo-graph-core@0.2.0 shipped two additive API improvements:
buildOrganizationgained a generic type parameter (<T extends Organization = Organization>) withOrganizationInput.extratyped asPartial<T>— flows schema-dts subtype autocomplete into the escape-hatch field.WebPageInput.breadcrumbbecame optional.
This plugin doesn't call those piece builders directly, so there's no functional change. The bump is install-footprint hygiene.
See CHANGELOG.md for details.
🤖 Generated with Claude Code
v0.4.0
See CHANGELOG.md for full release notes.
Highlights
hreflang alternates for multilingual EmDash sites. When Astro i18n is configured and content entries are linked via translation_group, the plugin now emits one <link rel="alternate" hreflang="…" href="…"> per published sibling plus an automatically-resolved x-default. URLs are built from each collection's urlPattern + locale prefix rules, matching canonical URLs. BCP 47 tags are normalized on output (fr-ca → fr-CA).
Zero cost on single-locale sites. Gated on isI18nEnabled() before any database call.
New dependency
@jdevalk/astro-seo-graph@^0.2.1— runtime dep for the purebuildAlternateLinkshelper. Pure TypeScript, no Astro runtime impact (Astro is a peer dep satisfied transitively through EmDash).
Dependency range updates
@jdevalk/seo-graph-core:^0.1.0-alpha.0→^0.1.0
Tests
30 new tests: 12 URL-construction tests covering locale-prefix rules and BCP 47 region tags, 18 hreflang adapter tests including a reciprocity invariant that verifies the same URL set is emitted regardless of which sibling is the "current" page.
🤖 Generated with Claude Code
v0.2.0 — share the graph envelope with @jdevalk/seo-graph-core
First release that shares infrastructure with the Astro side of the @jdevalk/seo-graph ecosystem. The JSON-LD envelope ({ @context, @graph } wrapping + first-wins @id deduplication) now comes from @jdevalk/seo-graph-core, which is also used by @jdevalk/astro-seo-graph on joost.blog. Two consumers, two very different runtimes (EmDash CMS vs Astro static site), one shared graph engine.
See CHANGELOG.md for the full notes.
Added
- Runtime dependency on
@jdevalk/seo-graph-core ^0.1.0-alpha.0.
Changed
src/schema/index.tsnow usesassembleGraphfrom the core package rather than manually constructing the envelope. JSON-LD output is byte-identical to 0.1.3 for existing pages.- Piece builder return types aligned with core's
GraphEntitytype. - Added a
.gitignore(the repo had none).
Notes
This is a minor bump rather than a patch because the new runtime dependency changes the plugin's install footprint. The per-page output is byte-identical to 0.1.3.