Deploy list - commit spine
deploy-list-spine.tsx
componentskill: design-taste-frontendlistdevtooltimelinedashboard
Variants of deploy-list-2026-q3: deploy-list-ledger, deploy-list-manifest
Brief
The prompt that produced this. Re-run it to generate more in the same taste.
- Aesthetic
- Vercel-native devtool - Geist ramp, hairline rules, mono for machine strings, tight radii, colour spent only on states that need attention
- Reference
- https://vercel.com/dashboard
- Intent
- a deploy list read in ten seconds to answer one question: is anything broken or still building. one monorepo push fans out to N projects, so the same commit must never be printed N times
- Guardrails
- always the fan-out shape is drawn, not implied, one node per push on a continuous spine, mono for branches, targets and URLsnever shadows for structure, card per row, accent as decoration, shared data repeated per row
Install
pnpm dlx shadcn@latest add http://localhost:3040/r/deploy-list-spine.json
Source
Meta block and library type import stripped - this is what pastes cleanly elsewhere.
import { GitBranch } from 'lucide-react'
type State = 'ready' | 'error' | 'building' | 'canceled'
type Deploy = { name: string; target: 'production' | 'preview'; state: State }
type Push = { commit: string; branch: string; when: string; deploys: Deploy[] }
const STATE: Record<State, { label: string; node: string; text: string }> = {
ready: { label: 'READY', node: 'bg-emerald-500', text: 'text-emerald-700 dark:text-emerald-400' },
error: { label: 'ERROR', node: 'bg-red-500', text: 'text-red-700 dark:text-red-400' },
building: { label: 'BUILDING', node: 'bg-amber-500', text: 'text-amber-800 dark:text-amber-400' },
canceled: { label: 'CANCELED', node: 'bg-border', text: 'text-muted-foreground' },
}
const PUSHES: Push[] = [
{
commit: 'fix(api): normalise readyState across list and detail',
branch: 'main',
when: '2m ago',
deploys: [
{ name: 'customer-portal', target: 'production', state: 'building' },
{ name: 'shop', target: 'preview', state: 'ready' },
{ name: 'blog', target: 'preview', state: 'error' },
],
},
{
commit: 'chore(launch): add cost-estimator dev server config',
branch: 'dev',
when: '3h ago',
deploys: [
{ name: 'shop-vivienne', target: 'preview', state: 'canceled' },
{ name: 'pro-landing', target: 'preview', state: 'canceled' },
{ name: 'storybook', target: 'preview', state: 'canceled' },
{ name: 'hadesor-docs', target: 'preview', state: 'canceled' },
],
},
{
commit: 'feat(widget): WidgetKit target reads the shared snapshot',
branch: 'main',
when: '1d ago',
deploys: [{ name: 'website', target: 'production', state: 'ready' }],
},
]
function worstState(push: Push): State {
const rank: State[] = ['error', 'building', 'ready', 'canceled']
return rank.find((s) => push.deploys.some((d) => d.state === s)) ?? 'canceled'
}
export default function DeployListSpine() {
return (
<div className="min-h-[100dvh] bg-background px-4 py-10 sm:px-8">
<div className="mx-auto max-w-3xl">
<h1 className="font-semibold text-2xl tracking-[-0.03em]">Deployments</h1>
<p className="mt-1 text-muted-foreground text-sm">Three pushes, eight deployments.</p>
{/* The spine draws the thing the flat list hides: one commit, N targets.
The vertical rule is the branch, each node is a push. */}
<ol className="mt-8 space-y-8">
{PUSHES.map((push) => {
const worst = worstState(push)
return (
<li key={push.commit} className="relative pl-7">
<span
className="absolute top-2 bottom-[-2rem] left-[5px] w-px bg-border last:hidden"
aria-hidden
/>
<span
className={`absolute top-1.5 left-0 size-[11px] rounded-full ring-4 ring-background ${STATE[worst].node}`}
aria-hidden
/>
<h2 className="font-medium text-[15px] leading-snug tracking-[-0.01em]">
{push.commit}
</h2>
<div className="mt-1 flex flex-wrap items-center gap-x-3 font-mono text-[11px] text-muted-foreground tabular-nums">
<span className="inline-flex items-center gap-1">
<GitBranch className="size-3" aria-hidden />
{push.branch}
</span>
<span>{push.when}</span>
</div>
<div className="mt-3 flex flex-wrap gap-2">
{push.deploys.map((d) => (
<button
key={d.name}
type="button"
className="group inline-flex items-center gap-2 rounded-[6px] border py-1.5 pr-2.5 pl-2 transition-[background-color,transform] duration-[160ms] ease-[cubic-bezier(0.23,1,0.32,1)] hover:bg-muted/60 active:scale-[0.97] motion-reduce:transition-none motion-reduce:active:scale-100"
>
<span
className={`size-1.5 shrink-0 rounded-full ${STATE[d.state].node}`}
aria-hidden
/>
<span className="font-medium text-[13px] tracking-[-0.01em]">{d.name}</span>
<span className="font-mono text-[10px] text-muted-foreground">
{d.target === 'production' ? 'prod' : 'prev'}
</span>
<span
className={`font-mono text-[9px] tracking-wider ${STATE[d.state].text}`}
>
{STATE[d.state].label}
</span>
</button>
))}
</div>
</li>
)
})}
</ol>
</div>
</div>
)
}