Ionosphere.tv
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: curated project list — 61 real projects, not talk titles

Rewrote atmosphere-projects.json to only include actual named
projects featured at the conference (Semble, Graze, tangled, Attie,
Cirrus, Surf, etc.) with URLs where known. Removed talks that don't
feature a distinct project (panels, workshops, discussions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+9 -13
+9 -13
apps/ionosphere-appview/src/routes.ts
··· 322 322 const BLOCKED_HANDLES = new Set(['nowbreezing.ntw.app']); 323 323 const filterBlocked = (rows: any[]) => rows.filter((r: any) => !BLOCKED_HANDLES.has(r.author_handle)); 324 324 325 - // Projects: curated list from JSON 325 + // Projects: curated list from JSON (flat array) 326 326 let projects: any[] = []; 327 327 try { 328 328 const projectsPath = path.resolve(import.meta.dirname, "../../data/atmosphere-projects.json"); 329 329 const raw = JSON.parse(readFileSync(projectsPath, "utf-8")); 330 - // Flatten: each project gets its talk context 331 - for (const talk of raw) { 332 - for (const proj of talk.projects) { 333 - projects.push({ 334 - name: proj.name, 335 - url: proj.url || null, 336 - talkRkey: talk.talkRkey, 337 - talkTitle: talk.talkTitle, 338 - speakers: talk.speakers, 339 - }); 340 - } 341 - } 330 + // Enrich with talk titles 331 + const talkTitles = new Map<string, string>(); 332 + const talkRows = db.prepare("SELECT rkey, title FROM talks").all() as any[]; 333 + for (const t of talkRows) talkTitles.set(t.rkey, t.title); 334 + projects = raw.map((p: any) => ({ 335 + ...p, 336 + talkTitle: talkTitles.get(p.talkRkey) || p.name, 337 + })); 342 338 } catch {} 343 339 344 340 // Posts: content_type = 'post' or NULL, top-level only, sorted by likes DESC