const app = document.querySelector("#app"); const ROOM_LABELS = { "void/research": "Research", "void/art": "Art", "void/homelab": "Homelab", }; const KIND_LABELS = { roomDefinitions: "definition", roomStates: "state", submissions: "submission", artifacts: "artifact", actions: "action", moderation: "moderation", digests: "digest", provenance: "provenance", }; function escapeHtml(value) { return String(value ?? "") .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function formatDate(value) { if (!value) return "undated"; const date = new Date(value); if (Number.isNaN(date.getTime())) return value; return date.toLocaleString(undefined, { year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit" }); } function recordText(record) { const value = record?.value ?? {}; return value.summary ?? value.text ?? value.purpose ?? value.body ?? value.action ?? value.method ?? value.status ?? JSON.stringify(value, null, 2); } function recordRoom(record) { return record?.value?.room ?? record?.value?.scope ?? "network"; } function recordTitle(record) { const value = record?.value ?? {}; return value.title ?? value.action ?? value.status ?? KIND_LABELS[record.kind] ?? "record"; } function truncate(value, max = 360) { const text = String(value ?? "").trim(); if (text.length <= max) return text; return `${text.slice(0, max).trim()}…`; } function shortUri(uri) { return String(uri ?? "").split("/").at(-1) || uri; } function totalRecords(counts = {}) { return Object.values(counts).reduce((sum, value) => sum + Number(value ?? 0), 0); } function allRecords(data) { const records = []; for (const room of data.rooms ?? []) records.push(...(room.timeline ?? [])); records.push(...(data.recent ?? [])); const byUri = new Map(); for (const record of records) byUri.set(record.uri, record); return [...byUri.values()].sort((a, b) => new Date(b.createdAt ?? 0) - new Date(a.createdAt ?? 0)); } function roomClass(name) { return `room-${String(name ?? "network").replace("void/", "").replace(/[^a-z0-9-]/gi, "-")}`; } function roomCard(room) { const latest = room.latestState?.value ?? {}; const counts = room.counts ?? {}; return `
${escapeHtml(ROOM_LABELS[room.name] ?? room.name)}${escapeHtml(room.name)}

${escapeHtml(room.displayName ?? room.name)}

${escapeHtml(room.purpose)}

${counts.states ?? 0} states${counts.actions ?? 0} actions${counts.submissions ?? 0} submissions${counts.artifacts ?? 0} artifacts
Latest state

${escapeHtml(latest.summary ?? "No state snapshot yet.")}

`; } function recordCard(record) { const room = recordRoom(record); return `
${escapeHtml(KIND_LABELS[record.kind] ?? record.kind)}${escapeHtml(room)}

${escapeHtml(recordTitle(record))}

${escapeHtml(truncate(recordText(record)))}

record value
${escapeHtml(JSON.stringify(record.value, null, 2))}
${escapeHtml(shortUri(record.uri))}
`; } function blockers(data) { const items = data.blockers ?? []; if (!items.length) return ""; return `
needs attention
`; } function render(data) { const records = allRecords(data).slice(0, 18); app.innerHTML = `

${escapeHtml(data.namespace)}

Void room records.

This page is the plain data browser: room state, open seams, and recent canonical records. The main site explains the experience; this page keeps the trail inspectable.

${data.rooms?.length ?? 0} rooms${totalRecords(data.counts)} recordsgenerated ${escapeHtml(formatDate(data.generatedAt))}PDS ${escapeHtml(data.pdsHost)}
${(data.rooms ?? []).map(roomCard).join("")}
${blockers(data)}
recent records
${records.map(recordCard).join("")}
`; } async function main() { try { const response = await fetch("./data.json", { cache: "no-store" }); if (!response.ok) throw new Error(`data.json returned HTTP ${response.status}`); render(await response.json()); } catch (error) { app.innerHTML = `

network.comind.void.*

Could not load records.

${escapeHtml(error.message)}

`; } } main();