Skip to content

fix(core): RecentPosts widget links by slug and supports urlTemplate (#1332)#1899

Open
swissky wants to merge 2 commits into
emdash-cms:mainfrom
swissky:fix/recent-posts-url
Open

fix(core): RecentPosts widget links by slug and supports urlTemplate (#1332)#1899
swissky wants to merge 2 commits into
emdash-cms:mainfrom
swissky:fix/recent-posts-url

Conversation

@swissky

@swissky swissky commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Addresses the remaining half of #1332. The LiveSearch half was already fixed by #1387 (routeMap templates); the core:recent-posts widget still hardcoded its link as /posts/${post.id} — and post.id is the ULID, not the slug, so the default link 404s against the standard /posts/[slug] routes even without catch-all routing.

Changes:

  • The widget now builds links through the existing buildLiveSearchResultUrl helper: default stays /posts/{slug} (id fallback when a row has no slug), same behavior LiveSearch has.
  • New optional urlTemplate prop (passed via the widget's componentProps, e.g. "/blog/:slug" or "/:slug" for catch-all sites) using the same :collection / :id / :slug / :path tokens as LiveSearch's routeMap — one template vocabulary for both components, per the issue's suggestion.
  • Widgets guide updated with the new prop.

No new helper, no new tests needed: the token interpolation and slug/id fallback are already covered by tests/unit/components/live-search-routing.test.ts; the widget change is a thin wrapper over the tested helper.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable) — n/a, thin wrapper over the already-tested buildLiveSearchResultUrl
  • User-visible strings in the admin UI are wrapped for translation (if applicable) — n/a
  • I have added a changeset (if this PR changes a published package)
  • New features link to an approved Discussion — the urlTemplate prop follows the maintainer-merged routeMap pattern from [codex] Add LiveSearch route templates #1387 for the sibling component

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Cursor + Claude (Fable 5)

Screenshots / test output

n/a — link-shape change; before /posts/01JXYZ… (404), after /posts/my-post-slug.

…mdash-cms#1332)

The widget hardcoded /posts/{post.id} — a ULID, which 404s against the
default slug-based routes. Links now go through the shared
buildLiveSearchResultUrl helper (slug with id fallback) and accept an
optional urlTemplate prop with the same :collection/:id/:slug/:path
tokens as LiveSearch routeMap, covering catch-all routing setups.
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4a35b0d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@1899

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@1899

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@1899

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@1899

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@1899

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@1899

emdash

npm i https://pkg.pr.new/emdash@1899

create-emdash

npm i https://pkg.pr.new/create-emdash@1899

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@1899

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@1899

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@1899

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@1899

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@1899

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@1899

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@1899

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@1899

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@1899

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@1899

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@1899

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@1899

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@1899

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@1899

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@1899

commit: 4a35b0d

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR takes the right approach to #1332: it fixes the core:recent-posts widget's hardcoded /posts/${id} link by routing it through the already-tested buildLiveSearchResultUrl helper, and it reuses the same :slug / :id / :path / :collection token vocabulary that LiveSearch's routeMap already uses. That's a clean, minimal change that matches the sibling component.

I read the widget code, the helper implementation and its unit tests, the widget registry (packages/core/src/widgets/components.ts), the admin widget form (packages/admin/src/components/Widgets.tsx), and the updated docs/changeset.

Headline finding: the new optional urlTemplate prop is declared on the Astro component but not added to the coreWidgetComponents registry in packages/core/src/widgets/components.ts. The admin UI renders prop fields from that registry (ComponentPropField iterates selectedComponent.props), so the prop is currently invisible to admin users. You also need to update the should return core widget components test in packages/core/tests/unit/widgets/widgets.test.ts to assert the prop exists.

Otherwise the change is solid: the helper coverage is already in place, the default /posts/{slug} behavior matches LiveSearch, and the changeset is appropriate.

Comment on lines 7 to 8
showThumbnails?: boolean;
showDate?: boolean;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[needs fixing] The new urlTemplate prop is declared on the component, but it is not registered in packages/core/src/widgets/components.ts under the core:recent-posts coreWidgetComponents entry. The admin UI builds the prop form from that registry (packages/admin/src/components/Widgets.tsx iterates selectedComponent.props), so this prop is currently invisible to admin users.

Add the prop definition there, e.g.:

urlTemplate: {
  type: "string",
  label: "URL template",
},

Also update the should return core widget components test in packages/core/tests/unit/widgets/widgets.test.ts to assert that recentPosts?.props has the new urlTemplate property.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4a35b0durlTemplate is now registered in coreWidgetComponents (type string, label "URL template (e.g. /blog/:slug)") so the admin prop form renders it, and the should return core widget components test asserts the new prop.

@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond and removed review/needs-review No maintainer or bot review yet labels Jul 10, 2026
The admin widget form builds its inputs from coreWidgetComponents, so
the prop was invisible to admin users without this registration.
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review and removed review/awaiting-author Reviewed; waiting on the author to respond labels Jul 10, 2026
@swissky swissky added the bot:review Trigger an emdashbot code review on this PR label Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core area/docs bot:review Trigger an emdashbot code review on this PR review/needs-rereview Author pushed changes since the last review size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant