Skip to content

Releases: jdevalk/emdash-plugin-seo

v0.10.0 — content-enumeration features now work

14 Apr 17:08

Choose a tag to compare

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:

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-error on the NLWeb rel contribution and per-call type casts in llms.ts / schema/endpoints.ts.
  • The "known broken" README warning.

Full Changelog: v0.9.0...v0.10.0

v0.9.0 — NLWeb link tag

13 Apr 16:45

Choose a tag to compare

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

13 Apr 13:44

Choose a tag to compare

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/map route), 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-suggester for later audit.

  • Exported rankCandidates() and scoreSlugMatch() from src/fuzzy.ts — reusable for the upcoming automatic-on-404 flow once the notfound hook lands upstream.

Companion upstream work

  • emdash-cms/emdash#525 — proposed notfound hook 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)

13 Apr 13:23

Choose a tag to compare

Added

  • Schema map (experimental). New public plugin route schema/map returning the list of every published URL backed by schema markup ({ items: [{ url, collection, updatedAt }] }). Wire it to /schemamap.xml at 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 nlweb to the page:metadata link-rel allowlist (unblocks a future NLWeb <link> tag contribution from this plugin).
  • emdash-cms/emdash#524 — proposed page:robots hook (will let this plugin emit a Schemamap: directive in robots.txt).
  • emdash-cms/emdash#525 — proposed notfound hook (foundation for a FuzzyRedirect feature).
  • emdash-cms/emdash#526 — proposed content:validate hook (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)

13 Apr 10:10

Choose a tag to compare

Added

  • llms.txt (experimental). Generates a small-form llms.txt index of all published content across every collection with a urlPattern, grouped by collection label. Exposed on the plugin route llms/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 plain llms.txt is implemented; the llms-full.txt variant is out of scope.
  • buildLlmsTxt() exported for consumers who want to assemble the body from getEmDashCollection() results with custom sectioning or ordering.

v0.5.0 — IndexNow

12 Apr 17:13

Choose a tag to compare

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

09 Apr 20:53

Choose a tag to compare

Dependency-range bump for transitive dedup.

Changes

  • Bump @jdevalk/seo-graph-core range from ^0.2.0 to ^0.3.0
  • Bump @jdevalk/astro-seo-graph range from ^0.2.1 to ^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

09 Apr 19:46

Choose a tag to compare

Dependency-bump patch release.

Changes

  • Bump @jdevalk/seo-graph-core range from ^0.1.0 to ^0.2.0 to match what @jdevalk/astro-seo-graph@^0.2.1 pulls in transitively. Avoids duplicate seo-graph-core copies in consumer node_modules.

Context

@jdevalk/seo-graph-core@0.2.0 shipped two additive API improvements:

  • buildOrganization gained a generic type parameter (<T extends Organization = Organization>) with OrganizationInput.extra typed as Partial<T> — flows schema-dts subtype autocomplete into the escape-hatch field.
  • WebPageInput.breadcrumb became 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

09 Apr 19:25

Choose a tag to compare

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-cafr-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 pure buildAlternateLinks helper. 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

09 Apr 13:05

Choose a tag to compare

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.ts now uses assembleGraph from 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 GraphEntity type.
  • 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.