/engineeringEngineering dashboard
A delivery page: deploy frequency, lead time, change failure rate and time to restore, production deploys a week, the last releases on a timeline, every environment's recent deployments, and the pull requests still waiting for review.
The page is a server component inside AppShell; only the frequency chart crosses into the client, because a chart formats its own axis labels. db.deployments is the whole pipeline history, and three of the four headline numbers fall straight out of it: how often production ships, how often a production deploy fails, and how long the next green deploy takes after a red one. The two things the entity does not record are derived, not written out — lead time is a rule over the row (main ships within hours, a feature branch within days, jittered per row by seeded("engineering-overview")), and the open pull requests are generated once from the same generator over the branches in db.deployments and the people in db.members. Composes AppShell, PageHeader, StatCardGroup, StatCard, DashboardGrid, ChartCard, BarChart, Widget, Timeline, SimpleTable and StatusBadge.
Preview
import { REFERENCE_DATE } from "@/lib/sample-data"
import { AppShell } from "@/components/ui/app-shell"
import { DashboardGrid, DashboardGridItem } from "@/components/ui/dashboard-grid"
import { PageHeader } from "@/components/ui/page-header"
import { signOut } from "./actions"
import { DeployFrequency } from "./components/deploy-frequency"
import { DeploysTimeline } from "./components/deploys-timeline"
import { EngineeringStats } from "./components/engineering-stats"
import { OpenPrs } from "./components/open-prs"
import { RecentDeployments } from "./components/recent-deployments"
import { currentUser, deploysByWeek, shellNotifications, windowLabel, WINDOW_DAYS } from "./data"
import { NAV, ROUTES } from "@/lib/dashboards/engineering/nav"
/**
* The delivery page. It is a server component: the pipeline history is read
* from db on the server, and only the frequency chart crosses into the
* client, because a chart formats its own axis labels — handed its weeks
* already counted, so the store never follows it into the browser.
*/
export default function EngineeringPage() {
return (
<AppShell
nav={NAV}
activeHref={ROUTES.overview}
user={currentUser()}
notifications={shellNotifications()}
now={REFERENCE_DATE}
onSignOut={signOut}
>
<PageHeader
title="Engineering"
description={`How often the last ${WINDOW_DAYS} days shipped, how long a change waited, and what broke.`}
meta={windowLabel()}
/>
<EngineeringStats />
<DashboardGrid>
<DashboardGridItem colSpan={{ base: 12, lg: 8 }}>
<DeployFrequency weeks={deploysByWeek()} />
</DashboardGridItem>
<DashboardGridItem colSpan={{ base: 12, lg: 4 }}>
<DeploysTimeline />
</DashboardGridItem>
<DashboardGridItem colSpan={{ base: 12, lg: 7 }}>
<RecentDeployments />
</DashboardGridItem>
<DashboardGridItem colSpan={{ base: 12, lg: 5 }}>
<OpenPrs />
</DashboardGridItem>
</DashboardGrid>
</AppShell>
)
}Install
npx shadcn@latest add @vibra/engineering-overviewNeeds the @vibra registry in your components.json — set it up once.
Source
import { REFERENCE_DATE } from "@/lib/sample-data"
import { AppShell } from "@/components/ui/app-shell"
import { DashboardGrid, DashboardGridItem } from "@/components/ui/dashboard-grid"
import { PageHeader } from "@/components/ui/page-header"
import { signOut } from "./actions"
import { DeployFrequency } from "./components/deploy-frequency"
import { DeploysTimeline } from "./components/deploys-timeline"
import { EngineeringStats } from "./components/engineering-stats"
import { OpenPrs } from "./components/open-prs"
import { RecentDeployments } from "./components/recent-deployments"
import { currentUser, deploysByWeek, shellNotifications, windowLabel, WINDOW_DAYS } from "./data"
import { NAV, ROUTES } from "@/lib/dashboards/engineering/nav"
/**
* The delivery page. It is a server component: the pipeline history is read
* from db on the server, and only the frequency chart crosses into the
* client, because a chart formats its own axis labels — handed its weeks
* already counted, so the store never follows it into the browser.
*/
export default function EngineeringPage() {
return (
<AppShell
nav={NAV}
activeHref={ROUTES.overview}
user={currentUser()}
notifications={shellNotifications()}
now={REFERENCE_DATE}
onSignOut={signOut}
>
<PageHeader
title="Engineering"
description={`How often the last ${WINDOW_DAYS} days shipped, how long a change waited, and what broke.`}
meta={windowLabel()}
/>
<EngineeringStats />
<DashboardGrid>
<DashboardGridItem colSpan={{ base: 12, lg: 8 }}>
<DeployFrequency weeks={deploysByWeek()} />
</DashboardGridItem>
<DashboardGridItem colSpan={{ base: 12, lg: 4 }}>
<DeploysTimeline />
</DashboardGridItem>
<DashboardGridItem colSpan={{ base: 12, lg: 7 }}>
<RecentDeployments />
</DashboardGridItem>
<DashboardGridItem colSpan={{ base: 12, lg: 5 }}>
<OpenPrs />
</DashboardGridItem>
</DashboardGrid>
</AppShell>
)
}/**
* What this page reads. `db.deployments` is the whole pipeline history, and
* three of the four headline numbers fall straight out of it: how often
* production ships, how often a production deploy fails, and how long the
* next green one takes to arrive after a red one.
*
* Two things the entity does not record are derived, and neither is a literal.
* Lead time is a *rule* over the row db does have — a deploy off `main` was
* cut hours after its commit, a feature branch days, with a jitter fixed by
* `seeded("dashboard-engineering")` so the same deploy always reads the same.
* The open pull requests have no entity at all, so they are generated once
* from the same generator over the branches in `db.deployments` and the people
* in `db.members`. "Now" is `REFERENCE_DATE`; nothing here reads a clock.
*/
import { formatDuration, formatNumber, formatPercent, getInitials } from "@/lib/format"
import {
db,
intBetween,
REFERENCE_DATE,
seeded,
type Deployment,
type Member,
} from "@/lib/sample-data"
export type { Deployment }
const HOUR_MS = 3_600_000
const DAY_MS = 86_400_000
/** The window the four headline numbers are measured over. */
export const WINDOW_DAYS = 30
const WINDOW_START = REFERENCE_DATE.getTime() - WINDOW_DAYS * DAY_MS
// One series for the whole block: one lead time per deployment first, then the
// pull requests.
const SEED = "dashboard-engineering"
const rand = seeded(SEED)
const BY_TIME = db.deployments.all().sort((a, b) => a.startedAt.getTime() - b.startedAt.getTime())
const PRODUCTION = BY_TIME.filter((deployment) => deployment.environment === "production")
// How long a change waits before it ships, in hours: work on main goes out the
// same day, a feature branch takes days. The jitter is drawn once per
// deployment, in time order, so a row's lead time never moves.
const LEAD_HOURS = new Map<string, number>(
BY_TIME.map((deployment) => [
deployment.id,
deployment.branch === "main" ? 2 + rand() * 7 : 14 + rand() * 60,
])
)
/** How long this change waited between its first commit and this deploy. */
export function leadTimeHours(deployment: Deployment): number {
return LEAD_HOURS.get(deployment.id) ?? 0
}
const inWindow = (deployment: Deployment) => deployment.startedAt.getTime() >= WINDOW_START
const median = (values: number[]): number => {
if (values.length === 0) return 0
const sorted = [...values].sort((a, b) => a - b)
return sorted[Math.floor(sorted.length / 2)]
}
/**
* How long production stayed broken: from a failed production deploy inside
* the window to the next successful one, in milliseconds. The recovery itself
* may land outside the window — what is windowed is the failure. A failure
* with nothing green after it is still open and cannot be measured.
*/
function recoveryTimes(): number[] {
const times: number[] = []
PRODUCTION.forEach((deployment, index) => {
if (deployment.status !== "failed" || !inWindow(deployment)) return
const fixed = PRODUCTION.slice(index + 1).find((next) => next.status === "success")
if (!fixed) return
times.push(fixed.startedAt.getTime() - deployment.startedAt.getTime())
})
return times
}
// Below this many incidents a median is one or two readings wearing a
// statistic's clothes, so the card says how many it stands on.
const THIN_SAMPLE = 5
export type EngineeringStat = {
key: string
label: string
value: string
/** Trails the value in quieter type — the sample a thin median stands on. */
note?: string
description: string
}
/** Deploy frequency, lead time, change failure rate and time to restore. */
export function engineeringStats(): EngineeringStat[] {
const shipped = PRODUCTION.filter(inWindow)
// A cancelled deploy never reached production, so it is neither a change
// that shipped nor a change that failed: it leaves the ratio entirely.
const completed = shipped.filter(
(deployment) => deployment.status === "success" || deployment.status === "failed"
)
const failed = completed.filter((deployment) => deployment.status === "failed")
const recoveries = recoveryTimes()
return [
{
key: "frequency",
label: "Deploy frequency",
value: `${formatNumber(shipped.length / WINDOW_DAYS, { maximumFractionDigits: 1 })}/day`,
description: `${shipped.length} production deploys in ${WINDOW_DAYS} days`,
},
{
key: "lead-time",
label: "Lead time",
value: formatDuration(median(shipped.map(leadTimeHours)) * HOUR_MS),
description: "median, first commit to production",
},
{
key: "failure-rate",
label: "Change failure rate",
value: formatPercent(completed.length === 0 ? 0 : failed.length / completed.length, {
maximumFractionDigits: 1,
}),
description: `${failed.length} of ${completed.length} completed deploys failed`,
},
{
key: "mttr",
label: "Time to restore",
value: formatDuration(median(recoveries)),
...(recoveries.length < THIN_SAMPLE
? { note: `${recoveries.length} incident${recoveries.length === 1 ? "" : "s"}` }
: {}),
description: "median, failed deploy to the next green one",
},
]
}
export type WeekPoint = { week: string; succeeded: number; failed: number }
const CHART_WEEKS = 12
const WEEK_LABEL = new Intl.DateTimeFormat("en-US", {
month: "short",
day: "numeric",
timeZone: "UTC",
})
/** Production deploys per week over the last twelve, green against red. */
export function deploysByWeek(): WeekPoint[] {
const end = REFERENCE_DATE.getTime()
return Array.from({ length: CHART_WEEKS }, (_, index) => {
const from = end - (CHART_WEEKS - index) * 7 * DAY_MS
const to = from + 7 * DAY_MS
const week = PRODUCTION.filter(
(deployment) =>
deployment.startedAt.getTime() >= from && deployment.startedAt.getTime() < to
)
return {
week: WEEK_LABEL.format(new Date(from)),
succeeded: week.filter((deployment) => deployment.status === "success").length,
failed: week.filter((deployment) => deployment.status === "failed").length,
}
})
}
/** The last production deploys, newest first. */
export function productionTimeline(limit = 6): Deployment[] {
return [...PRODUCTION].reverse().slice(0, limit)
}
/** The last deploys to any environment, newest first. */
export function recentDeployments(limit = 8): Deployment[] {
return [...BY_TIME].reverse().slice(0, limit)
}
export type PullRequest = {
id: string
number: number
title: string
branch: string
author: Member
additions: number
deletions: number
checks: "passing" | "failing" | "running"
reviews: number
openedAt: Date
}
// How a branch name reads as a pull request title: "feat/sso-login" becomes
// "Sso login". The branch is the record; the sentence is derived from it.
function titleFor(branch: string): string {
const words = branch.split("/").slice(1).join(" ").replace(/-/g, " ")
return words.charAt(0).toUpperCase() + words.slice(1)
}
const PR_COUNT = 6
function generatePullRequests(): PullRequest[] {
// The pull requests come after the lead times in the block's series: that
// part of it is replayed per request, so the authors are the members as they
// are now, a rename or a deactivation included, and every other figure is
// the one it always was.
const rand = seeded(SEED)
for (let drawn = 0; drawn < BY_TIME.length; drawn++) rand()
// Every branch the pipeline has seen, except main, newest first.
const branches = [
...new Set(
[...BY_TIME].reverse().map((deployment) => deployment.branch).filter((branch) => branch !== "main")
),
].slice(0, PR_COUNT)
const authors = db.members.all().filter((member) => member.status === "active")
return branches.map((branch, index) => {
const checks = rand()
return {
id: branch,
number: 1200 + index * intBetween(rand, 3, 19),
title: titleFor(branch),
branch,
author: authors[intBetween(rand, 0, authors.length - 1)],
additions: intBetween(rand, 12, 940),
deletions: intBetween(rand, 4, 420),
checks: checks < 0.68 ? "passing" : checks < 0.86 ? "failing" : "running",
reviews: intBetween(rand, 0, 3),
openedAt: new Date(REFERENCE_DATE.getTime() - intBetween(rand, 2, 260) * HOUR_MS),
}
})
}
/** What is waiting for review, oldest first. */
export function openPullRequests(): PullRequest[] {
return generatePullRequests().sort((a, b) => a.openedAt.getTime() - b.openedAt.getTime())
}
/** How long a deploy took, written out. */
export function deployDuration(deployment: Deployment): string {
return formatDuration(deployment.durationSec * 1000)
}
/** The moment every "ago" on this page is measured against. */
export const NOW = REFERENCE_DATE
/** How long ago something happened, in whole minutes, hours or days. */
export function since(at: Date): string {
const ms = REFERENCE_DATE.getTime() - at.getTime()
if (ms < HOUR_MS) return `${Math.max(1, Math.round(ms / 60_000))}m ago`
return ms < DAY_MS
? `${Math.round(ms / HOUR_MS)}h ago`
: `${Math.round(ms / DAY_MS)}d ago`
}
/** The bell's contents: the newest notifications, unread first in the panel. */
export function shellNotifications() {
return db.notifications
.all()
.sort((a, b) => b.at.getTime() - a.at.getTime())
.slice(0, 6)
.map(({ id, title, description, at, read, href }) => ({ id, title, description, at, read, href }))
}
function ownerRow(): Member {
return db.members.all().find((member) => member.role === "owner") ?? db.members.all()[0]
}
/** The person looking at the page: whoever owns this workspace. */
export function currentUser() {
const owner = ownerRow()
return { name: owner.name, email: owner.email, initials: getInitials(owner.name), avatarUrl: owner.avatarUrl }
}
// Fixed to UTC so the line reads the same wherever the page is rendered.
const WINDOW_LABEL = new Intl.DateTimeFormat("en-US", { dateStyle: "medium", timeZone: "UTC" })
/** The window the headline numbers cover, written out. */
export function windowLabel(): string {
return `${WINDOW_LABEL.format(new Date(WINDOW_START))} – ${WINDOW_LABEL.format(REFERENCE_DATE)} UTC`
}"use server"
import { mockAuthAdapter } from "@/lib/auth-adapter"
import { type Result } from "@/lib/sample-data"
/**
* The one thing this page changes. A server action so the page can stay a
* server component and still hand the shell something to call, and a `Result`
* so the caller reads the same success-or-error shape every mutation returns.
*/
export async function signOut(): Promise<Result<{ signedOut: true }>> {
await mockAuthAdapter.signOut()
return { ok: true, data: { signedOut: true } }
}"use client"
import { formatNumber } from "@/lib/format"
import { BarChart } from "@/components/ui/bar-chart"
import { ChartCard } from "@/components/ui/chart-card"
import { type WeekPoint } from "../data"
// Green against red, in that order, so the eye reads the week's outcome
// before it reads the week's volume.
const SERIES = [
{ key: "succeeded", label: "Succeeded", color: "chart-2" as const },
{ key: "failed", label: "Failed", color: "chart-4" as const },
]
export type DeployFrequencyProps = { weeks: WeekPoint[] }
/** Production deploys a week, green against red. The weeks arrive counted from the server page. */
export function DeployFrequency({ weeks }: DeployFrequencyProps) {
const succeeded = weeks.reduce((total, week) => total + week.succeeded, 0)
const failed = weeks.reduce((total, week) => total + week.failed, 0)
return (
<ChartCard
data-widget="widget-engineering-overview-deploy-frequency"
title="Deploy frequency"
description="Production deploys a week over the last twelve"
height={360}
className="h-full"
footer={`${formatNumber(succeeded, { maximumFractionDigits: 0 })} shipped clean, ${formatNumber(failed, { maximumFractionDigits: 0 })} failed on the way out.`}
>
<BarChart
data={weeks}
index="week"
series={SERIES}
height={360}
showYAxis
valueFormatter={(value) => formatNumber(value, { maximumFractionDigits: 0 })}
/>
</ChartCard>
)
}import { CircleCheckIcon, CircleSlashIcon, CircleXIcon, LoaderIcon } from "lucide-react"
import { Timeline, TimelineItem, type TimelineTone } from "@/components/ui/timeline"
import { Widget } from "@/components/ui/widget"
import { deployDuration, productionTimeline, since, type Deployment } from "../data"
const TONE: Record<Deployment["status"], TimelineTone> = {
success: "success",
failed: "danger",
running: "info",
cancelled: "neutral",
}
const ICON: Record<Deployment["status"], React.ReactNode> = {
success: <CircleCheckIcon />,
failed: <CircleXIcon />,
running: <LoaderIcon />,
cancelled: <CircleSlashIcon />,
}
export function DeploysTimeline() {
const deploys = productionTimeline()
return (
<Widget
data-widget="widget-engineering-overview-deploys-timeline"
title="Production timeline"
description="The last six releases, newest first"
className="h-full"
footer="A cancelled deploy never reached production, so it counts against nothing; a failed one rolled back."
>
<Timeline>
{deploys.map((deployment) => (
<TimelineItem
key={deployment.id}
tone={TONE[deployment.status]}
icon={ICON[deployment.status]}
time={since(deployment.startedAt)}
title={<span className="font-mono">{deployment.sha}</span>}
description={
<span className="flex flex-wrap items-baseline gap-x-2">
<span className="font-mono text-xs">{deployment.branch}</span>
<span>
{deployment.author} · {deployDuration(deployment)}
</span>
</span>
}
/>
))}
</Timeline>
</Widget>
)
}import { StatCard } from "@/components/ui/stat-card"
import { StatCardGroup } from "@/components/ui/stat-card-group"
import { engineeringStats } from "../data"
export function EngineeringStats() {
return (
<StatCardGroup data-widget="widget-engineering-overview-engineering-stats" columns={4}>
{engineeringStats().map((stat) => (
<StatCard
key={stat.key}
label={stat.label}
value={
stat.note ? (
<span className="flex items-baseline gap-1.5">
{stat.value}
<span className="text-sm font-normal text-muted-foreground">· {stat.note}</span>
</span>
) : (
stat.value
)
}
description={stat.description}
/>
))}
</StatCardGroup>
)
}import { formatNumber, getInitials } from "@/lib/format"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { StatusBadge } from "@/components/ui/status-badge"
import { Widget } from "@/components/ui/widget"
import { openPullRequests, since } from "../data"
export function OpenPrs() {
const requests = openPullRequests()
return (
<Widget
data-widget="widget-engineering-overview-open-prs"
title="Open pull requests"
description="Waiting for review, oldest first"
className="h-full"
footer="A pull request with no approvals has been waiting for its first reviewer."
>
<ul className="flex flex-col divide-y">
{requests.map((request) => (
<li key={request.id} className="flex flex-col gap-1 py-3 first:pt-0 last:pb-0">
<div className="flex items-baseline justify-between gap-3">
<span className="flex min-w-0 items-baseline gap-2">
<span className="font-mono text-xs text-muted-foreground">#{request.number}</span>
<span className="truncate text-sm font-medium">{request.title}</span>
</span>
<StatusBadge
status={request.checks}
size="sm"
pulse={request.checks === "running"}
map={{ passing: "success", failing: "danger", running: "info" }}
/>
</div>
<div className="flex flex-wrap items-baseline gap-x-2 text-xs text-muted-foreground">
<span className="font-mono">{request.branch}</span>
<span>·</span>
<span className="inline-flex items-center gap-1.5">
<Avatar className="size-4">
{request.author.avatarUrl ? <AvatarImage src={request.author.avatarUrl} alt="" /> : null}
<AvatarFallback className="text-avatar">{getInitials(request.author.name)}</AvatarFallback>
</Avatar>
{request.author.name}
</span>
<span>·</span>
<span className="tabular-nums">
<span className="text-success">
+{formatNumber(request.additions, { maximumFractionDigits: 0 })}
</span>{" "}
<span className="text-danger">
−{formatNumber(request.deletions, { maximumFractionDigits: 0 })}
</span>
</span>
<span>·</span>
<span className="tabular-nums">
{request.reviews === 0
? "no approvals"
: `${request.reviews} approval${request.reviews === 1 ? "" : "s"}`}
</span>
<span>·</span>
<span className="tabular-nums">{since(request.openedAt)}</span>
</div>
</li>
))}
</ul>
</Widget>
)
}import { SimpleTable, type SimpleTableColumn } from "@/components/ui/simple-table"
import { StatusBadge } from "@/components/ui/status-badge"
import { Widget } from "@/components/ui/widget"
import { deployDuration, recentDeployments, since, type Deployment } from "../data"
const COLUMNS: SimpleTableColumn<Deployment>[] = [
{
key: "sha",
header: "Commit",
cell: (row) => <span className="font-mono text-xs">{row.sha}</span>,
},
{
key: "branch",
header: "Branch",
cell: (row) => <span className="font-mono text-xs">{row.branch}</span>,
},
{ key: "environment", header: "Environment" },
{
key: "status",
header: "Status",
cell: (row) => (
<StatusBadge
status={row.status}
pulse={row.status === "running"}
map={{ success: "success", failed: "danger", running: "info", cancelled: "neutral" }}
/>
),
},
{ key: "author", header: "Author" },
{ key: "duration", header: "Duration", align: "right", cell: (row) => deployDuration(row) },
{ key: "started", header: "Started", align: "right", cell: (row) => since(row.startedAt) },
]
export function RecentDeployments() {
return (
<Widget
data-widget="widget-engineering-overview-recent-deployments"
title="Recent deployments"
description="Every environment, newest first"
className="h-full"
contentClassName="px-0"
footer="Duration is the pipeline run, not the time the change waited to ship."
>
<SimpleTable
columns={COLUMNS}
rows={recentDeployments()}
rowKey="id"
size="sm"
caption="Deployments across every environment"
/>
</Widget>
)
}