# Bug Bounty Page

> A bug bounty program page: rewards by severity with a CVSS reward estimator, scope, rules and safe harbor, a hall of fame and a report form.

- Type: React template (Templates)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add bug-bounty-page`
- Docs: https://wingo-ui.com/templates/bug-bounty-page

## Interaction

The hero rises in once beside a drawn triage terminal whose status badge flips from New to Triaged to a $7,500 bounty while the log ticks off (still under reduced motion and in thumbnails); the PGP chip copies the key fingerprint. Submit a report scrolls to the form and focuses its title; chips under the stats jump to each section, and the four program numbers roll up once when they scroll into view. The rewards table becomes cards below 768px. Estimate your reward: pick the asset tier, five simplified CVSS 3.1 inputs and the report quality on segmented controls (arrow keys move within each) and the score, severity badge, vector string and USD range update live and are announced. Scope tabs switch between in-scope assets (a table that becomes cards on phones) and out-of-scope findings. The year control filters the leaderboard; every disclosed report is one link. The report form validates on submit and moves focus to a GOV.UK style error summary whose links focus each field; attachments take a click or a drop, list names and sizes, flag files over the limit and can be removed; the submit button spins while onSubmitReport runs, then a success panel shows the report ID with a copy button and the next steps. The closing band copies security@acme.com.

## Installation

```bash
npx wingo-ui@latest add bug-bounty-page
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/bug-bounty-page` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/templates/bug-bounty-page.tsx`
- `components/templates/bug-bounty-page-data.ts`

npm dependencies: `npm i motion lucide-react`

Wingo UI dependencies (installed automatically):

