Render thread pages on the server

This commit is contained in:
dtonon 2026-08-17 18:29:26 +01:00
parent 40e0be35d9
commit c23428f904
4 changed files with 32 additions and 3 deletions

2
src/app.d.ts vendored
View file

@ -1,6 +1,7 @@
// See https://svelte.dev/docs/kit/types#app.d.ts // See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces // for information about these interfaces
import type { ForumShell, Profiles } from "$lib/forum/snapshot"; import type { ForumShell, Profiles } from "$lib/forum/snapshot";
import type { ThreadDetail } from "$lib/forum/thread";
declare global { declare global {
namespace App { namespace App {
@ -10,6 +11,7 @@ declare global {
interface PageData { interface PageData {
shell?: ForumShell | null; shell?: ForumShell | null;
profiles?: Profiles | null; profiles?: Profiles | null;
thread?: ThreadDetail | null;
} }
// interface PageState {} // interface PageState {}
// interface Platform {} // interface Platform {}

View file

@ -1,4 +1,5 @@
import { loadNostrUser, type NostrUser } from "$lib/gadgets"; import { loadNostrUser, type NostrUser } from "$lib/gadgets";
import { page } from "$app/state";
import { RELAY_URL, GROUP_ID } from "$lib/config"; import { RELAY_URL, GROUP_ID } from "$lib/config";
import { queryForum, publishForum } from "$lib/relay"; import { queryForum, publishForum } from "$lib/relay";
import { threads as mockThreads } from "$lib/mock"; import { threads as mockThreads } from "$lib/mock";
@ -26,15 +27,18 @@ let profiles = $state<Record<string, NostrUser>>({});
// in a private group the current (non-member) user can't read. // in a private group the current (non-member) user can't read.
let status = $state<"loading" | "ready" | "notfound">("loading"); let status = $state<"loading" | "ready" | "notfound">("loading");
// Until the live fetch lands, the server snapshot (if any) stands in. Its
// profiles stay as a base layer: the live ones arrive one by one.
export const threadDetailStore = { export const threadDetailStore = {
get detail() { get detail() {
return detail; return detail ?? page.data.thread ?? null;
}, },
get profiles() { get profiles() {
return profiles; const base = page.data.profiles;
return base ? { ...base, ...profiles } : profiles;
}, },
get status() { get status() {
return status; return status === "loading" && page.data.thread ? "ready" : status;
}, },
}; };

View file

@ -0,0 +1,13 @@
import { error, json } from "@sveltejs/kit";
import { GROUP_ID } from "$lib/config";
import { fetchThread, threadAuthors } from "$lib/forum/thread";
import { fetchProfiles } from "$lib/forum/profiles";
import { forumQuery, profileQuery } from "$lib/ssr/relay";
export async function GET({ params }) {
if (!/^[0-9a-f]{64}$/.test(params.id)) error(404, "Not found");
const thread = await fetchThread(forumQuery, params.id, GROUP_ID);
if (!thread) error(404, "Not found");
const profiles = await fetchProfiles(profileQuery, threadAuthors(thread));
return json({ thread, profiles });
}

View file

@ -0,0 +1,10 @@
import { snapshot, type Profiles } from "$lib/forum/snapshot";
import type { ThreadDetail } from "$lib/forum/thread";
export async function load({ fetch, params }) {
const data = await snapshot<{ thread: ThreadDetail; profiles: Profiles }>(
fetch,
`/api/thread/${params.id}`,
);
return { thread: data?.thread ?? null, profiles: data?.profiles ?? null };
}