Document urlPattern collection property, and add route to catch new pages where missing in the templates#1099
Document urlPattern collection property, and add route to catch new pages where missing in the templates#1099dcardosods wants to merge 6 commits into
Conversation
|
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/blocks
@emdash-cms/cloudflare
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
|
|
||
| When set, this pattern is used in three places: | ||
|
|
||
| - **Public routing** — `resolveEmDashPath()` matches incoming request paths against all collection patterns and returns the matching entry. |
There was a problem hiding this comment.
This is potentially misleading. It's not used for routing in actual sites by default (they use the Astro router)
There was a problem hiding this comment.
Removed this point and rephrase the rest of the section.
There was a problem hiding this comment.
Pull request overview
This PR updates multiple templates and the docs to better support the urlPattern collection property, so admin preview / menu links / public routes align with the intended URL shape (notably for pages at /{slug} and projects at /work/{slug} in the portfolio template).
Changes:
- Document
urlPatternin the seed-files docs and collections concept docs (including how it affects routing, menus, previews, and auto-redirects). - Add
urlPatternto template seed files (starter, marketing, portfolio; including Cloudflare variants) and add missingsrc/pages/[slug].astroroutes forpagesin marketing + portfolio templates. - Update template
Base.astrolayouts to pass richer page context (notablycontent) intocreatePublicPageContext.
Reviewed changes
Copilot reviewed 16 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| templates/starter/seed/seed.json | Add urlPattern for pages to generate root-level page URLs. |
| templates/starter/emdash-env.d.ts | Update generated types (bylines + richer media shape). |
| templates/starter-cloudflare/seed/seed.json | Add urlPattern for pages (Cloudflare starter). |
| templates/starter-cloudflare/emdash-env.d.ts | Update generated types (Cloudflare starter). |
| templates/portfolio/src/pages/[slug].astro | New route to render pages at /{slug} in portfolio template. |
| templates/portfolio/src/layouts/Base.astro | Extend props and public page context wiring (content, canonical, etc.). |
| templates/portfolio/seed/seed.json | Add urlPattern for projects and pages to match template routes. |
| templates/portfolio/emdash-env.d.ts | Update generated types (featured_image shape). |
| templates/portfolio-cloudflare/src/pages/[slug].astro | New route to render pages at /{slug} (Cloudflare portfolio). |
| templates/portfolio-cloudflare/src/layouts/Base.astro | Same Base layout updates for Cloudflare portfolio. |
| templates/portfolio-cloudflare/seed/seed.json | Add urlPattern for projects and pages (Cloudflare portfolio). |
| templates/portfolio-cloudflare/emdash-env.d.ts | Update generated types (Cloudflare portfolio). |
| templates/marketing/src/pages/[slug].astro | New route to render pages at /{slug} in marketing template. |
| templates/marketing/src/layouts/Base.astro | Extend props and public page context wiring (content, canonical, etc.). |
| templates/marketing/seed/seed.json | Add urlPattern for pages to generate root-level page URLs. |
| templates/marketing-cloudflare/src/pages/[slug].astro | New route to render pages at /{slug} (Cloudflare marketing). |
| templates/marketing-cloudflare/src/layouts/Base.astro | Same Base layout updates for Cloudflare marketing. |
| templates/marketing-cloudflare/seed/seed.json | Add urlPattern for pages (Cloudflare marketing). |
| docs/src/content/docs/themes/seed-files.mdx | Document urlPattern in the seed collection property table. |
| docs/src/content/docs/concepts/collections.mdx | Add a new “URL patterns” section describing urlPattern behavior and usage. |
Comments suppressed due to low confidence (8)
templates/portfolio/src/layouts/Base.astro:23
fullTitlealways appendssiteTitletotitle, but some callers (e.g. pages built withgetSeoMeta) may pass a title that already includes the site title. That yields duplicated titles like "X | Studio — Studio". Consider using the same guard used in templates/blog/src/layouts/Base.astro (only append whentitledoesn’t already includesiteTitle).
This issue also appears on line 33 of the same file.
const { title, pageTitle, description, image, canonical, type = "website", content } = Astro.props;
const settings = await getSiteSettings();
const siteTitle = settings?.title || "Studio";
const fullTitle = title ? `${title} — ${siteTitle}` : siteTitle;
const siteDescription = settings?.tagline || "Design & Development";
templates/portfolio/src/layouts/Base.astro:38
createPublicPageContextreceivescanonicalstraight from props; when callers don’t pass it, EmDashHead won’t emit a canonical link/og:url. If the intent is to always have canonical URLs for these templates (previously this usedAstro.url.href), consider defaultingcanonicalto the current request URL (ideally origin+pathname without query) when no override is provided.
title: fullTitle,
pageTitle: pageTitle ?? title ?? siteTitle,
description: description || siteDescription,
canonical,
image,
content,
templates/marketing/src/layouts/Base.astro:22
fullTitlecurrently appendssiteTitleunconditionally whentitleis set. If a page passes a pre-composed SEO title that already includessiteTitle(e.g. fromgetSeoMeta), this produces a duplicated<title>like "X | Acme — Acme". Consider guarding against this the same way templates/blog/src/layouts/Base.astro does.
This issue also appears on line 40 of the same file.
const { title, pageTitle, description, image, canonical, content } = Astro.props;
const settings = await getSiteSettings();
const siteTitle = settings?.title || "Acme";
const fullTitle = title ? `${title} — ${siteTitle}` : siteTitle;
const siteDescription =
templates/marketing/src/layouts/Base.astro:50
createPublicPageContextnow receivescanonicalfrom props only. For pages that don’t pass a canonical override, EmDashHead won’t emit canonical/og:url. If canonical tags are desired by default for this template, consider falling back to the current request URL (preferably without query params) whencanonicalis not provided.
const pageCtx = createPublicPageContext({
Astro,
kind: content ? "content" : "custom",
pageType: "website",
title: fullTitle,
pageTitle: pageTitle ?? title ?? siteTitle,
description: description || siteDescription,
canonical,
image,
content,
siteName: siteTitle,
templates/portfolio-cloudflare/src/layouts/Base.astro:23
- Same title composition issue as the non-Cloudflare template:
fullTitleappendssiteTitleeven when the incomingtitlealready includes it (e.g. titles fromgetSeoMeta), producing duplicated<title>values. Consider adding a guard before appendingsiteTitle(see templates/blog/src/layouts/Base.astro).
This issue also appears on line 33 of the same file.
const { title, pageTitle, description, image, canonical, type = "website", content } = Astro.props;
const settings = await getSiteSettings();
const siteTitle = settings?.title || "Studio";
const fullTitle = title ? `${title} — ${siteTitle}` : siteTitle;
const siteDescription = settings?.tagline || "Design & Development";
templates/portfolio-cloudflare/src/layouts/Base.astro:38
- Same canonical handling as the non-Cloudflare template: if
canonicalisn’t passed in props, EmDashHead won’t emit canonical/og:url. If you want canonical tags by default, consider falling back to the current request URL (ideally origin+pathname) whencanonicalis not provided.
title: fullTitle,
pageTitle: pageTitle ?? title ?? siteTitle,
description: description || siteDescription,
canonical,
image,
content,
templates/marketing-cloudflare/src/layouts/Base.astro:22
- Same title composition issue as the non-Cloudflare template:
fullTitleappendssiteTitleeven whentitlealready contains it (common whentitlecomes fromgetSeoMeta). This can produce duplicated titles like "X | Acme — Acme". Consider guarding against double-appendingsiteTitle(see templates/blog/src/layouts/Base.astro).
This issue also appears on line 40 of the same file.
const { title, pageTitle, description, image, canonical, content } = Astro.props;
const settings = await getSiteSettings();
const siteTitle = settings?.title || "Acme";
const fullTitle = title ? `${title} — ${siteTitle}` : siteTitle;
const siteDescription =
templates/marketing-cloudflare/src/layouts/Base.astro:50
- Same canonical handling as the non-Cloudflare template: since
canonicalis only taken from props, pages that don’t pass it will render without canonical/og:url contributions. Consider defaultingcanonicalto the current request URL (preferably without query params) when it’s not provided.
const pageCtx = createPublicPageContext({
Astro,
kind: content ? "content" : "custom",
pageType: "website",
title: fullTitle,
pageTitle: pageTitle ?? title ?? siteTitle,
description: description || siteDescription,
canonical,
image,
content,
siteName: siteTitle,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| title={seo.title} | ||
| description={seo.description} |
| title={seo.title} | ||
| description={seo.description} |
| title={seo.title} | ||
| description={seo.description} |
| title={seo.title} | ||
| description={seo.description} |
…plate to match route
ee0e0dc to
bedca5c
Compare
What does this PR do?
Related discussion: #687 (comment)
urlPatterncollection property,urlPatternto pages collection and/[slug].astroroute to avoid preview of pages created using the admin interface going to/pages/{slug}and resulting in 404urlPatternto the projects collection of portfolio template to match the existing routeI manually tested each template with the following steps:
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runmessages.pochanges except in translation PRs — a workflow extracts catalogs on merge tomain.AI-generated code disclosure
Screenshots / test output