- [Marketing Section](https://wingo-ui.com/components/marketing-section) ([Markdown](https://wingo-ui.com/components/marketing-section.md))
- [Marketing Header](https://wingo-ui.com/components/marketing-header) ([Markdown](https://wingo-ui.com/components/marketing-header.md))
- [Marketing Footer](https://wingo-ui.com/components/marketing-footer) ([Markdown](https://wingo-ui.com/components/marketing-footer.md))
- [Hero Section](https://wingo-ui.com/components/hero-section) ([Markdown](https://wingo-ui.com/components/hero-section.md))
- [FAQ Section](https://wingo-ui.com/components/faq-section) ([Markdown](https://wingo-ui.com/components/faq-section.md))
- [CTA Section](https://wingo-ui.com/components/cta-section) ([Markdown](https://wingo-ui.com/components/cta-section.md))
- [Animated Counter](https://wingo-ui.com/components/animated-counter) ([Markdown](https://wingo-ui.com/components/animated-counter.md))
- [Avatar](https://wingo-ui.com/components/avatar) ([Markdown](https://wingo-ui.com/components/avatar.md))
- [Badge](https://wingo-ui.com/components/badge) ([Markdown](https://wingo-ui.com/components/badge.md))
- [Button](https://wingo-ui.com/components/button) ([Markdown](https://wingo-ui.com/components/button.md))
- [Checkbox](https://wingo-ui.com/components/checkbox) ([Markdown](https://wingo-ui.com/components/checkbox.md))
- [Copy Button](https://wingo-ui.com/components/copy-button) ([Markdown](https://wingo-ui.com/components/copy-button.md))
- [Field](https://wingo-ui.com/components/field) ([Markdown](https://wingo-ui.com/components/field.md))
- [Input](https://wingo-ui.com/components/input) ([Markdown](https://wingo-ui.com/components/input.md))
- [Segmented Control](https://wingo-ui.com/components/segmented-control) ([Markdown](https://wingo-ui.com/components/segmented-control.md))
- [Select](https://wingo-ui.com/components/select) ([Markdown](https://wingo-ui.com/components/select.md))
- [Tabs](https://wingo-ui.com/components/tabs) ([Markdown](https://wingo-ui.com/components/tabs.md))
- [Textarea](https://wingo-ui.com/components/textarea) ([Markdown](https://wingo-ui.com/components/textarea.md))
- [Navigation](https://wingo-ui.com/components/navigation) ([Markdown](https://wingo-ui.com/components/navigation.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
// app/(marketing)/security/bug-bounty/page.tsx
"use client"

import Link from "next/link"
import { BugBountyPage } from "@/components/templates/bug-bounty-page"

export default function BugBountyRoute() {
  return (
    <BugBountyPage
      linkComponent={Link}
      onSubmitReport={async ({ files, ...values }) => {
        const body = new FormData()
        body.append("report", JSON.stringify(values))
        files.forEach((file) => body.append("files", file))
        const response = await fetch("/api/security/reports", { method: "POST", body })
        if (!response.ok) throw new Error("Could not submit the report")
        const { id } = (await response.json()) as { id: string }
        return id
      }}
    />
  )
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `design?` | `"classic" \| "terminal" \| "minimal"` | `"classic"` | The whole page's look. classic follows the layout props; terminal: a dark monospace page in both themes with $-prefixed eyebrows, a green dotted backdrop, hairline panels, dashed section rules, mono figures and a soft closing band; minimal: a transparent header, a centered hero without the terminal, outlined panels, no bands, a plain closing band and a simple footer. The *Props overrides still win. |
| `stats?` | `BugBountyStat[]` | `"BUG_BOUNTY_STATS"` | { id, value, decimals?, prefix?, suffix?, label } numbers under the hero; they roll up once in view. |
| `rewards?` | `BugBountyReward[]` | `"BUG_BOUNTY_REWARDS"` | { severity, min, max, cvssMin, cvssMax, examples } rows of the rewards table, amounts in USD. |
| `assetTiers?` | `BugBountyAssetTier[]` | `"BUG_BOUNTY_ASSET_TIERS"` | { tier, label, description, multiplier } tiers; the estimator scales the range by the multiplier. |
| `assets?` | `BugBountyAsset[]` | `"BUG_BOUNTY_ASSETS"` | { id, name, type, tier, notes } in-scope assets, also the form's asset choices. |
| `outOfScope?` | `BugBountyExclusion[]` | `"BUG_BOUNTY_OUT_OF_SCOPE"` | { id, title, description } findings that are out of scope. |
| `rules?` | `BugBountyRule[]` | `"BUG_BOUNTY_RULES"` | { id, title, description } numbered rules of engagement. |
| `timeline?` | `BugBountyTimelineStep[]` | `"BUG_BOUNTY_TIMELINE"` | { id, title, sla, description } steps of the disclosure timeline. |
| `researchers?` | `BugBountyResearcher[]` | `"BUG_BOUNTY_RESEARCHERS"` | { handle, country, points, reports, year } leaderboard entries; country is an ISO code shown as text. |
| `reports?` | `BugBountyDisclosedReport[]` | `"BUG_BOUNTY_REPORTS"` | { id, title, severity, bounty, disclosedAt, researcher, asset, href } recently disclosed reports; disclosedAt is an ISO day. |
| `vulnerabilityTypes?` | `BugBountyOption[]` | `"BUG_BOUNTY_VULNERABILITY_TYPES"` | { value, label } choices of the Vulnerability type select. |
| `program?` | `BugBountyProgram` | `"BUG_BOUNTY_PROGRAM"` | { email, pgpFingerprint, pgpHref, securityTxtHref, policyHref, reportIdPrefix, firstReportNumber }. |
| `scene?` | `BugBountyScene` | `"BUG_BOUNTY_SCENE"` | The strings of the hero's triage terminal: { window, command, reportId, fields, cvss, phases, log }. |
| `faq?` | `FaqItem[]` | `"BUG_BOUNTY_FAQ"` | Questions and answers for the FAQ section. |
| `labels?` | `Partial<BugBountyPageLabels>` | `"DEFAULT_BUG_BOUNTY_PAGE_LABELS"` | Every visible string: headings, table headers, estimator options, form fields and errors, success copy. |
| `heroLayout?` | `"split" \| "centered"` | `"split"` | The hero copy beside the triage terminal, or centered over it. Applies to the classic design. |
| `defaultScopeTab?` | `"in" \| "out"` | `"in"` | The scope tab open on load. |
| `defaultYear?` | `number` | `2026` | The leaderboard's year on load; a year without entries falls back to the newest year in researchers. |
| `maxFileSize?` | `number` | `10` | The largest attachment in megabytes; bigger files are flagged and block the submit. |
| `maxFiles?` | `number` | `5` | How many attachments a report can carry. |
| `onSubmitReport?` | `(values: BugBountyReportValues) => (string \| void \| Promise<string \| void>)` |  | Called with { title, asset, vulnerabilityType, severity, steps, impact, files, email, agree } once the form is valid. A returned promise keeps the button loading, a string it resolves to becomes the report ID and a rejection shows labels.failed. Without it the form waits 900 ms and shows the next ID (ACME-H1-2026-0412). |
| `showStats?` | `boolean` | `true` | The program numbers under the hero. |
| `showJumpLinks?` | `boolean` | `true` | The row of section chips. |
| `showRewards?` | `boolean` | `true` | The rewards section. |
| `showEstimator?` | `boolean` | `true` | The Estimate your reward calculator inside the rewards section. |
| `showScope?` | `boolean` | `true` | The in scope / out of scope tabs. |
| `showRules?` | `boolean` | `true` | The rules of engagement and the safe harbor callout. |
| `showTimeline?` | `boolean` | `true` | The disclosure timeline. |
| `showHallOfFame?` | `boolean` | `true` | The leaderboard section. |
| `showReports?` | `boolean` | `true` | The recently disclosed reports beside the leaderboard. |
| `showSubmit?` | `boolean` | `true` | The report form. |
| `showFaq?` | `boolean` | `true` | The FAQ section. |
| `showCta?` | `boolean` | `true` | The closing band with the security email. |
| `alternate?` | `boolean` | `true` | Bands on every other visible section, in the bandBackground look. Applies to the classic design. |
| `background?` | `"plain" \| "soft" \| "glow" \| "aurora" \| "grid" \| "dots"` | `"grid"` | The main background: plain is the bare page color; the others tint the page and add a glow, an aurora, a grid or dots over the first screen. A design picks its own unless you set one. Classic uses grid, terminal dots, minimal plain. |
| `backgroundColor?` | `string` | `"oklch(0.62 0.14 275)"` | The tint and glow color of the main background; the terminal design uses a terminal green unless you set one. |
| `bandBackground?` | `"muted" \| "tinted" \| "gradient" \| "dots"` | `"muted"` | The secondary background of the alternating bands. Cards, fields and tiles inside a band are lifted one step above it, so they never share its color. |
| `bandColor?` | `string` | `"oklch(0.62 0.14 275)"` | The tint of tinted and gradient bands; defaults to backgroundColor. |
| `tone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Icon tiles, timeline nodes, the top three ranks, the safe harbor badge and the estimator's segmented controls. Severity colors stay fixed. |
| `ctaTone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Get started, both Submit a report buttons and the form's submit; brand is the marketing orange. |
| `radius?` | `"none" \| "sm" \| "md" \| "lg" \| "full"` | `"md"` | The corners of the form fields, the scope tabs and the segmented controls. |
| `header?` | `boolean` | `true` | The marketing header; off inside a site layout. |
| `footer?` | `boolean` | `true` | The marketing footer. |
| `headerProps?` | `Partial<MarketingHeaderProps>` |  | Passed to MarketingHeader. |
| `footerProps?` | `Partial<MarketingFooterProps>` |  | Passed to MarketingFooter. |
| `heroProps?` | `Partial<HeroSectionProps>` |  | Overrides for the HeroSection (media, background...). |
| `faqProps?` | `Partial<FaqSectionProps>` |  | Overrides for the FaqSection (layout, variant...). |
| `ctaProps?` | `Partial<CtaSectionProps>` |  | Overrides for the closing CtaSection (variant, actions...). |
| `animateIn?` | `boolean` | `true` | The hero rises in, the numbers roll up and the triage terminal plays; false keeps everything still (thumbnails). Reduced motion always does. |
| `locale?` | `string` | `"en-US"` | Intl locale for the USD amounts, numbers, file sizes and dates (shown in UTC). |
| `linkComponent?` | `(props: LinkComponentProps) => ReactNode` | `"<a>"` | The router link for every link on the page (next/link in an app). |
| `className?` | `string` |  | Classes for the root. |
| `classNames?` | `Partial<Record<BugBountyPageSlot, string>>` |  | Classes for header, hero, stats, jump, rewards, estimator, scope, rules, safeHarbor, timeline, hallOfFame, leaderboard, reports, submit, form, success, faq, cta and footer. |

## Parts

### cvssScore (function)

cvssScore({ attackVector, attackComplexity, privileges, userInteraction, impact }): the CVSS 3.1 base score with scope unchanged and one impact level for C, I and A.

### cvssSeverity (function)

cvssSeverity(score): critical, high, medium, low, or null for 0.

### estimateReward (function)

estimateReward(reward, score, quality, multiplier): the { low, high } USD estimate the calculator shows, rounded to $50.

### BUG_BOUNTY_PAGE_SAMPLE (constant)

All the sample content in one object.

### BUG_BOUNTY_STATS (constant)

$1.4M paid, 612 researchers, 9 hours to first response, 11 days to bounty.

### BUG_BOUNTY_REWARDS (constant)

Critical $10,000 to $30,000, High $3,000 to $10,000, Medium $750 to $3,000 and Low $150 to $750.

### BUG_BOUNTY_ASSET_TIERS (constant)

Tier 1 (100%), Tier 2 (60%) and Tier 3 (30%).

### BUG_BOUNTY_ASSETS (constant)

app.acme.com, api.acme.com, the desktop and mobile apps, the CLI and the browser extension.

### BUG_BOUNTY_OUT_OF_SCOPE (constant)

Ten out-of-scope finding types.

### BUG_BOUNTY_RULES (constant)

Eight rules of engagement.

### BUG_BOUNTY_TIMELINE (constant)

Report, Acknowledge, Triage, Fix, Bounty and Disclose with their promises.

### BUG_BOUNTY_RESEARCHERS (constant)

Leaderboard entries for 2024 to 2026.

### BUG_BOUNTY_REPORTS (constant)

Six recently disclosed reports.

### BUG_BOUNTY_VULNERABILITY_TYPES (constant)

The Vulnerability type choices.

### BUG_BOUNTY_PROGRAM (constant)

The security email, PGP fingerprint, links and report ID numbering.

### BUG_BOUNTY_SCENE (constant)

The strings of the hero's triage terminal.

### BUG_BOUNTY_FAQ (constant)

Six researcher questions.

### DEFAULT_BUG_BOUNTY_PAGE_LABELS (constant)

The English strings.

### BUG_BOUNTY_PAGE_DESIGNS (constant)

The design names, classic first: ["classic", "terminal", "minimal"].

### BugBountyPageProps (type)

Props of BugBountyPage.

### BugBountyPageDesign (type)

"classic" | "terminal" | "minimal".

### BugBountyPageLabels (type)

The strings labels can override.

### BugBountyReportValues (type)

{ title, asset, vulnerabilityType, severity, steps, impact, files, email, agree } passed to onSubmitReport.

### BugBountyCvssInput (type)

The five inputs of cvssScore.

### BugBountyReward (type)

One row of the rewards table.

### BugBountyAsset (type)

One in-scope asset.

### BugBountyResearcher (type)

One leaderboard entry.

### BugBountyDisclosedReport (type)

One disclosed report.

## Examples

- **Terminal design**: design="terminal": a dark monospace page in both themes, $-prefixed eyebrows, a green dotted backdrop, hairline panels and dashed rules.
- **Minimal design**: design="minimal": a transparent header, a centered hero without the terminal, outlined panels, no bands and a plain closing band.
- **Brand orange, centered hero**: heroLayout centered with tone and ctaTone brand; the scope opens on the out of scope tab and the board on 2025.
- **Disclosure policy only**: A vulnerability disclosure program without bounties: scope, rules, timeline, the form and the FAQ, in en-GB.
- **When the submit fails**: onSubmitReport rejects: after the spinner the form keeps everything and shows the error above the button.

## See also

- [Security Page](https://wingo-ui.com/templates/security-page) ([Markdown](https://wingo-ui.com/templates/security-page.md))
- [Legal Page](https://wingo-ui.com/templates/legal-page) ([Markdown](https://wingo-ui.com/templates/legal-page.md))
- [Accessibility Page](https://wingo-ui.com/templates/accessibility-page) ([Markdown](https://wingo-ui.com/templates/accessibility-page.md))
- [Copy Button](https://wingo-ui.com/components/copy-button) ([Markdown](https://wingo-ui.com/components/copy-button.md))
- [Segmented Control](https://wingo-ui.com/components/segmented-control) ([Markdown](https://wingo-ui.com/components/segmented-control.md))

---

Canonical: https://wingo-ui.com/templates/bug-bounty-page
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
