Pattern · TypeScript
BreadcrumbList JSON-LD for internal pages
One helper feeds both visible breadcrumbs and markup — names and URLs stay in sync.
·
Level: beginnerTime estimate: ~15 min
One data array powers the Breadcrumb UI and `itemListElement` in JSON-LD — no label/URL drift.
- Matching order lowers rich-result mistakes
- the object drops into `@graph`
- re-run a validator after route changes
Visible breadcrumbs and
application/ld+jsonmust share the same order and labels.
Code
export function buildBreadcrumbListLd(items: { name: string; url: string }[]) {
return {
'@type': 'BreadcrumbList' as const,
itemListElement: items.map((item, index) => ({
'@type': 'ListItem' as const,
position: index + 1,
name: item.name,
item: item.url,
})),
}
}
Verification
- UI labels and JSON-LD use the same canonical URLs, including trailing slashes if that is your site policy.
- Rich Results Test / Schema.org validator reports no
ListItemerrors.
Sources
More patterns
- Next.js
Canonical URL and page metadata in Next.js App Router
A generateMetadata pattern with canonical and Open Graph — baseline SEO hygiene.
Open pattern - JSON-LD
Extending JSON-LD Organization and WebSite in the root layout
Linked @id values in @graph: organization, person, site — the base for other entities.
Open pattern
Blog posts
- Process
Site handoff checklist: speed, accessibility, and baseline tech SEO before you sign
Why to look at PageSpeed Insights and WAVE before sign-off, how lab metrics differ from field data, and a minimum tech SEO bar that reduces post-launch surprises.
Read article - SEO
SEO architecture: why a site does not sell without structure
How the right site structure affects sales and rankings. Why design comes second and semantics first.
Read article
Need this implemented for your domain and stack?
Short form: name, phone, and site. After you submit, we reply with next steps and a phase outline; details are refined on a call.