← back to Stars of Design
starsofdesign: BreadcrumbList JSON-LD across all 3 detail page types — /firms/:slug (Home > Firms > {firm}), /designers/:slug (Home > Designers > {name}), /clients/:slug (Home > Clients > {name}). Packaged in @graph alongside entity schema. /firms also now emits employee→Person list for each associated designer.
ed2f2d8b5a115efe4828d86277f61c9c3f461ceb · 2026-05-12 19:29:40 -0700 · Steve Abrams
Files touched
Diff
commit ed2f2d8b5a115efe4828d86277f61c9c3f461ceb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue May 12 19:29:40 2026 -0700
starsofdesign: BreadcrumbList JSON-LD across all 3 detail page types — /firms/:slug (Home > Firms > {firm}), /designers/:slug (Home > Designers > {name}), /clients/:slug (Home > Clients > {name}). Packaged in @graph alongside entity schema. /firms also now emits employee→Person list for each associated designer.
---
routes/public.js | 137 ++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 90 insertions(+), 47 deletions(-)
diff --git a/routes/public.js b/routes/public.js
index 66fefd7..766bad6 100644
--- a/routes/public.js
+++ b/routes/public.js
@@ -108,18 +108,30 @@ router.get('/designers/:slug', (req, res, next) => {
const designerVideos = data.videosByDesigner(slug);
const json_ld = {
'@context': 'https://schema.org',
- '@type': 'Person',
- name: d.name,
- url: `https://starsofdesign.com/designers/${d.slug || slug}`,
- ...(d.headline ? { description: d.headline } : {}),
- ...(d.city ? {
- homeLocation: {
- '@type': 'Place',
- name: d.city,
- }
- } : {}),
- ...(d.styles && d.styles.length ? { knowsAbout: d.styles } : {}),
- jobTitle: 'Interior Designer',
+ '@graph': [
+ {
+ '@type': 'Person',
+ name: d.name,
+ url: `https://starsofdesign.com/designers/${d.slug || slug}`,
+ ...(d.headline ? { description: d.headline } : {}),
+ ...(d.city ? {
+ homeLocation: {
+ '@type': 'Place',
+ name: d.city,
+ }
+ } : {}),
+ ...(d.styles && d.styles.length ? { knowsAbout: d.styles } : {}),
+ jobTitle: 'Interior Designer',
+ },
+ {
+ '@type': 'BreadcrumbList',
+ itemListElement: [
+ { '@type': 'ListItem', position: 1, name: 'Home', item: 'https://starsofdesign.com/' },
+ { '@type': 'ListItem', position: 2, name: 'Designers', item: 'https://starsofdesign.com/designers' },
+ { '@type': 'ListItem', position: 3, name: d.name, item: `https://starsofdesign.com/designers/${d.slug || slug}` },
+ ],
+ },
+ ],
};
res.render('public/designer', {
title: `${d.name} — Profile, Signature Style & Wallcovering Pairings | Stars of Design`,
@@ -169,23 +181,35 @@ router.get('/clients/:slug', async (req, res, next) => {
// only, never street/zip/phone — schema mirrors that exactly.
const json_ld = {
'@context': 'https://schema.org',
- '@type': 'Person',
- name: c.full_name,
- url: `https://starsofdesign.com/clients/${c.slug || slug}`,
- jobTitle: c.role || 'Interior Designer',
- ...(c.city || c.state ? {
- homeLocation: {
- '@type': 'Place',
- name: [c.city, c.state].filter(Boolean).join(', '),
- }
- } : {}),
- ...(c.firm ? {
- worksFor: {
- '@type': 'Organization',
- name: c.firm.name,
- ...(c.firm.slug ? { url: `https://starsofdesign.com/firms/${c.firm.slug}` } : {}),
- }
- } : {}),
+ '@graph': [
+ {
+ '@type': 'Person',
+ name: c.full_name,
+ url: `https://starsofdesign.com/clients/${c.slug || slug}`,
+ jobTitle: c.role || 'Interior Designer',
+ ...(c.city || c.state ? {
+ homeLocation: {
+ '@type': 'Place',
+ name: [c.city, c.state].filter(Boolean).join(', '),
+ }
+ } : {}),
+ ...(c.firm ? {
+ worksFor: {
+ '@type': 'Organization',
+ name: c.firm.name,
+ ...(c.firm.slug ? { url: `https://starsofdesign.com/firms/${c.firm.slug}` } : {}),
+ }
+ } : {}),
+ },
+ {
+ '@type': 'BreadcrumbList',
+ itemListElement: [
+ { '@type': 'ListItem', position: 1, name: 'Home', item: 'https://starsofdesign.com/' },
+ { '@type': 'ListItem', position: 2, name: 'Clients', item: 'https://starsofdesign.com/clients' },
+ { '@type': 'ListItem', position: 3, name: c.full_name, item: `https://starsofdesign.com/clients/${c.slug || slug}` },
+ ],
+ },
+ ],
};
res.render('public/dwclient', {
title: `${c.full_name} — DW Client Designer | Stars of Design`,
@@ -226,26 +250,45 @@ router.get('/firms/:slug', async (req, res, next) => {
}
const f = await firmsLib.getFirm(slug);
if (!f) return res.status(404).render('public/404', { title: 'Not found — Stars of Design' });
- // JSON-LD Organization (design firm) — Schema.org primary entity is
- // Organization with subtype `Architectural` only when applicable; we
- // stay generic since the firm may be interiors or architecture or both.
+ // JSON-LD @graph — Organization (the firm itself) + BreadcrumbList
+ // (Home > Firms > {firm}) + ItemList of associated designers, all in
+ // one script tag for cleaner head injection.
const json_ld = {
'@context': 'https://schema.org',
- '@type': 'Organization',
- name: f.name,
- url: `https://starsofdesign.com/firms/${f.slug}`,
- ...(f.website ? { sameAs: [f.website] } : {}),
- ...(f.founded_year ? { foundingDate: String(f.founded_year) } : {}),
- ...(f.bio ? { description: f.bio.slice(0, 800) } : {}),
- ...(f.city || f.state ? {
- address: {
- '@type': 'PostalAddress',
- ...(f.city ? { addressLocality: f.city } : {}),
- ...(f.state ? { addressRegion: f.state } : {}),
- ...(f.country ? { addressCountry: f.country } : {}),
- }
- } : {}),
- ...(f.areas && f.areas.length ? { areaServed: f.areas } : {}),
+ '@graph': [
+ {
+ '@type': 'Organization',
+ name: f.name,
+ url: `https://starsofdesign.com/firms/${f.slug}`,
+ ...(f.website ? { sameAs: [f.website] } : {}),
+ ...(f.founded_year ? { foundingDate: String(f.founded_year) } : {}),
+ ...(f.bio ? { description: f.bio.slice(0, 800) } : {}),
+ ...(f.city || f.state ? {
+ address: {
+ '@type': 'PostalAddress',
+ ...(f.city ? { addressLocality: f.city } : {}),
+ ...(f.state ? { addressRegion: f.state } : {}),
+ ...(f.country ? { addressCountry: f.country } : {}),
+ }
+ } : {}),
+ ...(f.areas && f.areas.length ? { areaServed: f.areas } : {}),
+ ...(f.designers && f.designers.length ? {
+ employee: f.designers.map(d => ({
+ '@type': 'Person',
+ name: d.full_name,
+ url: `https://starsofdesign.com/clients/${d.slug}`,
+ })),
+ } : {}),
+ },
+ {
+ '@type': 'BreadcrumbList',
+ itemListElement: [
+ { '@type': 'ListItem', position: 1, name: 'Home', item: 'https://starsofdesign.com/' },
+ { '@type': 'ListItem', position: 2, name: 'Firms', item: 'https://starsofdesign.com/firms' },
+ { '@type': 'ListItem', position: 3, name: f.name, item: `https://starsofdesign.com/firms/${f.slug}` },
+ ],
+ },
+ ],
};
res.render('public/firm', {
title: `${f.name} — Design Firm | Stars of Design`,
← 7348d91 starsofdesign: home page — WebSite + Organization JSON-LD wi
·
back to Stars of Design
·
starsofdesign: GET /privacy + /terms — minimal legal pages ( 00a2a60 →