# Beacon: launch site from blocks

> A four-page product site assembled entirely from Ballmac blocks (Hero6, Stats1, Features5, Testimonials2, Cta3, Pricing2, Pricing3, Faq2, Changelog1, Contact1) in one palette, so any section can be swapped for another block.

A shadcn/ui block from the [@ballmac](https://ui.ballmac.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/ballmac/template-launch).

- Page, with a live preview: https://shadcn.exchange/r/ballmac/template-launch
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/ballmac/template-launch-light-fcb7ba5f199669fe.png
- Registry item: https://ui.ballmac.com/r/template-launch.json
- Categories: templates
- Listed: 2026-10-14, source last changed 2026-10-14

## Install

```bash
npx shadcn@latest add https://ui.ballmac.com/r/template-launch.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`
- Registry items: `utils`, `https://ui.ballmac.com/r/header-2.json`, `https://ui.ballmac.com/r/footer-2.json`, `https://ui.ballmac.com/r/hero-6.json`, `https://ui.ballmac.com/r/logo-cloud-1.json`, `https://ui.ballmac.com/r/stats-1.json`, `https://ui.ballmac.com/r/features-5.json`, `https://ui.ballmac.com/r/testimonials-2.json`, `https://ui.ballmac.com/r/cta-3.json`, `https://ui.ballmac.com/r/pricing-2.json`, `https://ui.ballmac.com/r/pricing-3.json`, `https://ui.ballmac.com/r/faq-2.json`, `https://ui.ballmac.com/r/changelog-1.json`, `https://ui.ballmac.com/r/contact-1.json`

## Notes from the registry

Pages are at /launch, /launch/pricing, /launch/changelog and /launch/contact. Each page is LaunchShell (header, footer, palette) around Ballmac blocks: change copy through the blocks' props, reorder them, or swap any block for another in the same category. Edit launchCss in launch-theme.tsx for the palette.

## Files

### `registry/ballmac/components/templates/launch/launch-fonts.ts`

```ts
// Ballmac UI: Launch template fonts. https://ui.ballmac.com/templates/template-launch
import { Geist_Mono, Schibsted_Grotesk } from "next/font/google"

export const launchSans = Schibsted_Grotesk({ variable: "--launch-sans", subsets: ["latin"], display: "swap", preload: false })
export const launchMono = Geist_Mono({ variable: "--launch-mono", subsets: ["latin"], display: "swap", preload: false })
```

### `registry/ballmac/components/templates/launch/launch-theme.tsx`

```tsx
// Ballmac UI: Launch template shell. https://ui.ballmac.com/templates/template-launch
"use client"

import * as React from "react"
import { Globe, Mail } from "lucide-react"

import { Footer2 } from "@/components/ballmac/blocks/footer-2/footer-2"
import { Header2 } from "@/components/ballmac/blocks/header-2/header-2"
import { launchMono, launchSans } from "@/components/ballmac/templates/launch/launch-fonts"
import { cn } from "@/lib/utils"

type LaunchPage = "home" | "pricing" | "changelog" | "contact"
type LaunchHrefs = Record<LaunchPage, string>

const defaultHrefs: LaunchHrefs = { home: "/launch", pricing: "/launch/pricing", changelog: "/launch/changelog", contact: "/launch/contact" }

/** Beacon's palette: warm paper, graphite ink and one electric violet. Dark mode is graphite with the violet turned up. */
const launchCss = `
.launch-theme,body:not(:has([data-gallery])):has(.launch-theme){--background:oklch(0.985 0.006 85);--foreground:oklch(0.2 0.02 285);--card:oklch(1 0 0);--card-foreground:oklch(0.2 0.02 285);--popover:oklch(1 0 0);--popover-foreground:oklch(0.2 0.02 285);--primary:oklch(0.5 0.24 285);--primary-foreground:oklch(0.99 0.005 285);--secondary:oklch(0.95 0.012 85);--secondary-foreground:oklch(0.2 0.02 285);--muted:oklch(0.955 0.01 85);--muted-foreground:oklch(0.46 0.03 285);--accent:oklch(0.94 0.025 290);--accent-foreground:oklch(0.2 0.02 285);--border:oklch(0.2 0.02 285 / 12%);--input:oklch(0.2 0.02 285 / 20%);--ring:oklch(0.55 0.22 285);--surface:oklch(0.968 0.01 85);--destructive:oklch(0.52 0.21 27);--chart-1:oklch(0.5 0.24 285);--chart-2:oklch(0.7 0.17 160);--chart-3:oklch(0.75 0.16 70);--chart-4:oklch(0.65 0.2 25);--chart-5:oklch(0.62 0.17 230);--radius:0.9rem}
.dark .launch-theme,.dark body:not(:has([data-gallery])):has(.launch-theme){--background:oklch(0.15 0.015 285);--foreground:oklch(0.96 0.008 85);--card:oklch(0.19 0.018 285);--card-foreground:oklch(0.96 0.008 85);--popover:oklch(0.21 0.02 285);--popover-foreground:oklch(0.96 0.008 85);--primary:oklch(0.72 0.19 285);--primary-foreground:oklch(0.15 0.03 285);--secondary:oklch(0.24 0.02 285);--secondary-foreground:oklch(0.96 0.008 85);--muted:oklch(0.23 0.02 285);--muted-foreground:oklch(0.74 0.03 285);--accent:oklch(0.28 0.04 285);--accent-foreground:oklch(0.96 0.008 85);--border:oklch(1 0 0 / 10%);--input:oklch(1 0 0 / 15%);--ring:oklch(0.72 0.19 285);--surface:oklch(0.175 0.017 285);--destructive:oklch(0.7 0.19 27);--chart-1:oklch(0.72 0.19 285);--chart-2:oklch(0.78 0.16 160);--chart-3:oklch(0.82 0.14 75);--chart-4:oklch(0.74 0.17 25);--chart-5:oklch(0.76 0.13 230)}
body:not(:has([data-gallery])):has(.launch-theme){font-family:var(--launch-sans),ui-sans-serif,system-ui,sans-serif}
`

type LaunchShellProps = React.ComponentProps<"div"> & {
  /** The page being shown. */
  page: LaunchPage
  /** Override where pages live (used by previews). */
  hrefs?: Partial<LaunchHrefs>
}

/**
 * Beacon's frame: Header2 and Footer2 with Beacon's links, in Beacon's palette and type.
 * Every page of the template is this shell around Ballmac blocks, so any block can be swapped for another.
 */
function LaunchShell({ page: _page, hrefs: overrides, className, style, children, ...props }: LaunchShellProps) {
  const hrefs = { ...defaultHrefs, ...overrides }
  React.useEffect(() => {
    const classes = [launchSans.variable, launchMono.variable].filter(Boolean)
    document.body.classList.add(...classes)
    return () => document.body.classList.remove(...classes)
  }, [])
  return (
    <div
      data-slot="launch"
      className={cn("launch-theme bg-background text-foreground min-h-dvh overflow-x-clip", launchSans.variable, launchMono.variable, className)}
      style={{ fontFamily: "var(--launch-sans), ui-sans-serif, system-ui, sans-serif", ...style }}
      {...props}
    >
      <style>{launchCss}</style>
      <Header2
        brand="Beacon"
        brandHref={hrefs.home}
        items={[{ label: "Product", href: hrefs.home }, { label: "Pricing", href: hrefs.pricing }, { label: "Changelog", href: hrefs.changelog }, { label: "Contact", href: hrefs.contact }]}
        secondaryAction={{ label: "Sign in", href: hrefs.contact }}
        primaryAction={{ label: "Start free", href: hrefs.pricing }}
      />
      {children}
      <Footer2
        brand="Beacon"
        tagline="Preview every branch, watch every budget and roll back in one click."
        columns={[
          { title: "Product", links: [{ label: "Overview", href: hrefs.home }, { label: "Pricing", href: hrefs.pricing }, { label: "Changelog", href: hrefs.changelog }] },
          { title: "Company", links: [{ label: "About", href: hrefs.home }, { label: "Careers", href: hrefs.contact }, { label: "Contact", href: hrefs.contact }] },
          { title: "Resources", links: [{ label: "Documentation", href: hrefs.home }, { label: "Status", href: hrefs.home }, { label: "Security", href: hrefs.home }] },
        ]}
        socials={[{ label: "Beacon website", href: hrefs.home, icon: <Globe /> }, { label: "Email Beacon", href: hrefs.contact, icon: <Mail /> }]}
        legal="© 2026 Beacon Labs, Inc."
        legalLinks={[{ label: "Privacy", href: hrefs.home }, { label: "Terms", href: hrefs.home }]}
      />
    </div>
  )
}

export { LaunchShell, defaultHrefs as launchDefaultHrefs, launchMono, type LaunchHrefs, type LaunchPage, type LaunchShellProps }
```

### `registry/ballmac/components/templates/launch/launch-page.tsx`

```tsx
// Ballmac UI: Launch template page. https://ui.ballmac.com/templates/template-launch
"use client"

import * as React from "react"
import { Check, GitBranch, Gauge, Rocket, RotateCcw } from "lucide-react"

import { Cta3 } from "@/components/ballmac/blocks/cta-3/cta-3"
import { Features5 } from "@/components/ballmac/blocks/features-5/features-5"
import { Hero6, Hero6Float } from "@/components/ballmac/blocks/hero-6/hero-6"
import { LogoCloud1 } from "@/components/ballmac/blocks/logo-cloud-1/logo-cloud-1"
import { Stats1 } from "@/components/ballmac/blocks/stats-1/stats-1"
import { Testimonials2 } from "@/components/ballmac/blocks/testimonials-2/testimonials-2"
import { LaunchShell, launchMono, type LaunchHrefs } from "@/components/ballmac/templates/launch/launch-theme"
import { cn } from "@/lib/utils"

const card = "bg-card w-64 rounded-2xl border p-4 shadow-lg"

/** The three cards that float around the hero: a deploy, a budget and a rollback. Replace with product shots. */
function HeroCards() {
  return (
    <>
      <Hero6Float depth={22} bob={6.5} className="xl:top-[50%] xl:start-0 2xl:start-[3%]">
        <div className={card}>
          <p className="flex items-center gap-2 text-sm font-semibold"><Rocket className="text-primary size-4" aria-hidden="true" />Preview ready</p>
          <p className={cn("text-muted-foreground mt-2 text-xs", launchMono.className)}>feat/checkout-v2 · 41s</p>
          <p className="mt-3 flex items-center gap-1.5 text-xs font-medium"><span className="bg-chart-2 size-2 rounded-full" aria-hidden="true" />Live at pe-482.beacon.app</p>
        </div>
      </Hero6Float>
      <Hero6Float depth={34} bob={7.5} delay={1.2} className="xl:top-[44%] xl:end-0 2xl:end-[3%]">
        <div className={card}>
          <p className="flex items-center gap-2 text-sm font-semibold"><Gauge className="text-primary size-4" aria-hidden="true" />Performance budget</p>
          <p className="mt-2 text-2xl font-semibold tabular-nums">94 <span className="text-muted-foreground text-xs font-medium">/ 90 required</span></p>
          <div className="bg-muted mt-2 h-1.5 overflow-hidden rounded-full" aria-hidden="true"><div className="bg-chart-2 h-full w-[94%]" /></div>
        </div>
      </Hero6Float>
      <Hero6Float depth={14} bob={8} delay={0.6} className="xl:end-[3%] xl:bottom-[1%] 2xl:end-[9%]">
        <div className={card}>
          <p className="flex items-center gap-2 text-sm font-semibold"><RotateCcw className="text-primary size-4" aria-hidden="true" />Rolled back</p>
          <p className="text-muted-foreground mt-2 text-xs">Error rate crossed 2%. Production returned to <span className={launchMono.className}>v2.18.3</span> in 6s.</p>
        </div>
      </Hero6Float>
    </>
  )
}

function Visual({ children, label }: { children: React.ReactNode; label: string }) {
  return <div role="img" aria-label={label} className="bg-surface grid min-h-72 place-items-center rounded-3xl border p-6">{children}</div>
}

const steps = [
  {
    title: "Every branch gets a URL",
    description: "Push a branch and Beacon builds it, runs your checks and posts a live preview on the pull request. Reviewers click a link instead of cloning a repo.",
    points: ["Previews in under a minute", "Comments pinned to the page", "Shareable with people outside your team"],
    visual: (
      <Visual label="A list of three preview deployments, the newest building">
        <ul className="grid w-full max-w-sm gap-2.5">{[["feat/checkout-v2", "Ready", "bg-chart-2"], ["fix/nav-focus", "Ready", "bg-chart-2"], ["chore/deps", "Building", "bg-chart-3"]].map(([b, s, c]) => <li key={b} className="bg-card flex items-center justify-between rounded-xl border px-4 py-3 text-sm shadow-xs"><span className="flex items-center gap-2"><GitBranch className="text-muted-foreground size-4" aria-hidden="true" /><span className={launchMono.className}>{b}</span></span><span className="flex items-center gap-1.5 text-xs font-medium"><span className={cn("size-2 rounded-full", c)} aria-hidden="true" />{s}</span></li>)}</ul>
      </Visual>
    ),
  },
  {
    title: "Budgets that block bad merges",
    description: "Set a ceiling for bundle size, load time or accessibility score. If a change breaks it, the check fails with the exact line that did.",
    points: ["Lighthouse and bundle budgets", "Per-route limits", "Trend lines over time"],
    visual: (
      <Visual label="Three budget bars: bundle size passes, load time passes and accessibility fails">
        <ul className="grid w-full max-w-sm gap-4">{[["Bundle size", 72, true, "148 KB of 200 KB"], ["Load time", 58, true, "1.6 s of 2.5 s"], ["Accessibility", 100, false, "Score 86, needs 90"]].map(([l, w, ok, note]) => <li key={l as string}><div className="flex justify-between text-sm font-medium"><span>{l as string}</span><span className="text-muted-foreground text-xs">{note as string}</span></div><div className="bg-muted mt-1.5 h-2 overflow-hidden rounded-full" aria-hidden="true"><div className={cn("h-full rounded-full", ok ? "bg-chart-2" : "bg-chart-4")} style={{ width: `${w}%` }} /></div></li>)}</ul>
      </Visual>
    ),
  },
  {
    title: "Roll back before anyone notices",
    description: "Beacon watches errors and latency after every release. Cross a threshold and it returns production to the last good build, then tells you why.",
    points: ["One-click or automatic rollback", "Alerts in Slack and email", "A full audit trail"],
    visual: (
      <Visual label="A release timeline where version 2.19.0 is rolled back to 2.18.3">
        <ol className="grid w-full max-w-sm gap-3">{[["v2.19.0", "Released 14:02", "bg-chart-4", "Rolled back at 14:03"], ["v2.18.3", "Restored 14:03", "bg-chart-2", "Serving traffic"]].map(([v, t, c, n]) => <li key={v} className="bg-card flex items-start gap-3 rounded-xl border p-4 shadow-xs"><span className={cn("mt-1.5 size-2.5 shrink-0 rounded-full", c)} aria-hidden="true" /><span><span className={cn("block text-sm font-semibold", launchMono.className)}>{v}</span><span className="text-muted-foreground block text-xs">{t}</span><span className="mt-1 flex items-center gap-1 text-xs font-medium"><Check className="size-3.5" aria-hidden="true" />{n}</span></span></li>)}</ol>
      </Visual>
    ),
  },
]

type LaunchHomeProps = React.ComponentProps<"div"> & { hrefs?: Partial<LaunchHrefs> }

/**
 * The Launch home page: every section is a Ballmac block (Hero6, LogoCloud1, Stats1, Features5, Testimonials2, Cta3).
 * Edit the copy through each block's props, reorder them, or swap one for another block in the same category.
 */
function LaunchPage({ hrefs, ...props }: LaunchHomeProps) {
  const link = { pricing: "/launch/pricing", contact: "/launch/contact", changelog: "/launch/changelog", ...hrefs }
  return (
    <LaunchShell page="home" hrefs={hrefs} {...props}>
      <main>
        <Hero6
          eyebrow="Beacon 3.2 · automatic rollbacks"
          title="Ship every branch with"
          highlight="nothing to fear."
          description="Preview URLs, performance budgets and one-click rollbacks for every pull request. Know what you are about to ship, and undo it in seconds if you were wrong."
          primaryAction={{ label: "Start for free", href: link.pricing }}
          secondaryAction={{ label: "Talk to us", href: link.contact }}
          highlights={["Free for small teams", "Connects to GitHub in a minute", "No card needed"]}
          cards={<HeroCards />}
        />
        <LogoCloud1 title="Trusted by teams who deploy on a Friday" />
        <Stats1
          eyebrow="By the numbers"
          title="Fewer incidents, faster merges."
          description="Across 9,400 teams and 3.1 million deploys last quarter."
          link={{ label: "Read the report", href: link.changelog }}
          stats={[
            { label: "Teams on Beacon", value: 9400, suffix: "+", delta: "+21%", trend: [3, 4, 5, 6, 7, 8, 8, 9, 9.4], trendLabel: "Teams, last 9 months", note: "Up from 7,800 in the spring." },
            { label: "Deploys each quarter", value: 3.1, suffix: "M", decimals: 1, delta: "+32%", trend: [1.2, 1.5, 1.7, 2, 2.2, 2.4, 2.7, 2.9, 3.1], trendLabel: "Deploys, last 9 months", note: "Roughly one every three seconds." },
            { label: "Median preview time", value: 41, suffix: " s", delta: "−12 s", trend: [70, 66, 60, 55, 52, 48, 45, 43, 41], trendLabel: "Preview time, last 9 months", note: "From push to a live URL." },
            { label: "Rollback time", value: 6, suffix: " s", trend: [30, 24, 18, 12, 10, 8, 7, 6, 6], trendLabel: "Rollback time, last 9 months", note: "From alert to the last good build." },
          ]}
        />
        <Features5 eyebrow="How it works" title="Preview it. Check it. Undo it." description="Three things every release needs, built into the same pull request." steps={steps} />
        <Testimonials2
          eyebrow="What teams say"
          items={[
            { quote: "We used to dread Fridays. Now a bad deploy rolls itself back before I finish reading the alert.", name: "Maya Chen", role: "VP Engineering", company: "Northwind", result: "−71% incident minutes" },
            { quote: "Budgets on pull requests changed how my team thinks about performance. Nobody argues about it anymore, the check just says no.", name: "Tomás Reyes", role: "Staff Engineer", company: "Parcel", result: "Bundle −38%" },
            { quote: "Design review used to mean screenshots in Slack. Now it is a link and a comment pinned to the button.", name: "Ingrid Solheim", role: "Design Director", company: "Fjord & Co", result: "Reviews 3× faster" },
          ]}
        />
        <Cta3
          title="Your next deploy, with a safety net."
          description="Connect a repository and Beacon builds your first preview in about a minute."
          command="create-beacon@latest"
          storageKey="beacon-pm"
          primaryAction={{ label: "Start for free", href: link.pricing }}
          secondaryAction={{ label: "Read the docs", href: link.changelog }}
          notes={["Works with Next.js, Remix, Astro and plain static sites", "Free forever for personal projects"]}
        />
      </main>
    </LaunchShell>
  )
}

export { LaunchPage, type LaunchHomeProps }
```

### `registry/ballmac/components/templates/launch/launch-pricing.tsx`

```tsx
// Ballmac UI: Launch pricing page. https://ui.ballmac.com/templates/template-launch
"use client"

import * as React from "react"

import { Faq2 } from "@/components/ballmac/blocks/faq-2/faq-2"
import { Pricing2 } from "@/components/ballmac/blocks/pricing-2/pricing-2"
import { Pricing3 } from "@/components/ballmac/blocks/pricing-3/pricing-3"
import { LaunchShell, type LaunchHrefs } from "@/components/ballmac/templates/launch/launch-theme"

type LaunchPricingProps = React.ComponentProps<"div"> & { hrefs?: Partial<LaunchHrefs> }

/** The Launch pricing page: Pricing2 (plans with a yearly switch), Pricing3 (full comparison) and Faq2. */
function LaunchPricing({ hrefs, ...props }: LaunchPricingProps) {
  const link = { contact: "/launch/contact", ...hrefs }
  return (
    <LaunchShell page="pricing" hrefs={hrefs} {...props}>
      <main>
        <Pricing2
          title="Pay for the team you have."
          description="Start free. Upgrade when your team grows. Every plan includes unlimited previews."
          plans={[
            { name: "Hobby", description: "For side projects and learning.", price: { monthly: 0, yearly: 0 }, unit: "free forever", features: ["3 projects", "Unlimited previews", "Community support", "7 days of history"], cta: { label: "Start free", href: link.contact } },
            { name: "Team", description: "For product teams who ship weekly.", price: { monthly: 24, yearly: 19 }, unit: "per seat", lead: "Everything in Hobby, plus:", features: ["Unlimited projects", "Performance budgets", "Automatic rollbacks", "90 days of history", "Slack alerts"], cta: { label: "Start a 14-day trial", href: link.contact }, featured: true },
            { name: "Company", description: "For organisations with compliance needs.", price: "Custom", lead: "Everything in Team, plus:", features: ["SSO and SCIM", "Audit log export", "Private networking", "Dedicated support", "Custom retention"], cta: { label: "Talk to sales", href: link.contact } },
          ]}
        />
        <Pricing3
          title="Compare every feature"
          description="The details, side by side."
          stickyOffset={64}
          plans={[
            { key: "hobby", name: "Hobby", price: "$0", period: "free forever", cta: { label: "Start free", href: link.contact } },
            { key: "team", name: "Team", price: "$24", period: "per seat / month", cta: { label: "Start trial", href: link.contact }, featured: true },
            { key: "company", name: "Company", price: "Custom", period: "talk to us", cta: { label: "Talk to sales", href: link.contact } },
          ]}
          groups={[
            { title: "Deploys", rows: [
              { label: "Preview deployments", values: { hobby: "Unlimited", team: "Unlimited", company: "Unlimited" } },
              { label: "Concurrent builds", hint: "Builds that can run at the same time", values: { hobby: "1", team: "10", company: "50" } },
              { label: "Build history", values: { hobby: "7 days", team: "90 days", company: "Custom" } },
            ] },
            { title: "Safety", rows: [
              { label: "Performance budgets", values: { hobby: false, team: true, company: true } },
              { label: "Automatic rollbacks", values: { hobby: false, team: true, company: true } },
              { label: "Audit log export", values: { hobby: false, team: false, company: true } },
            ] },
            { title: "Support", rows: [
              { label: "Slack and email alerts", values: { hobby: false, team: true, company: true } },
              { label: "SSO and SCIM", values: { hobby: false, team: false, company: true } },
              { label: "Support", values: { hobby: "Community", team: "Email, 1 day", company: "Dedicated, 1 hour" } },
            ] },
          ]}
        />
        <Faq2
          title="Pricing questions"
          description="Still unsure? These are the ones we hear most."
          support={{ label: "Contact support", href: link.contact, text: "Not here? A human replies within a working day." }}
          categories={[
            { name: "Billing", questions: [
              { question: "Can I change plans later?", answer: "Yes. Upgrade or downgrade at any time. We prorate the difference, so you only pay for what you use." },
              { question: "How do seats work?", answer: "You pay for people who can deploy. Viewers who only comment on previews are always free." },
              { question: "Do you offer discounts?", answer: "Open source projects and students get Team free. Annual billing saves about 20%." },
            ] },
            { name: "Product", questions: [
              { question: "What counts as a preview?", answer: "Every branch or pull request build. There is no limit on how many you create." },
              { question: "How do rollbacks decide?", answer: "You set thresholds for error rate and latency. If a release crosses one, Beacon restores the last good build." },
            ] },
            { name: "Security", questions: [
              { question: "Where is my code stored?", answer: "Builds run in isolated, short-lived containers in the region you choose. Source is never kept after the build." },
            ] },
          ]}
        />
      </main>
    </LaunchShell>
  )
}

export { LaunchPricing, type LaunchPricingProps }
```

### `registry/ballmac/components/templates/launch/launch-changelog.tsx`

```tsx
// Ballmac UI: Launch changelog page. https://ui.ballmac.com/templates/template-launch
"use client"

import * as React from "react"

import { Changelog1 } from "@/components/ballmac/blocks/changelog-1/changelog-1"
import { LaunchShell, type LaunchHrefs } from "@/components/ballmac/templates/launch/launch-theme"

type LaunchChangelogProps = React.ComponentProps<"div"> & { hrefs?: Partial<LaunchHrefs> }

/** The Launch changelog page: Changelog1 with Beacon's releases. */
function LaunchChangelog({ hrefs, ...props }: LaunchChangelogProps) {
  return (
    <LaunchShell page="changelog" hrefs={hrefs} {...props}>
      <main>
        <Changelog1
          title="What’s new in Beacon"
          description="Every release, newest first. We ship something most weeks."
          initialCount={3}
          releases={[
            { version: "3.2.0", date: "2026-09-24", title: "Automatic rollbacks", summary: "Set an error or latency threshold and Beacon returns production to the last good build when a release crosses it.", cover: 0, changes: [{ type: "new", text: "Rollback rules per project, with Slack and email alerts" }, { type: "new", text: "A rollback timeline on every deployment" }, { type: "improved", text: "Rollbacks finish in a median of six seconds" }] },
            { version: "3.1.2", date: "2026-09-09", title: "Budgets for accessibility", summary: "Fail a pull request when its accessibility score drops below your ceiling.", cover: 1, changes: [{ type: "new", text: "Accessibility score as a budget" }, { type: "improved", text: "Budget failures link to the offending element" }, { type: "fixed", text: "Budgets no longer reset when a project is renamed" }] },
            { version: "3.1.0", date: "2026-08-20", title: "Comments pinned to the page", changes: [{ type: "new", text: "Pin a comment to any element on a preview" }, { type: "improved", text: "Reviewers outside your team can comment without an account" }] },
            { version: "3.0.4", date: "2026-08-02", title: "Faster monorepo builds", changes: [{ type: "improved", text: "Builds skip packages that did not change" }, { type: "fixed", text: "Cached dependencies are no longer invalidated by lockfile whitespace" }] },
            { version: "3.0.0", date: "2026-06-18", title: "Beacon 3", summary: "A new dashboard, regions and a rebuilt build pipeline.", cover: 2, changes: [{ type: "new", text: "Choose where builds run: Frankfurt, Virginia or Singapore" }, { type: "improved", text: "A new dashboard that loads in under a second" }, { type: "fixed", text: "Fifteen long-standing bugs in the Git integration" }] },
          ]}
        />
      </main>
    </LaunchShell>
  )
}

export { LaunchChangelog, type LaunchChangelogProps }
```

### `registry/ballmac/components/templates/launch/launch-contact.tsx`

```tsx
// Ballmac UI: Launch contact page. https://ui.ballmac.com/templates/template-launch
"use client"

import * as React from "react"
import { Calendar, LifeBuoy, Mail } from "lucide-react"

import { Contact1 } from "@/components/ballmac/blocks/contact-1/contact-1"
import { LaunchShell, type LaunchHrefs } from "@/components/ballmac/templates/launch/launch-theme"

type LaunchContactProps = React.ComponentProps<"div"> & { hrefs?: Partial<LaunchHrefs> }

/** The Launch contact page: Contact1 with Beacon's channels and topics. */
function LaunchContact({ hrefs, ...props }: LaunchContactProps) {
  return (
    <LaunchShell page="contact" hrefs={hrefs} {...props}>
      <main>
        <Contact1
          title="Talk to a person."
          description="Questions about plans, security or migrating from another platform? Tell us what you need and the right person will reply."
          topics={["Sales and pricing", "Security review", "Migrating to Beacon", "Support", "Something else"]}
          responseTime="We reply within one working day"
          methods={[
            { icon: <Mail />, label: "Email", value: "hello@beacon.example", href: "mailto:hello@beacon.example" },
            { icon: <Calendar />, label: "Book a demo", value: "Thirty minutes with an engineer", href: "#" },
            { icon: <LifeBuoy />, label: "Support", value: "Customers: open a ticket in the dashboard", href: "#" },
          ]}
        />
      </main>
    </LaunchShell>
  )
}

export { LaunchContact, type LaunchContactProps }
```

### `registry/ballmac/app/launch/page.tsx`

```tsx
// Ballmac UI: Launch template route. https://ui.ballmac.com/templates/template-launch
import type { Metadata } from "next"

import { LaunchPage } from "@/components/ballmac/templates/launch/launch-page"

export const metadata: Metadata = {
  title: "Beacon: ship every branch with nothing to fear",
  description: "Preview URLs, performance budgets and one-click rollbacks for every pull request.",
}

export default function Page() {
  return <LaunchPage />
}
```

### `registry/ballmac/app/launch/pricing/page.tsx`

```tsx
// Ballmac UI: Launch template route. https://ui.ballmac.com/templates/template-launch
import type { Metadata } from "next"

import { LaunchPricing } from "@/components/ballmac/templates/launch/launch-pricing"

export const metadata: Metadata = {
  title: "Pricing · Beacon",
  description: "Start free. Upgrade when your team grows.",
}

export default function Page() {
  return <LaunchPricing />
}
```

### `registry/ballmac/app/launch/changelog/page.tsx`

```tsx
// Ballmac UI: Launch template route. https://ui.ballmac.com/templates/template-launch
import type { Metadata } from "next"

import { LaunchChangelog } from "@/components/ballmac/templates/launch/launch-changelog"

export const metadata: Metadata = {
  title: "Changelog · Beacon",
  description: "Every release, newest first.",
}

export default function Page() {
  return <LaunchChangelog />
}
```

### `registry/ballmac/app/launch/contact/page.tsx`

```tsx
// Ballmac UI: Launch template route. https://ui.ballmac.com/templates/template-launch
import type { Metadata } from "next"

import { LaunchContact } from "@/components/ballmac/templates/launch/launch-contact"

export const metadata: Metadata = {
  title: "Contact · Beacon",
  description: "Talk to a person about plans, security or migrating.",
}

export default function Page() {
  return <LaunchContact />
}
```
