'use client';
import { useEffect, useState } from 'react';
import { useAuth } from '@/contexts/AuthContext';
import { Skeleton, SkeletonList } from '@/components/vyndr';
/**
* /desk (Session 63 / A1-S4c) — the founder's daily copy-paste arsenal.
* Auth: gated route + backend email allowlist (DESK_OWNERS). Everything on
* this page is assembled from the pipeline by the VOICE v1.1 template
* engine; per-tweet copy buttons + character counts; the DATA BRIEF block
* pastes into claude.ai for freeform writing. Nothing auto-posts.
*/
interface Variant { label: string; text: string; tweets: string[] }
interface DeskPack {
generated_at: string | null;
formats: {
morning_wire?: Variant[];
signals?: Variant[][];
streak_watch?: Variant[];
settle?: Variant[];
receipts?: Variant[][];
archetype_watch?: Variant[];
line_dispatches?: Variant[][];
};
data_brief?: unknown;
error?: string;
}
function CopyBtn({ text, label = 'COPY' }: { text: string; label?: string }) {
const [done, setDone] = useState(false);
return (
{
void navigator.clipboard.writeText(text).then(() => {
setDone(true);
setTimeout(() => setDone(false), 1200);
});
}}
className="mono"
style={{ cursor: 'pointer', background: done ? 'var(--g-a)' : 'transparent', color: done ? '#06060B' : 'var(--text-1)', border: '1px solid var(--border-hi)', borderRadius: 6, padding: '4px 10px', fontSize: 10, fontWeight: 700, letterSpacing: '0.06em' }}
>
{done ? 'COPIED' : label}
);
}
function VariantBlock({ v }: { v: Variant }) {
return (
{v.label.toUpperCase()}
{v.tweets.map((t, i) => (
{t}
280 ? 'var(--miss)' : 'var(--text-2)' }}>{t.length}/280
))}
);
}
function FormatCard({ title, variants }: { title: string; variants?: Variant[] }) {
if (!variants || variants.length === 0) return null;
return (
{title}
{variants.map((v, i) => )}
);
}
export default function DeskPage() {
const { session } = useAuth();
const [pack, setPack] = useState(null);
const [status, setStatus] = useState<'loading' | 'denied' | 'ready' | 'error'>('loading');
useEffect(() => {
const token = session?.access_token;
if (!token) return;
let active = true;
fetch('/api/desk/pack', { headers: { Authorization: `Bearer ${token}` } })
.then(async (r) => {
if (!active) return;
if (r.status === 403 || r.status === 401) { setStatus('denied'); return; }
const data = (await r.json()) as DeskPack;
setPack(data);
setStatus(data && data.formats ? 'ready' : 'error');
})
.catch(() => { if (active) setStatus('error'); });
return () => { active = false; };
}, [session]);
if (status === 'denied') {
return (
The desk is the publisher’s surface. DESK_OWNERS grants access.
);
}
if (status === 'loading') {
// DS1 (§4) — the pack is assembling; layout-matched skeleton, not a text
// wall. Mirrors the header + stack of FormatCards below.
return (
);
}
if (status !== 'ready' || !pack) {
return (
Pack unavailable. Check back after the first pipeline run.
);
}
const f = pack.formats;
return (
{(f.signals || []).map((v, i) => )}
{(f.line_dispatches || []).map((v, i) => )}
{(f.receipts || []).map((v, i) => )}
{/* DATA BRIEF — paste into claude.ai for freeform Read Room threads. */}
{pack.data_brief != null && (
DATA BRIEF
paste into claude.ai for Read Room + freeform
{JSON.stringify(pack.data_brief, null, 2)}
)}
);
}