← back to Stars of Design
add /sitemap.xml route + JSON-LD Person schema on designer detail
70b7912447cb10355582172303fcd9c145b444da · 2026-05-10 09:41:41 -0700 · Steve Abrams
- robots.txt already advertised /sitemap.xml; route was missing (404).
Now serves all 4 static pages + every designer slug with lastmod/priority.
- Detail pages now emit schema.org Person JSON-LD (name, bio, styles via
knowsAbout, city via workLocation, DW pairings as subjectOf) so SERP
cards get rich-result eligibility.
Files touched
M routes/public.jsM views/public/designer.ejs
Diff
commit 70b7912447cb10355582172303fcd9c145b444da
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun May 10 09:41:41 2026 -0700
add /sitemap.xml route + JSON-LD Person schema on designer detail
- robots.txt already advertised /sitemap.xml; route was missing (404).
Now serves all 4 static pages + every designer slug with lastmod/priority.
- Detail pages now emit schema.org Person JSON-LD (name, bio, styles via
knowsAbout, city via workLocation, DW pairings as subjectOf) so SERP
cards get rich-result eligibility.
---
routes/public.js | 26 ++++++++++++++++++++++++++
views/public/designer.ejs | 23 +++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/routes/public.js b/routes/public.js
index ee08542..4bb4c3a 100644
--- a/routes/public.js
+++ b/routes/public.js
@@ -70,6 +70,32 @@ router.get('/submit', (req, res) => {
res.render('public/submit', { title: 'Submit a designer — Stars of Design' });
});
+router.get('/sitemap.xml', (req, res, next) => {
+ try {
+ const base = 'https://starsofdesign.com';
+ const all = data.load();
+ const today = new Date().toISOString().slice(0, 10);
+ const urls = [
+ { loc: `${base}/`, priority: '1.0', changefreq: 'weekly' },
+ { loc: `${base}/designers`, priority: '0.9', changefreq: 'weekly' },
+ { loc: `${base}/about`, priority: '0.5', changefreq: 'monthly' },
+ { loc: `${base}/submit`, priority: '0.4', changefreq: 'monthly' },
+ ...all.map((d) => ({
+ loc: `${base}/designers/${d.slug}`,
+ priority: '0.8',
+ changefreq: 'monthly',
+ })),
+ ];
+ const xml = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' +
+ urls.map((u) =>
+ ` <url><loc>${u.loc}</loc><lastmod>${today}</lastmod><changefreq>${u.changefreq}</changefreq><priority>${u.priority}</priority></url>`
+ ).join('\n') +
+ '\n</urlset>\n';
+ res.type('application/xml').send(xml);
+ } catch (e) { next(e); }
+});
+
router.get('/healthz', (req, res) => res.type('text').send('ok'));
module.exports = router;
diff --git a/views/public/designer.ejs b/views/public/designer.ejs
index be64287..ff4acab 100644
--- a/views/public/designer.ejs
+++ b/views/public/designer.ejs
@@ -1,4 +1,27 @@
<%- include('../partials/head', { title, meta_desc_override: typeof meta_desc_override !== 'undefined' ? meta_desc_override : undefined }) %>
+<%
+ // JSON-LD Person schema for richer SERP cards. Mention=DW collections that
+ // pair with this designer; affiliation/image kept loose since we host neither
+ // images nor employment data.
+ var jsonld = {
+ '@context': 'https://schema.org',
+ '@type': 'Person',
+ name: designer.name,
+ description: designer.bio || designer.headline || ('Interior designer profile on Stars of Design.'),
+ url: 'https://starsofdesign.com/designers/' + designer.slug,
+ jobTitle: 'Interior Designer',
+ knowsAbout: (designer.styles || []).slice(0, 8),
+ };
+ if (designer.city) {
+ jsonld.workLocation = { '@type': 'Place', name: designer.city };
+ }
+ if (designer.preferred_dw && designer.preferred_dw.length) {
+ jsonld.subjectOf = designer.preferred_dw.map(function (p) {
+ return { '@type': 'CreativeWork', name: p.label, url: p.url };
+ });
+ }
+%>
+<script type="application/ld+json"><%- JSON.stringify(jsonld) %></script>
<%- include('../partials/header') %>
<main class="designer-detail">
← aa14a02 initial scaffold + GA gtag (G-YCT0F2Q692) + 27 designer prof
·
back to Stars of Design
·
starsofdesign tick0: PG schema + AI placeholder + scaffold bde4448 →