From 5ae26824c5377719f9bee194be1ea0865936575f Mon Sep 17 00:00:00 2001 From: Patricio Date: Thu, 6 Nov 2025 20:40:45 -0300 Subject: [PATCH 01/11] readding page --- src/lib/types.ts | 12 ++++ src/routes/api/people/+server.ts | 80 ++++++++++++++++++++++ src/routes/api/posts/+server.ts | 2 + src/routes/people/+page.svelte | 30 ++++++++ src/routes/people/+page.ts | 21 ++++++ src/routes/people/meta.ts | 9 +++ src/routes/people/person.svelte | 114 +++++++++++++++++++++++++++++++ 7 files changed, 268 insertions(+) create mode 100644 src/routes/api/people/+server.ts create mode 100644 src/routes/people/+page.svelte create mode 100644 src/routes/people/+page.ts create mode 100644 src/routes/people/meta.ts create mode 100644 src/routes/people/person.svelte diff --git a/src/lib/types.ts b/src/lib/types.ts index cf8b0034..aa9909ca 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -34,6 +34,18 @@ export type AirtableSignatory = { duplicate?: boolean } +export type Person = { + id: string + name: string + /** URL to image file */ + image?: string + bio: string + title?: string + /** Doesn't want to be visible on the /people page */ + privacy?: boolean + checked?: boolean +} + export type Team = { id: string name: string diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts new file mode 100644 index 00000000..05a5c541 --- /dev/null +++ b/src/routes/api/people/+server.ts @@ -0,0 +1,80 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { Person } from '$lib/types.js' +import { defaultTitle } from '$lib/utils' +import { json } from '@sveltejs/kit' +import { fetchAllPages } from '$lib/airtable.js' + +/** + * Fallback people data to use in development if Airtable fetch fails + */ +const fallbackPeople: Person[] = [ + { + id: 'fallback-stub1', + name: '[FALLBACK DATA] Example Person', + bio: 'I hold places when Airtable API is unavailable.', + title: 'Placeholder', + image: 'https://api.dicebear.com/7.x/bottts/svg?seed=fallback1', + privacy: false, + checked: true + }, + { + id: 'fallback-stub2', + name: '[FALLBACK DATA] Holdor', + bio: 'Thrown at games', + title: 'of Plays', + image: 'https://api.dicebear.com/7.x/bottts/svg?seed=fallback2', + privacy: false, + checked: true + } +] + +function recordToPerson(record: any): Person { + return { + id: record.id || 'noId', + name: record.fields.Name, + bio: record.fields.bio, + title: record.fields.title || defaultTitle, + image: record.fields.image && record.fields.image[0].thumbnails.large.url, + privacy: record.fields.privacy, + checked: record.fields.checked + } +} + +const filter = (p: Person) => { + return p.image && !p.privacy && p.checked +} + +export async function GET({ fetch, setHeaders }) { + const url = `https://api.airtable.com/v0/appWPTGqZmUcs3NWu/tblZhQc49PkCz3yHd` + //const url = `https://api.airtable.com/v0/NEW_APP_ID/NEW_TABLE_ID` + setHeaders({ + 'cache-control': 'public, max-age=3600' // 1 hour in seconds + }) + + try { + // Create fallback records in the expected Airtable format + const fallbackRecords = fallbackPeople.map((person) => ({ + id: person.id, + fields: { + Name: person.name, + bio: person.bio, + title: person.title, + image: [{ thumbnails: { large: { url: person.image } } }], + privacy: person.privacy, + checked: person.checked + } + })) + + const records = await fetchAllPages(fetch, url, fallbackRecords) + const out: Person[] = records + .map(recordToPerson) + .filter(filter) + // Shuffle the array, although not truly random + .sort(() => 0.5 - Math.random()) + return json(out) + } catch (e) { + console.error('Error fetching people:', e) + // Return fallback data instead of error + return json(fallbackPeople.filter(filter)) + } +} \ No newline at end of file diff --git a/src/routes/api/posts/+server.ts b/src/routes/api/posts/+server.ts index 64daf638..f4e75e8c 100644 --- a/src/routes/api/posts/+server.ts +++ b/src/routes/api/posts/+server.ts @@ -5,6 +5,7 @@ import { communitiesMeta } from '../../communities/communities' import { meta as pdoomMeta } from '../../pdoom/meta' import { meta as quotesMeta } from '../../quotes/meta' import { meta as emailBuilderMeta } from '../../email-builder/meta' +import { meta as peopleMeta } from '../../people/meta' import { meta as teamsMeta } from '../../teams/meta' import { meta as statementMeta } from '../../statement/meta' import { meta as dearSirDemisMeta } from '../../dear-sir-demis-2025/meta' @@ -16,6 +17,7 @@ const hardCodedPages: Post[] = [ pdoomMeta, quotesMeta, emailBuilderMeta, + peopleMeta, teamsMeta, statementMeta, dearSirDemisMeta diff --git a/src/routes/people/+page.svelte b/src/routes/people/+page.svelte new file mode 100644 index 00000000..9b1d177d --- /dev/null +++ b/src/routes/people/+page.svelte @@ -0,0 +1,30 @@ + + + + +

{title}

+ +
+ {#if people.length === 0} +

No team members found

+ {/if} +
    + {#each people as { name, image, bio, title }} + + {/each} +
+
+ + \ No newline at end of file diff --git a/src/routes/people/+page.ts b/src/routes/people/+page.ts new file mode 100644 index 00000000..ad3642b2 --- /dev/null +++ b/src/routes/people/+page.ts @@ -0,0 +1,21 @@ +import type { Person } from '$lib/types' +import { defaultTitle } from '$lib/utils' + +export const prerender = false + +export const load = async ({ fetch, setHeaders }) => { + const response = await fetch('api/people') + const people: Person[] = await response.json() + setHeaders({ + 'cache-control': 'public, max-age=3600' // 1 hour in seconds + }) + // sort people, those who dont have "Volunteer" as title should be at the top + people.sort((a, b) => { + if (a.title === defaultTitle && b.title !== defaultTitle) return 1 + if (a.title !== defaultTitle && b.title === defaultTitle) return -1 + return 0 + }) + return { + people: people + } +} \ No newline at end of file diff --git a/src/routes/people/meta.ts b/src/routes/people/meta.ts new file mode 100644 index 00000000..27e0988b --- /dev/null +++ b/src/routes/people/meta.ts @@ -0,0 +1,9 @@ +import type { Post } from '$lib/types' + +export const meta: Post = { + title: 'People of PauseAI', + description: 'Staff and contributors behind PauseAI', + date: '2025-11-06', + slug: 'people', + categories: [] +} \ No newline at end of file diff --git a/src/routes/people/person.svelte b/src/routes/people/person.svelte new file mode 100644 index 00000000..0f4c010d --- /dev/null +++ b/src/routes/people/person.svelte @@ -0,0 +1,114 @@ + + +
  • + {#if image} +
    + {/if} +
    +
    +
    + {name} +
    + {#if title} +
    {title}
    + {/if} +
    + {#if bio} +
    + {bioOpen ? bio : bioTruncated} + {#if !bioOpen && bio.length > len} + + {/if} +
    + {/if} +
    +
  • + + \ No newline at end of file From 990a5e8a08950a808743fb13a07430337d2eca5b Mon Sep 17 00:00:00 2001 From: Patricio Date: Thu, 6 Nov 2025 20:41:33 -0300 Subject: [PATCH 02/11] filtering by only titled people --- src/routes/api/people/+server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts index 05a5c541..b7c0401b 100644 --- a/src/routes/api/people/+server.ts +++ b/src/routes/api/people/+server.ts @@ -41,7 +41,7 @@ function recordToPerson(record: any): Person { } const filter = (p: Person) => { - return p.image && !p.privacy && p.checked + return p.image && !p.privacy && p.checked && p.title?.trim() !== ''; } export async function GET({ fetch, setHeaders }) { From 2772830b670b9bacfc8013dc58d822a4767c14b5 Mon Sep 17 00:00:00 2001 From: Patricio Date: Thu, 6 Nov 2025 20:47:32 -0300 Subject: [PATCH 03/11] forgot defaultTitle --- src/lib/utils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 30f6844f..fa73bd3b 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -19,3 +19,5 @@ export function generateCacheControlRecord(options: CacheControlInit): Record { return Object.fromEntries(headers.entries()) } + +export const defaultTitle = 'Volunteer'; From 94157ddca177c9f9916d7a5d04688eb743051168 Mon Sep 17 00:00:00 2001 From: Patricio Date: Thu, 6 Nov 2025 21:57:03 -0300 Subject: [PATCH 04/11] idk man --- src/routes/api/people/+server.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts index b7c0401b..d7f1aa25 100644 --- a/src/routes/api/people/+server.ts +++ b/src/routes/api/people/+server.ts @@ -41,12 +41,11 @@ function recordToPerson(record: any): Person { } const filter = (p: Person) => { - return p.image && !p.privacy && p.checked && p.title?.trim() !== ''; -} + return p.image && !p.privacy && p.checked && p.title?.trim() !== '' && p.title !== 'Volunteer'; +}; export async function GET({ fetch, setHeaders }) { const url = `https://api.airtable.com/v0/appWPTGqZmUcs3NWu/tblZhQc49PkCz3yHd` - //const url = `https://api.airtable.com/v0/NEW_APP_ID/NEW_TABLE_ID` setHeaders({ 'cache-control': 'public, max-age=3600' // 1 hour in seconds }) From 888be99e6c1f164390847ce718c29f0f4ae5f368 Mon Sep 17 00:00:00 2001 From: Patricio Date: Tue, 11 Nov 2025 00:43:09 -0300 Subject: [PATCH 05/11] Switching to Members table. Filtering out duplicates --- src/lib/types.ts | 1 + src/routes/api/people/+server.ts | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/lib/types.ts b/src/lib/types.ts index aa9909ca..a697615e 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -44,6 +44,7 @@ export type Person = { /** Doesn't want to be visible on the /people page */ privacy?: boolean checked?: boolean + duplicate?: boolean } export type Team = { diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts index d7f1aa25..4668ec59 100644 --- a/src/routes/api/people/+server.ts +++ b/src/routes/api/people/+server.ts @@ -31,17 +31,22 @@ const fallbackPeople: Person[] = [ function recordToPerson(record: any): Person { return { id: record.id || 'noId', - name: record.fields.Name, - bio: record.fields.bio, - title: record.fields.title || defaultTitle, - image: record.fields.image && record.fields.image[0].thumbnails.large.url, - privacy: record.fields.privacy, - checked: record.fields.checked + name: record.fields['Full name'], + bio: record.fields.Bio2, + title: record.fields.Title || defaultTitle, + image: record.fields.Photo && record.fields.image[0].thumbnails.large.url, + privacy: record.fields.Privacy, + checked: record.fields.About, + duplicate: record.fields.Duplicate } } const filter = (p: Person) => { - return p.image && !p.privacy && p.checked && p.title?.trim() !== '' && p.title !== 'Volunteer'; + return p.image && + !p.privacy && + p.checked && + p.title?.trim() !== '' && p.title !== 'Volunteer' && + !p.duplicate; }; export async function GET({ fetch, setHeaders }) { From 080797ded09261dbd2ba2a99d1e3cfb1535a59d8 Mon Sep 17 00:00:00 2001 From: Patricio Date: Tue, 11 Nov 2025 00:46:13 -0300 Subject: [PATCH 06/11] link changed for members table --- src/routes/api/people/+server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts index 4668ec59..d0d0884e 100644 --- a/src/routes/api/people/+server.ts +++ b/src/routes/api/people/+server.ts @@ -50,7 +50,7 @@ const filter = (p: Person) => { }; export async function GET({ fetch, setHeaders }) { - const url = `https://api.airtable.com/v0/appWPTGqZmUcs3NWu/tblZhQc49PkCz3yHd` + const url = `https://api.airtable.com/v0/appWPTGqZmUcs3NWu/tblL1icZBhTV1gQ9o` setHeaders({ 'cache-control': 'public, max-age=3600' // 1 hour in seconds }) From 43e273bf7371ce816c73ab3e23e62e667a638b0a Mon Sep 17 00:00:00 2001 From: Patricio Date: Tue, 11 Nov 2025 18:07:48 -0300 Subject: [PATCH 07/11] fixing fields --- src/routes/api/people/+server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts index d0d0884e..a47a9ec6 100644 --- a/src/routes/api/people/+server.ts +++ b/src/routes/api/people/+server.ts @@ -34,10 +34,10 @@ function recordToPerson(record: any): Person { name: record.fields['Full name'], bio: record.fields.Bio2, title: record.fields.Title || defaultTitle, - image: record.fields.Photo && record.fields.image[0].thumbnails.large.url, + image: record.fields.Photo && record.fields.Photo[0].thumbnails.large.url, privacy: record.fields.Privacy, checked: record.fields.About, - duplicate: record.fields.Duplicate + duplicate: record.fields.duplicate } } From fb949da1834b642827ac0fa70aaad01e3cdea5b0 Mon Sep 17 00:00:00 2001 From: Anthony Bailey Date: Wed, 12 Nov 2025 16:38:41 +0000 Subject: [PATCH 08/11] Trigger rebuild to test fresh edge function deployment Testing first-request behavior on cold start --- src/routes/people/meta.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/people/meta.ts b/src/routes/people/meta.ts index 27e0988b..43a67aa5 100644 --- a/src/routes/people/meta.ts +++ b/src/routes/people/meta.ts @@ -1,9 +1,9 @@ import type { Post } from '$lib/types' export const meta: Post = { - title: 'People of PauseAI', + title: 'People of PauseAI', // Whitespace change to trigger rebuild description: 'Staff and contributors behind PauseAI', date: '2025-11-06', slug: 'people', categories: [] -} \ No newline at end of file +} From d29c11d93fca1f61e2ab5a563521e8e2f134db63 Mon Sep 17 00:00:00 2001 From: Wituareard <87208350+Wituareard@users.noreply.github.com> Date: Sat, 15 Nov 2025 16:28:55 +0100 Subject: [PATCH 09/11] Revert dummy edit --- src/routes/people/+page.ts | 2 +- src/routes/people/meta.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/people/+page.ts b/src/routes/people/+page.ts index ad3642b2..a1be8462 100644 --- a/src/routes/people/+page.ts +++ b/src/routes/people/+page.ts @@ -18,4 +18,4 @@ export const load = async ({ fetch, setHeaders }) => { return { people: people } -} \ No newline at end of file +} diff --git a/src/routes/people/meta.ts b/src/routes/people/meta.ts index 43a67aa5..b55fc8ad 100644 --- a/src/routes/people/meta.ts +++ b/src/routes/people/meta.ts @@ -1,7 +1,7 @@ import type { Post } from '$lib/types' export const meta: Post = { - title: 'People of PauseAI', // Whitespace change to trigger rebuild + title: 'People of PauseAI', description: 'Staff and contributors behind PauseAI', date: '2025-11-06', slug: 'people', From 66ac02b39172e03d97d4980916343f6be8ab4bd6 Mon Sep 17 00:00:00 2001 From: Wituareard <87208350+Wituareard@users.noreply.github.com> Date: Sat, 15 Nov 2025 16:31:33 +0100 Subject: [PATCH 10/11] Move constant to config --- src/lib/config.ts | 1 + src/lib/utils.ts | 2 -- src/routes/api/people/+server.ts | 27 +++++++++++++++------------ src/routes/people/+page.ts | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/lib/config.ts b/src/lib/config.ts index 778b63fd..651bb395 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -6,3 +6,4 @@ export const description = export const url = dev ? 'http://localhost:37572' : 'https://pauseai.info' export const botName = 'RogueGPT' export const verificationParameter = 'verificationKey' +export const defaultTitle = 'Volunteer' diff --git a/src/lib/utils.ts b/src/lib/utils.ts index fa73bd3b..30f6844f 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -19,5 +19,3 @@ export function generateCacheControlRecord(options: CacheControlInit): Record { return Object.fromEntries(headers.entries()) } - -export const defaultTitle = 'Volunteer'; diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts index a47a9ec6..eb79ed93 100644 --- a/src/routes/api/people/+server.ts +++ b/src/routes/api/people/+server.ts @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { Person } from '$lib/types.js' -import { defaultTitle } from '$lib/utils' +import type { Person } from '$lib/types' +import { defaultTitle } from '$lib/config' import { json } from '@sveltejs/kit' -import { fetchAllPages } from '$lib/airtable.js' +import { fetchAllPages } from '$lib/airtable' /** * Fallback people data to use in development if Airtable fetch fails @@ -37,21 +37,24 @@ function recordToPerson(record: any): Person { image: record.fields.Photo && record.fields.Photo[0].thumbnails.large.url, privacy: record.fields.Privacy, checked: record.fields.About, - duplicate: record.fields.duplicate + duplicate: record.fields.duplicate } } const filter = (p: Person) => { - return p.image && - !p.privacy && - p.checked && - p.title?.trim() !== '' && p.title !== 'Volunteer' && - !p.duplicate; -}; + return ( + p.image && + !p.privacy && + p.checked && + p.title?.trim() !== '' && + p.title !== 'Volunteer' && + !p.duplicate + ) +} export async function GET({ fetch, setHeaders }) { const url = `https://api.airtable.com/v0/appWPTGqZmUcs3NWu/tblL1icZBhTV1gQ9o` - setHeaders({ + setHeaders({ 'cache-control': 'public, max-age=3600' // 1 hour in seconds }) @@ -81,4 +84,4 @@ export async function GET({ fetch, setHeaders }) { // Return fallback data instead of error return json(fallbackPeople.filter(filter)) } -} \ No newline at end of file +} diff --git a/src/routes/people/+page.ts b/src/routes/people/+page.ts index a1be8462..acc08e42 100644 --- a/src/routes/people/+page.ts +++ b/src/routes/people/+page.ts @@ -1,5 +1,5 @@ import type { Person } from '$lib/types' -import { defaultTitle } from '$lib/utils' +import { defaultTitle } from '$lib/config' export const prerender = false From 85c5c52ee5f693d361e3692842cd1f22cae81a1a Mon Sep 17 00:00:00 2001 From: Wituareard <87208350+Wituareard@users.noreply.github.com> Date: Sat, 15 Nov 2025 16:33:16 +0100 Subject: [PATCH 11/11] Remove magic value --- src/routes/api/people/+server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/api/people/+server.ts b/src/routes/api/people/+server.ts index eb79ed93..09b10893 100644 --- a/src/routes/api/people/+server.ts +++ b/src/routes/api/people/+server.ts @@ -47,7 +47,7 @@ const filter = (p: Person) => { !p.privacy && p.checked && p.title?.trim() !== '' && - p.title !== 'Volunteer' && + p.title !== defaultTitle && !p.duplicate ) }