Skip to content

Releases: jdevalk/emdash-plugin-seo

v0.11.0

21 Apr 15:47

Choose a tag to compare

Changed

  • peerDependencies.emdash bumped to ^0.6.0. Picks up eager taxonomy-term hydration on getEmDashEntry results (emdash PR #626), plus the toolbar portableText fix (#685) and several cold-start / D1 replica performance improvements.

Added

  • Taxonomy keywords and section in Article schema. For content pages the plugin now calls getEmDashEntry to read the entry's eagerly-hydrated data.terms map (zero extra DB queries when the Astro template already fetched the entry in the same request). All assigned taxonomy terms are joined into the keywords field of the BlogPosting node. Terms from any taxonomy whose name starts with categor are additionally mapped to articleSection.

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