[object Object]

← back to AsSeenInMovies

asseeninmovies: ItemList JSON-LD on /movies + /people index pages — each visible row emitted as schema.org/Movie or /Person ListItem with position + url. Closes the schema-coverage gap on listing pages. numberOfItems reflects total filter result count, not page slice, so crawlers know there's more behind pagination.

4648ead3d7c31e4fd2a83d2d9d15b9deb193f375 · 2026-05-12 19:57:32 -0700 · SteveStudio2

Files touched

Diff

commit 4648ead3d7c31e4fd2a83d2d9d15b9deb193f375
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Tue May 12 19:57:32 2026 -0700

    asseeninmovies: ItemList JSON-LD on /movies + /people index pages — each visible row emitted as schema.org/Movie or /Person ListItem with position + url. Closes the schema-coverage gap on listing pages. numberOfItems reflects total filter result count, not page slice, so crawlers know there's more behind pagination.
---
 server.js | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/server.js b/server.js
index faac3e7..f1a7a24 100644
--- a/server.js
+++ b/server.js
@@ -1331,7 +1331,22 @@ app.get('/movies', async (req, res) => {
       <div class="grid">${cards || '<div class="empty">No movies match those filters yet.</div>'}</div>
       ${pager}
       <script>(function(){var KEY='asim_movies_density';var saved=parseInt(localStorage.getItem(KEY)||'180',10);var r=document.querySelector('[data-density="movies"]');if(!r)return;if(saved&&saved>=140&&saved<=280){r.value=saved;document.documentElement.style.setProperty('--movies-card',saved+'px')}r.addEventListener('input',function(){document.documentElement.style.setProperty('--movies-card',r.value+'px');localStorage.setItem(KEY,r.value)})})();</script>`;
-    res.type('html').send(htmlShell('Movies', body, '', 'https://asseeninmovies.com/movies'));
+    const itemListMovies = {
+      '@context': 'https://schema.org',
+      '@type': 'ItemList',
+      itemListElement: r.rows.map((m, i) => ({
+        '@type': 'ListItem',
+        position: offset + i + 1,
+        item: {
+          '@type': 'Movie',
+          name: m.title,
+          ...(m.release_year ? { datePublished: String(m.release_year) } : {}),
+          url: `https://asseeninmovies.com/movie/${m.id}`,
+        },
+      })),
+      numberOfItems: total,
+    };
+    res.type('html').send(htmlShell('Movies', body, `<script type="application/ld+json">${JSON.stringify(itemListMovies)}</script>`, 'https://asseeninmovies.com/movies'));
   } catch (e) {
     res.status(500).type('html').send(htmlShell('Error', `<div class="empty">${esc(e.message)}</div>`));
   }
@@ -1430,7 +1445,22 @@ app.get('/people', async (req, res) => {
       <div class="grid">${cards || '<div class="empty">No people match that filter yet.</div>'}</div>
       ${pager}
       <script>(function(){var KEY='asim_people_density';var saved=parseInt(localStorage.getItem(KEY)||'160',10);var r=document.querySelector('[data-density="people"]');if(!r)return;if(saved&&saved>=120&&saved<=280){r.value=saved;document.documentElement.style.setProperty('--people-card',saved+'px')}r.addEventListener('input',function(){document.documentElement.style.setProperty('--people-card',r.value+'px');localStorage.setItem(KEY,r.value)})})();</script>`;
-    res.type('html').send(htmlShell('People', body, '', 'https://asseeninmovies.com/people'));
+    const itemListPeople = {
+      '@context': 'https://schema.org',
+      '@type': 'ItemList',
+      itemListElement: r.rows.map((p, i) => ({
+        '@type': 'ListItem',
+        position: offset + i + 1,
+        item: {
+          '@type': 'Person',
+          name: p.full_name,
+          ...(p.primary_profession && p.primary_profession.length ? { jobTitle: p.primary_profession[0] } : {}),
+          url: `https://asseeninmovies.com/person/${p.id}`,
+        },
+      })),
+      numberOfItems: total,
+    };
+    res.type('html').send(htmlShell('People', body, `<script type="application/ld+json">${JSON.stringify(itemListPeople)}</script>`, 'https://asseeninmovies.com/people'));
   } catch (e) {
     res.status(500).type('html').send(htmlShell('Error', `<div class="empty">${esc(e.message)}</div>`));
   }

← 2d5ec29 asseeninmovies: smoke test harness — test/smoke.js (zero dep  ·  back to AsSeenInMovies  ·  asseeninmovies: GET /api — JSON index of every public API en ea5c081 →