// components/pricing/ComparisonTable.tsx import { Plan } from "./types"; import { CheckIcon, MinusIcon } from "./icons"; const rows: { label: string; keys: Array }[] = [ { label: "Email deliverability monitoring", keys: [] }, { label: "Automated backups", keys: [] }, { label: "Restore test cadence", keys: [] }, { label: "Cloudflare WAF & bot tuning", keys: [] }, { label: "Web Vitals reporting", keys: [] }, { label: "On-call paging", keys: [] }, { label: "First response SLA", keys: [] }, { label: "Uptime target", keys: [] }, ]; export default function ComparisonTable({ plans }: { plans: Plan[] }) { // Hard-code feature mapping for clarity (keeps copy outcome-driven) const matrix: Record string | boolean> = { "Email deliverability monitoring": () => true, "Automated backups": () => true, "Restore test cadence": (id) => id === "essential" ? "Quarterly" : id === "growth" ? "Quarterly" : "Monthly", "Cloudflare WAF & bot tuning": (id) => id !== "essential", "Web Vitals reporting": (id) => (id === "growth" || id === "mission" ? "Monthly" : false), "On-call paging": (id) => (id === "mission" ? "24/7" : false), "First response SLA": (id) => id === "essential" ? "NBD (8×5)" : id === "growth" ? "4h (8×5)" : "1h (24/7)", "Uptime target": (id) => id === "essential" ? "99.9%" : id === "growth" ? "99.95%" : "99.99%", }; const features = Object.keys(matrix); return (

What’s inside each plan

Outcome-driven features, not laundry lists.

{plans.map((p) => ( ))} {features.map((feature) => ( {plans.map((p) => { const val = matrix[feature](p.id); const isBool = typeof val === "boolean"; return ( ); })} ))}
Feature {p.name}
{feature} {isBool ? ( val ? ( ) : ( ) ) : ( {val as string} )}
“Uptime target” refers to target SLO over a rolling 30-day period. Credits apply if response SLAs are missed.
); }