Design Library

Deploy list - manifest card

deploy-list-manifest.tsx

componentskill: design-taste-frontendlistdevtooldensedashboard

Variants of deploy-list-2026-q3: deploy-list-ledger, deploy-list-spine

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 one card per push, never per row, shared state stated once in a tinted band, mono for branches, targets and URLs
never 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-manifest.json

Source

Meta block and library type import stripped - this is what pastes cleanly elsewhere.

import { ChevronRight, 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; dot: string; text: string; band: string }> = {
  ready: {
    label: 'READY',
    dot: 'bg-emerald-500',
    text: 'text-emerald-700 dark:text-emerald-400',
    band: 'bg-emerald-50 dark:bg-emerald-950/40',
  },
  error: {
    label: 'ERROR',
    dot: 'bg-red-500',
    text: 'text-red-700 dark:text-red-400',
    band: 'bg-red-50 dark:bg-red-950/40',
  },
  building: {
    label: 'BUILDING',
    dot: 'bg-amber-500',
    text: 'text-amber-800 dark:text-amber-400',
    band: 'bg-amber-50 dark:bg-amber-950/40',
  },
  canceled: {
    label: 'CANCELED',
    dot: 'bg-muted-foreground',
    text: 'text-muted-foreground',
    band: 'bg-muted/50',
  },
}

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' }],
  },
]

/** A run is uniform when every deployment in it settled the same way. */
function uniformState(push: Push): State | null {
  const first = push.deploys[0].state
  return push.deploys.every((d) => d.state === first) ? first : null
}

export default function DeployListManifest() {
  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>

        <div className="mt-8 grid gap-3">
          {PUSHES.map((push) => {
            const uniform = uniformState(push)
            return (
              <article key={push.commit} className="overflow-hidden rounded-[12px] border bg-card">
                {/* Tinted band: state registers as a colour field before a
                    single word is parsed, which is the job of a glance app. */}
                <div
                  className={`border-b px-4 py-3 ${uniform ? STATE[uniform].band : 'bg-muted/50'}`}
                >
                  <div className="flex items-center gap-2">
                    {uniform ? (
                      <>
                        <span
                          className={`size-2 shrink-0 rounded-full ${STATE[uniform].dot}`}
                          aria-hidden
                        />
                        <span
                          className={`font-mono text-[10px] tracking-wider ${STATE[uniform].text}`}
                        >
                          {push.deploys.length > 1
                            ? `${push.deploys.length} ${STATE[uniform].label}`
                            : STATE[uniform].label}
                        </span>
                      </>
                    ) : (
                      <span className="font-mono text-[10px] text-muted-foreground tracking-wider">
                        {push.deploys.length} DEPLOYMENTS
                      </span>
                    )}
                    <span className="ml-auto font-mono text-[11px] text-muted-foreground tabular-nums">
                      {push.when}
                    </span>
                  </div>
                  <h2 className="mt-1.5 font-medium text-[14px] leading-snug tracking-[-0.01em]">
                    {push.commit}
                  </h2>
                  <span className="mt-1 inline-flex items-center gap-1 font-mono text-[11px] text-muted-foreground">
                    <GitBranch className="size-3" aria-hidden />
                    {push.branch}
                  </span>
                </div>

                <ul className="divide-y">
                  {push.deploys.map((d) => (
                    <li key={d.name}>
                      <button
                        type="button"
                        className="flex h-11 w-full items-center gap-3 px-4 text-left transition-[background-color,transform] duration-[160ms] ease-[cubic-bezier(0.23,1,0.32,1)] hover:bg-muted/60 active:scale-[0.99] motion-reduce:transition-none motion-reduce:active:scale-100"
                      >
                        <span className="min-w-0 flex-1 truncate font-medium text-[15px] tracking-[-0.01em]">
                          {d.name}
                        </span>
                        {!uniform && (
                          <span
                            className={`font-mono text-[10px] tracking-wider ${STATE[d.state].text}`}
                          >
                            {STATE[d.state].label}
                          </span>
                        )}
                        {/* Target yields first at narrow widths. Measured at
                            375px, keeping it truncated "customer-portal" to
                            "custo..." - the most important token in the row
                            losing space to the least important one. */}
                        <span className="hidden shrink-0 font-mono text-[11px] text-muted-foreground sm:inline">
                          {d.target}
                        </span>
                        <ChevronRight
                          className="size-3.5 shrink-0 text-muted-foreground"
                          aria-hidden
                        />
                      </button>
                    </li>
                  ))}
                </ul>
              </article>
            )
          })}
        </div>
      </div>
    </div>
  )
}