From c04e82e0852c3885e233d33be92ae0de1d900db6 Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Wed, 23 Sep 2026 21:04:29 -0400 Subject: [PATCH] The family list knows the hall: about panels link to gamehall.kestrelsnest.social, and a new game gets a card there Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG --- src/lib/components/Hall.svelte | 10 +++++++--- src/lib/family.ts | 19 +++++++++++++------ static/family.json | 1 + 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/lib/components/Hall.svelte b/src/lib/components/Hall.svelte index a8a0346..a244e4c 100644 --- a/src/lib/components/Hall.svelte +++ b/src/lib/components/Hall.svelte @@ -3,7 +3,7 @@ // bot, open a table, join by code, the ledger of your tables, and the // about panel with the rules, the guide and a way to reach the keeper. import { goto } from '$app/navigation'; - import { otherGames, type FamilyGame } from '$lib/family'; + import { loadFamily, type FamilyGame } from '$lib/family'; import Preferences from './Preferences.svelte'; import { prefs, setPref } from '$lib/prefs.svelte'; import { allSeats, doubtSeat, forgetSeat, rememberSeat, ServerError, trustSeat } from '$lib/net/client'; @@ -35,8 +35,12 @@ const hours = (minutes: number) => (minutes < 90 ? `${minutes} minutes` : `${Math.round(minutes / 60)} hours`); /** The other games of Kestrel's Hall, for the about panel. */ let family = $state([]); + let hall = $state(''); $effect(() => { - void otherGames('hnefatafl').then((g) => (family = g)); + void loadFamily('hnefatafl').then((f) => { + family = f.games; + hall = f.hall; + }); }); /** Reports this browser's seats have filed, with the keeper's replies. */ let reports = $state([]); @@ -283,7 +287,7 @@

{/if} {#if family.length} -

More games in Kestrel's Hall

+

More games in {#if hall}Kestrel's Hall{:else}Kestrel's Hall{/if}

    {#each family as g (g.slug)}
  • {g.name}: {g.pitch} {g.players} players; {g.origin}.
  • diff --git a/src/lib/family.ts b/src/lib/family.ts index b706a6b..596072d 100644 --- a/src/lib/family.ts +++ b/src/lib/family.ts @@ -1,6 +1,7 @@ // The other games of Kestrel's Hall, from the family list the kit keeps // (family.json, one copy shipped with every game), so a player who liked one -// table can find the next. This game is left out of its own list. +// table can find the next, and the hall's front door. This game is left out +// of its own list. export interface FamilyGame { slug: string; @@ -11,13 +12,19 @@ export interface FamilyGame { origin: string; } -export async function otherGames(self: string): Promise { +/** The family list: the hall's front door and every game but this one. */ +export interface Family { + hall: string; + games: FamilyGame[]; +} + +export async function loadFamily(self: string): Promise { try { const res = await fetch('/family.json', { cache: 'no-cache' }); - if (!res.ok) return []; - const data = (await res.json()) as { games?: FamilyGame[] }; - return (data.games ?? []).filter((g) => g.slug !== self); + if (!res.ok) return { hall: '', games: [] }; + const data = (await res.json()) as { hall?: string; games?: FamilyGame[] }; + return { hall: data.hall ?? '', games: (data.games ?? []).filter((g) => g.slug !== self) }; } catch { - return []; + return { hall: '', games: [] }; } } diff --git a/static/family.json b/static/family.json index f9e6d33..48572da 100644 --- a/static/family.json +++ b/static/family.json @@ -1,5 +1,6 @@ { "family": "Kestrel's Hall", + "hall": "https://gamehall.kestrelsnest.social", "games": [ { "slug": "wizwar",