A SQL-rendered record of everyone who passed through. Entries are stored in PostgreSQL and assembled into this page on every request. There are 0 signatures.
-- ═══════════════════════════════════════════════════════════ -- THE GUESTBOOK — A SQL-rendered visitor record -- ═══════════════════════════════════════════════════════════ WITH -- ─── STYLES ────────────────────────────────────────────────── styles AS ( SELECT $css$ @import url('https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&family=Space+Mono:wght@400;700&display=swap'); :root { --bg: #0d0d10; --surface: #13131a; --fg: #f0ede6; --muted: #7a7870; --accent: #c8a96e; --border: rgba(200,169,110,0.18); } *, *::before, *::after { margin:0; padding:0; box-sizing:border-box; } html { scroll-behavior:smooth; } body { background:var(--bg); color:var(--fg); font-family:'EB Garamond',Georgia,serif; font-size:18px; line-height:1.6; } a { color:inherit; text-decoration:none; } nav { display:flex; justify-content:space-between; align-items:center; padding:1.4rem 4rem; border-bottom:1px solid var(--border); position:sticky; top:0; background:rgba(13,13,16,0.94); backdrop-filter:blur(12px); z-index:100; } .logo { font-family:'Space Mono',monospace; font-size:.8rem; letter-spacing:.22em; color:var(--accent); } .nav-links a { font-family:'Space Mono',monospace; font-size:.65rem; letter-spacing:.14em; margin-left:2rem; color:var(--muted); transition:color .2s; } .nav-links a:hover { color:var(--fg); } .gb-header { padding:6rem 4rem 4rem; border-bottom:1px solid var(--border); } .gb-eye { display:block; font-family:'Space Mono',monospace; font-size:.62rem; letter-spacing:.3em; color:var(--accent); text-transform:uppercase; margin-bottom:2rem; } .gb-title { font-size:clamp(3rem,7vw,6.5rem); font-weight:400; line-height:1.0; letter-spacing:-.03em; margin-bottom:1.5rem; } .gb-title em { font-style:italic; color:var(--accent); } .gb-sub { font-size:1.2rem; color:var(--muted); max-width:520px; line-height:1.8; } .stats-bar { display:grid; grid-template-columns:repeat(4,1fr); border-bottom:1px solid var(--border); } .stat { padding:2.2rem 2rem; border-right:1px solid var(--border); display:flex; flex-direction:column; gap:.4rem; } .stat:last-child { border-right:none; } .stat-val { font-size:2.2rem; line-height:1; letter-spacing:-.03em; } .stat-lbl { font-family:'Space Mono',monospace; font-size:.58rem; letter-spacing:.16em; color:var(--muted); text-transform:uppercase; } .stat-mono { font-family:'Space Mono',monospace !important; font-size:1rem !important; } .entries { padding:0; } .entry { padding:2.2rem 4rem; border-bottom:1px solid var(--border); display:grid; grid-template-columns:auto 1fr; gap:3rem; align-items:baseline; } .entry:hover { background:var(--surface); } .entry-meta { text-align:right; min-width:160px; } .entry-num { display:block; font-family:'Space Mono',monospace; font-size:.58rem; letter-spacing:.2em; color:var(--accent); margin-bottom:.4rem; } .entry-ts { display:block; font-family:'Space Mono',monospace; font-size:.6rem; letter-spacing:.08em; color:var(--muted); line-height:1.6; } .entry-name { font-size:1.35rem; letter-spacing:-.01em; display:block; margin-bottom:.35rem; } .entry-note { font-size:1rem; color:var(--muted); line-height:1.75; font-style:italic; max-width:600px; } .no-entries { padding:6rem 4rem; color:var(--muted); font-size:1.1rem; font-style:italic; border-bottom:1px solid var(--border); } .sign-section { padding:5rem 4rem 7rem; max-width:640px; } .sign-eye { font-family:'Space Mono',monospace; font-size:.62rem; letter-spacing:.28em; color:var(--accent); text-transform:uppercase; display:block; margin-bottom:2rem; } .sign-title { font-size:clamp(2rem,4vw,3.2rem); font-weight:400; letter-spacing:-.02em; margin-bottom:2.5rem; } .sign-title em { font-style:italic; } .field { display:flex; flex-direction:column; gap:.6rem; margin-bottom:1.6rem; } .field label { font-family:'Space Mono',monospace; font-size:.6rem; letter-spacing:.18em; color:var(--muted); text-transform:uppercase; } .field input, .field textarea { background:var(--surface); border:1px solid var(--border); color:var(--fg); font-family:'EB Garamond',serif; font-size:1.1rem; padding:.75rem 1rem; outline:none; width:100%; resize:vertical; transition:border-color .2s; } .field input::placeholder, .field textarea::placeholder { color:var(--muted); font-style:italic; } .field input:focus, .field textarea:focus { border-color:rgba(200,169,110,.45); } .field textarea { min-height:100px; } .sign-btn { font-family:'Space Mono',monospace; font-size:.72rem; letter-spacing:.14em; padding:.85rem 2.2rem; border:1px solid var(--accent); color:var(--accent); background:transparent; cursor:pointer; transition:all .25s; } .sign-btn:hover { background:var(--accent); color:var(--bg); } footer { display:flex; justify-content:space-between; align-items:center; padding:1.8rem 4rem; border-top:1px solid var(--border); } footer span { font-family:'Space Mono',monospace; font-size:.62rem; letter-spacing:.12em; color:var(--muted); } .pg-badge { color:var(--accent) !important; } #sql-toggle-btn { font-family:'Space Mono',monospace; font-size:.65rem; letter-spacing:.14em; margin-left:1.8rem; color:var(--accent); background:none; border:none; cursor:pointer; padding:0; transition:opacity .2s; } #sql-toggle-btn:hover { opacity:.7; } #sql-panel { position:fixed; inset:0; z-index:999; background:var(--bg); display:flex; flex-direction:column; transform:translateY(100%); transition:transform .38s cubic-bezier(.4,0,.2,1); overflow:hidden; } #sql-panel.open { transform:translateY(0); } #sql-panel-header { display:flex; justify-content:space-between; align-items:center; padding:1.2rem 4rem; border-bottom:1px solid var(--border); background:rgba(13,13,16,.96); backdrop-filter:blur(12px); flex-shrink:0; } #sql-panel-filename { font-family:'Space Mono',monospace; font-size:.65rem; letter-spacing:.22em; color:var(--accent); text-transform:uppercase; } #sql-panel-close { font-family:'Space Mono',monospace; font-size:.65rem; letter-spacing:.14em; color:var(--muted); background:none; border:none; cursor:pointer; transition:color .2s; } #sql-panel-close:hover { color:var(--fg); } #sql-panel-body { flex:1; overflow-y:auto; padding:2.5rem 4rem 4rem; } #sql-panel-pre { font-family:'Space Mono',monospace; font-size:.72rem; line-height:1.85; white-space:pre-wrap; word-break:break-word; color:#bbb; background:none; border:none; padding:0; margin:0; } .sk { color:#c8a96e; font-weight:700; } .ss { color:#a8c97f; } .sc { color:#4a5060; font-style:italic; } .sn { color:#79b8e0; } @media (max-width:768px) { nav { padding:1.2rem 1.5rem; } .nav-links a { margin-left:1rem; font-size:.58rem; } #sql-toggle-btn { margin-left:1rem; font-size:.58rem; } #sql-panel-header { padding:1rem 1.5rem; } #sql-panel-body { padding:1.5rem; } #sql-panel-pre { font-size:.6rem; } .gb-header { padding:3.5rem 1.5rem 2.5rem; } .stats-bar { grid-template-columns:1fr 1fr; } .stat { padding:1.8rem 1.2rem; } .stat:nth-child(2) { border-right:none; } .stat:nth-child(3) { border-right:1px solid var(--border); border-top:1px solid var(--border); } .stat:nth-child(4) { border-right:none; border-top:1px solid var(--border); } .entry { grid-template-columns:1fr; gap:0; padding:2rem 1.5rem; } .entry-meta { text-align:left; display:flex; gap:1.5rem; align-items:baseline; margin-bottom:.8rem; } .entry-ts { display:inline; } .sign-section { padding:3rem 1.5rem 5rem; } footer { padding:1.5rem; flex-direction:column; gap:.6rem; text-align:center; } } $css$ AS css ), -- ─── STATS ─────────────────────────────────────────────────── gb_stats AS ( SELECT count(*)::int AS total, count(*) FILTER ( WHERE created_at > now() - interval '24 hours' )::int AS today, coalesce(to_char(min(created_at) AT TIME ZONE 'UTC', 'DD Mon YYYY'), '—') AS first_date, coalesce(to_char(max(created_at) AT TIME ZONE 'UTC', 'DD Mon YYYY'), '—') AS last_date FROM guestbook ), -- ─── ENTRIES ───────────────────────────────────────────────── entry_rows AS ( SELECT id, name, note, created_at, row_number() OVER (ORDER BY created_at ASC) AS entry_num FROM guestbook ORDER BY created_at DESC ), entries_html AS ( SELECT coalesce( string_agg( '<div class="entry">' || '<div class="entry-meta">' || '<span class="entry-num">#' || lpad(entry_num::text, 4, '0') || '</span>' || '<span class="entry-ts">' || to_char(created_at AT TIME ZONE 'UTC', 'DD Mon YYYY') || '<br>' || to_char(created_at AT TIME ZONE 'UTC', 'HH24:MI') || ' UTC</span></div>' || '<div class="entry-body">' || '<span class="entry-name">' || replace(replace(replace(replace(name,'&','&'),'<','<'),'>','>'),'"','"') || '</span>' || CASE WHEN note IS NOT NULL AND trim(note) != '' THEN '<p class="entry-note">' || replace(replace(replace(replace(trim(note),'&','&'),'<','<'),'>','>'),'"','"') || '</p>' ELSE '' END || '</div></div>', '' ORDER BY created_at DESC ), '<div class="no-entries">No entries yet. Be the first.</div>' ) AS html FROM entry_rows ), -- ─── NAV ───────────────────────────────────────────────────── nav AS ( SELECT '<nav>' || '<span class="logo">THE GUESTBOOK</span>' || '<div class="nav-links">' || '<a href="/">← Studio Null</a>' || '<a href="/chronolith">Chronolith</a>' || '<button id="sql-toggle-btn" onclick="toggleSQL()">[ sql ]</button>' || '</div>' || '</nav>' AS html ), -- ─── HEADER ────────────────────────────────────────────────── header AS ( SELECT '<div class="gb-header">' || '<span class="gb-eye">Experiment 02 — Studio Null</span>' || '<h1 class="gb-title">The<br><em>Guestbook</em></h1>' || '<p class="gb-sub">A SQL-rendered record of everyone who passed through. ' || 'Entries are stored in PostgreSQL and assembled into this page on every request. ' || 'There are ' || total || ' signatures.</p>' || '</div>' AS html FROM gb_stats ), -- ─── STATS BAR ─────────────────────────────────────────────── stats_bar AS ( SELECT '<div class="stats-bar">' || '<div class="stat"><span class="stat-val">' || total || '</span><span class="stat-lbl">Total Entries</span></div>' || '<div class="stat"><span class="stat-val">' || today || '</span><span class="stat-lbl">Signed Today</span></div>' || '<div class="stat"><span class="stat-val stat-mono">' || first_date || '</span><span class="stat-lbl">First Entry</span></div>' || '<div class="stat"><span class="stat-val stat-mono">' || last_date || '</span><span class="stat-lbl">Most Recent</span></div>' || '</div>' AS html FROM gb_stats ), -- ─── SIGN FORM ─────────────────────────────────────────────── sign_form AS ( SELECT '<div class="sign-section" id="sign">' || '<span class="sign-eye">— Leave your mark</span>' || '<h2 class="sign-title">Sign the<br><em>guestbook</em></h2>' || '<form method="POST" action="/guestbook/sign">' || '<div class="field"><label for="gb-name">Your name</label>' || '<input id="gb-name" name="name" type="text" placeholder="What do they call you?" maxlength="80" required autocomplete="off"></div>' || '<div class="field"><label for="gb-note">A note (optional)</label>' || '<textarea id="gb-note" name="note" placeholder="Something brief. Or not." maxlength="500"></textarea></div>' || '<button type="submit" class="sign-btn">Sign the guestbook →</button>' || '</form></div>' AS html ), -- ─── FOOTER ────────────────────────────────────────────────── footer AS ( SELECT '<footer>' || '<span>The Guestbook · Studio Null</span>' || '<span class="pg-badge">« Generated live by PostgreSQL ' || current_setting('server_version') || ' in __QUERY_MS__ms »</span>' || '</footer>' AS html ), -- ─── ASSEMBLE ──────────────────────────────────────────────── page AS ( SELECT '<!DOCTYPE html><html lang="en"><head>' || '<meta charset="UTF-8">' || '<meta name="viewport" content="width=device-width,initial-scale=1.0">' || '<title>The Guestbook — Studio Null</title>' || '<link rel="icon" type="image/svg+xml" href="/favicon.svg">' || '<style>' || styles.css || '</style>' || '</head><body>' || nav.html || header.html || stats_bar.html || '<div class="entries">' || entries_html.html || '</div>' || sign_form.html || footer.html || '__SQL_PANEL__' || '</body></html>' AS html FROM styles, nav, header, stats_bar, entries_html, sign_form, footer ) SELECT html FROM page;