diff --git a/src/lib/content.ts b/src/lib/content.ts index 00cb9af..14bf5af 100644 --- a/src/lib/content.ts +++ b/src/lib/content.ts @@ -1,6 +1,7 @@ import { env as cfEnv } from "cloudflare:workers"; export interface Note { + id: string; body: string; date: string; } @@ -17,10 +18,13 @@ export interface Project { draft: boolean; } -export const DEFAULT_NOTE: Note = { - body: "rebuilt the site from scratch this weekend. corkboard of badges, a rolling note, the usual webrings. more soon.", - date: "2026-09-06T00:00:00.000Z", -}; +export const DEFAULT_NOTES: Note[] = [ + { + id: "1", + body: "rebuilt the site from scratch this weekend. corkboard of badges, a running log, the usual webrings. more soon.", + date: "2026-09-06T00:00:00.000Z", + }, +]; export const DEFAULT_PROJECTS: Project[] = [ { @@ -154,31 +158,39 @@ function kv(): any { } } -export async function getNote(): Promise { +export async function getNotes(): Promise { const store = kv(); - if (!store) return DEFAULT_NOTE; + if (!store) return DEFAULT_NOTES; let raw: string | null = null; try { - raw = await store.get("note"); + raw = await store.get("notes"); } catch { - return DEFAULT_NOTE; + return DEFAULT_NOTES; + } + if (raw) { + try { + const list = JSON.parse(raw); + if (Array.isArray(list)) return list as Note[]; + } catch { + } } - if (!raw) return DEFAULT_NOTE; try { - const n = JSON.parse(raw); - if (n && typeof n.body === "string") { - return { body: n.body, date: n.date ?? new Date().toISOString() }; + const legacy = await store.get("note"); + if (legacy) { + const n = JSON.parse(legacy); + if (n && typeof n.body === "string") { + return [{ id: "legacy", body: n.body, date: n.date ?? new Date().toISOString() }]; + } } } catch { - return { body: raw, date: new Date().toISOString() }; } - return DEFAULT_NOTE; + return DEFAULT_NOTES; } -export async function setNote(body: string): Promise { +export async function setNotes(list: Note[]): Promise { const store = kv(); if (!store) throw new Error("CONTENT KV namespace is not bound"); - await store.put("note", JSON.stringify({ body, date: new Date().toISOString() })); + await store.put("notes", JSON.stringify(list)); } export async function getProjects(): Promise { diff --git a/src/pages/admin/index.astro b/src/pages/admin/index.astro index 71b5438..39f89fb 100644 --- a/src/pages/admin/index.astro +++ b/src/pages/admin/index.astro @@ -1,15 +1,21 @@ --- import Base from "../../layouts/Base.astro"; import { isAuthed, adminPasswordSet } from "../../lib/session"; -import { getNote, getProjects } from "../../lib/content"; +import { getNotes, getProjects } from "../../lib/content"; const authed = await isAuthed(Astro.request); const loginError = Astro.url.searchParams.has("e"); const noPassword = !adminPasswordSet(); -const note = authed ? await getNote() : null; +const notes = authed + ? (await getNotes()).slice().sort((a, b) => +new Date(b.date) - +new Date(a.date)) + : []; const projects = authed ? await getProjects() : []; const thisYear = String(new Date().getFullYear()); + +const fmtShort = (d: string) => + new Date(d).toLocaleDateString("en-GB", { day: "numeric", month: "short" }); +const preview = (s: string, n = 56) => (s.length > n ? `${s.slice(0, n).trim()}…` : s); --- @@ -43,17 +49,60 @@ const thisYear = String(new Date().getFullYear()); } { - authed && note && ( + authed && ( <> -
- -

note

-