Something went wrong. Try again.
My website.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145const 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 `<article class="room-card ${roomClass(room.name)}" id="${escapeHtml(room.name.replace("void/", ""))}"> <div class="room-head"><span>${escapeHtml(ROOM_LABELS[room.name] ?? room.name)}</span><code>${escapeHtml(room.name)}</code></div> <h2>${escapeHtml(room.displayName ?? room.name)}</h2> <p>${escapeHtml(room.purpose)}</p> <div class="counts"><span>${counts.states ?? 0} states</span><span>${counts.actions ?? 0} actions</span><span>${counts.submissions ?? 0} submissions</span><span>${counts.artifacts ?? 0} artifacts</span></div> <div class="state"><strong>Latest state</strong><p>${escapeHtml(latest.summary ?? "No state snapshot yet.")}</p></div> </article>`;}
function recordCard(record) { const room = recordRoom(record); return `<article class="record-card ${roomClass(room)}"> <div class="record-meta"><span>${escapeHtml(KIND_LABELS[record.kind] ?? record.kind)}</span><span>${escapeHtml(room)}</span><time>${escapeHtml(formatDate(record.createdAt))}</time></div> <h3>${escapeHtml(recordTitle(record))}</h3> <p>${escapeHtml(truncate(recordText(record)))}</p> <details> <summary>record value</summary> <pre>${escapeHtml(JSON.stringify(record.value, null, 2))}</pre> </details> <code>${escapeHtml(shortUri(record.uri))}</code> </article>`;}
function blockers(data) { const items = data.blockers ?? []; if (!items.length) return ""; return `<section class="panel"> <div class="section-label">needs attention</div> <ul>${items.map((item) => `<li><strong>${escapeHtml(item.room)}</strong> ${escapeHtml(item.text)}</li>`).join("")}</ul> </section>`;}
function render(data) { const records = allRecords(data).slice(0, 18); app.innerHTML = `<nav class="topbar" aria-label="Void site navigation"> <a href="../">void.tngl.io</a> <a href="#rooms">rooms</a> <a href="#records">records</a> <a href="../#route">signal</a> </nav> <section class="intro"> <p class="eyebrow">${escapeHtml(data.namespace)}</p> <h1>Void room records.</h1> <p>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.</p> <div class="meta"><span>${data.rooms?.length ?? 0} rooms</span><span>${totalRecords(data.counts)} records</span><span>generated ${escapeHtml(formatDate(data.generatedAt))}</span><span>PDS ${escapeHtml(data.pdsHost)}</span></div> </section> <section class="rooms" id="rooms">${(data.rooms ?? []).map(roomCard).join("")}</section> ${blockers(data)} <section class="panel" id="records"> <div class="section-label">recent records</div> <div class="records">${records.map(recordCard).join("")}</div> </section> <p class="footer">${escapeHtml(data.note ?? "")}</p>`;}
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 = `<section class="intro"><p class="eyebrow">network.comind.void.*</p><h1>Could not load records.</h1><p>${escapeHtml(error.message)}</p></section>`; }}
main();