From e84517b45b9f65cc0e5734abdc44e13b82a059a6 Mon Sep 17 00:00:00 2001 From: DaveWJRH Date: Wed, 16 Sep 2026 15:55:09 -0400 Subject: [PATCH] Implement automated ring.json generation --- public/ring-README.txt | 10 ---------- public/ring.json | 5 ----- src/pages/ring.json.ts | 31 +++++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 15 deletions(-) delete mode 100644 public/ring-README.txt delete mode 100644 public/ring.json create mode 100644 src/pages/ring.json.ts diff --git a/public/ring-README.txt b/public/ring-README.txt deleted file mode 100644 index 209e279..0000000 --- a/public/ring-README.txt +++ /dev/null @@ -1,10 +0,0 @@ -ring.json — PLACEHOLDER FILE -============================= - -This file is hand-written placeholder data for the ring widget to develop against. - -A later ticket will replace it with a build-time generated version derived from the -webring content collection (src/content/webring/**/*.json), filtered to entries where -inRing === true, and output to this same path during `astro build`. - -Do NOT edit the generated file in production — edit the source entries instead. diff --git a/public/ring.json b/public/ring.json deleted file mode 100644 index bda1848..0000000 --- a/public/ring.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - { "name": "Example Member A", "url": "https://example-a.example.com" }, - { "name": "Example Member B", "url": "https://example-b.example.com" }, - { "name": "Example Member C", "url": "https://example-c.example.com" } -] diff --git a/src/pages/ring.json.ts b/src/pages/ring.json.ts new file mode 100644 index 0000000..6577ebe --- /dev/null +++ b/src/pages/ring.json.ts @@ -0,0 +1,31 @@ +import type { APIRoute } from 'astro'; +import { getCollection } from 'astro:content'; + +export const GET: APIRoute = async () => { + const members = await getCollection('webring'); + + // Build `ring` from `members`: + // - .filter() to keep only inRing === true + // - .sort() by graduation year ascending, then name as a stable tiebreak + // (year difference, falling back to localeCompare on name) + // - .map() each down to just { name, url } + // This order defines prev/next traversal in the embed — keep it deterministic. + const ring = members + .filter((member) => member.data.inRing) + .sort((a, b) => { + if (a.data.year < b.data.year) return -1; + if (a.data.year > b.data.year) return 1; + + return a.data.name.localeCompare(b.data.name); + }) + .map((member) => { + return { + name: member.data.name, + url: member.data.url, + }; + }); + + return new Response(JSON.stringify(ring, null, 2), { + headers: { 'Content-Type': 'application/json' }, + }); +};