Skip to content

Developer Tool

Near-black buttons, square corners and a terminal-green accent. Install command above the fold, real code before any prose, docs and changelog behind it.

5 routes5 pages · 17 blocks33 files · 3,837 lineslucide-reactAdded 2 Sept 2026

What's included

  • app/changelog/page.tsx
  • app/docs/page.tsx
  • app/globals.css
  • app/layout.tsx
  • app/not-found.tsx
  • app/page.tsx
  • and 9 more files
  • 5 pages it is built from, installed with it
  • Needs lucide-react

Works with

  • React
  • Next.js
  • Tailwind CSS
  • TypeScript

npx hoverlab init developer-tool ./my-app

Or over MCP, from your editor's agent — no account needed.

License

Free to read, copy and install, for personal and non-commercial projects. Shipping it in client work or a paid product needs Pro ($79 once). The source lands in your repo and stops being ours — no attribution, nothing to upgrade.

Was this useful?

Every screen

v4.2 — no agent, no sidecar

Webhooks that arrive, or tell you why not

Relay takes delivery, retries, signature verification and the dead-letter queue off your critical path. One endpoint in, one verified payload out.

npm i @relay/sdk

Delivering for

  • Northwind
  • Contoso
  • Initech
  • Globex
  • Lumon
  • Vandelay

4.1 billion events delivered last month, at 99.99% first-attempt success.

The whole integration

Two files. There is no third one where the complexity was hiding.

  • Signature verification is one call, and it throws rather than returning false
  • Retries, backoff and the dead-letter queue are server-side — nothing to schedule
  • Typed payloads generated from your own event schema
import { verify } from '@relay/sdk' export async function POST(req: Request) {  // Throws on a bad signature or a replayed timestamp, so there is  // no boolean to forget to check.  const event = await verify(req, process.env.RELAY_SECRET!)   switch (event.type) {    case 'invoice.paid':      await fulfil(event.data.invoiceId)      break    case 'invoice.failed':      await notify(event.data.customerId)      break  }   // 200 means "stored". Relay retries anything else for 72 hours.  return new Response(null, { status: 200 })}

What you stop maintaining

Each of these is a thing teams build in-house, ship, and then own forever.

Delivery

The retry loop you were going to write on Friday

Twelve attempts over 72 hours with exponential backoff, resumed across your deploys rather than lost with the process that scheduled them. Anything that never lands goes to a dead-letter queue you can replay from a dashboard or a single API call.

  • Retries survive your restarts
  • Replay one event or ten thousand
  • Per-endpoint circuit breaking

Verification

Signatures, timestamps and replay windows, once

Constant-time comparison, a configurable tolerance window, and rejection of anything reused. The failure mode of hand-rolled verification is not an outage — it is silently accepting forged events for a year, which is why this is the section to read twice.

  • Constant-time compare
  • Replay rejection by default

Visibility

Every attempt, with the response body attached

The request, the response, the status code and the latency, for every attempt of every event, kept for 30 days. When a customer says the webhook never arrived, this is the difference between an answer and an afternoon.

  • Full request and response bodies
  • 30-day retention
  • Filter by endpoint, type or status

Works with what you already run

Direct integrations, not a webhook you have to adapt at both ends.

  • Stripe

    Payments

    Available

    Verified passthrough of every Stripe event type.

  • GitHub

    Source

    Available

    Repository, org and app events, with installation scoping.

  • Shopify

    Commerce

    Available

    Order, fulfilment and inventory topics.

  • Slack

    Alerting

    Available

    Post failures into a channel with the payload attached.

  • AWS EventBridge

    Infrastructure

    Beta

    Forward into a bus with the original signature preserved.

  • Kafka

    Infrastructure

    Planned

    Produce to a topic with at-least-once semantics.

What it costs at your volume

Move the slider. There is no plan to pick, and the number below is the number on the invoice.

100K50M
0–1M at $0.08 per 1K
$80.00
1M–10M at $0.05 per 1K
$50.00
Estimated monthly total$130.00
Get an API key

The awkward questions

Infrastructure buyers ask about exits before they ask about features. Fair enough.

What happens if Relay goes down?
Your senders keep retrying into us and we keep the backlog; nothing is dropped for the length of your retry window. If we are down longer than that, the failover endpoint documented in the SDK forwards raw to your origin unverified, and you fall back to your own handling.
Can I self-host it?
Yes, on the enterprise plan, as a container with a Postgres and a Redis. It is the same image we run. The dashboard and the replay API come with it; the only thing that does not is our on-call.
How do I get my data out?
A single export endpoint returns every event, attempt and response body as newline-delimited JSON, and it is available on every plan including the free one. No ticket, no notice period, no export fee.
Is the SDK required?
No. It is 40 lines around a documented HTTP contract and an HMAC. The verification algorithm is written out in the docs so you can implement it in a language we do not ship for — several customers have.
What counts as an event?
One inbound payload, regardless of how many times we retry it or how many endpoints you fan it out to. Retries are our problem, so charging you for them would be charging you for our failures.
Do you have an SLA?
99.99% on ingest, credited automatically against the next invoice rather than on request. The status page below is the same one our own alerting reads, and its history is not editable after the fact.

Live components in your current theme — switch routes, or the phone icon to check the mobile layout. Colours are this template’s Graphite palette, which ships in app/globals.css. Near-black buttons, cool grey neutrals, one green terminal accent. Square-ish corners. The palette developer tools converge on because it stays out of the way of code.

Get it

33 files · .zip · nothing to configure · Pro

then

cd developer-tool
npm install
npm run dev

The archive contains the whole project — routes, blocks, theme tokens, Tailwind and PostCSS config, tsconfig and a .gitignore. One runtime dependency, and no Hoverlab dependency at all: it is your code from the moment it unzips.

For AI

The component, its props, the design tokens it expects and the command that installs it — as one prompt. Paste it into Claude, Cursor, v0 or ChatGPT and what they build around it will match the rest of the catalog instead of inventing its own system.

See the prompt

Routes

PathPageFile
/Developer Tool Landing Pageapp/page.tsx
/docsDocumentation Pageapp/docs/page.tsx
/changelogChangelog Pageapp/changelog/page.tsx
/pricingPricing Pageapp/pricing/page.tsx
404404 Pageapp/not-found.tsx

What you get

project root(8 files)

  • GETTING-STARTED.md
  • gitignore
  • next.config.ts
  • package.json
  • postcss.config.mjs
  • README.md
  • tailwind.config.ts
  • tsconfig.json

app/(7 files)

  • changelog/page.tsx
  • docs/page.tsx
  • globals.css
  • layout.tsx
  • not-found.tsx
  • page.tsx
  • pricing/page.tsx

components/(18 files)

  • changelog-timeline.tsx
  • code-showcase.tsx
  • comparison-table.tsx
  • docs-layout.tsx
  • faq-accordion.tsx
  • faq-grid.tsx
  • feature-rows.tsx
  • footer-minimal.tsx
  • footer-status-locale.tsx
  • hero-terminal.tsx
  • integration-grid.tsx
  • logo-grid.tsx
  • navbar-simple.tsx
  • newsletter-signup.tsx
  • not-found-404.tsx
  • pricing-tiers.tsx
  • pricing-usage-calculator.tsx
  • theme-provider.tsx

Every file is listed. The 17 files in components/ are the blocks the pages import — each one has its own page if you want to read it on its own.

Project files

Everything except the blocks. Opens on app/globals.css — the file that makes the rest look right, since every block styles itself with bg-card and text-muted-foreground rather than literal colours.

app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

/**
 * Design tokens — the Graphite palette.
 *
 * Near-black buttons, cool grey neutrals, one green terminal accent. Square-ish corners. The palette developer tools converge on because it stays out of the way of code.
 *
 * This file is the reason a pasted block looks right. Every block and page
 * styles itself with semantic classes — `bg-card`, `text-muted-foreground`,
 * `border-border` — rather than literal colours, so they inherit whatever
 * you define here instead of fighting it. Change a value below and every
 * section in the project moves with it. Change the hue on `--primary` and
 * `--ring` together and you have rebranded the site.
 *
 * Values are bare HSL channels, not `hsl(...)` calls. That is what lets
 * Tailwind compose them with an alpha suffix: `bg-primary/10` expands to
 * `hsl(var(--primary) / 0.1)`, which is impossible if the variable already
 * carries its own function wrapper.
 *
 * Every foreground/background pair below clears WCAG AA (4.5:1) in both
 * themes. If you retune one, check the pair rather than trusting the eye —
 * mid-lightness accents are the ones that fail.
 */

@layer base {
  :root {
    --background: 220 20% 98%;
    --foreground: 220 30% 10%;
    --card: 0 0% 100%;
    --card-foreground: 220 30% 10%;
    --popover: 0 0% 100%;
    --popover-foreground: 220 30% 10%;
    --primary: 220 30% 18%;
    --primary-foreground: 220 20% 98%;
    --secondary: 220 16% 94%;
    --secondary-foreground: 220 30% 16%;
    --muted: 220 16% 95%;
    --muted-foreground: 220 12% 42%;
    --accent: 158 60% 92%;
    --accent-foreground: 158 70% 16%;
    --destructive: 0 70% 45%;
    --destructive-foreground: 0 0% 100%;
    --border: 220 14% 89%;
    --input: 220 14% 89%;
    --ring: 220 30% 18%;

    --radius: 0.25rem;
  }

  .dark {
    --background: 220 26% 6%;
    --foreground: 220 14% 96%;
    --card: 220 22% 9%;
    --card-foreground: 220 14% 96%;
    --popover: 220 22% 9%;
    --popover-foreground: 220 14% 96%;
    --primary: 220 14% 96%;
    --primary-foreground: 220 30% 10%;
    --secondary: 220 18% 15%;
    --secondary-foreground: 220 14% 96%;
    --muted: 220 18% 15%;
    --muted-foreground: 220 10% 66%;
    --accent: 158 40% 16%;
    --accent-foreground: 158 60% 82%;
    --destructive: 0 62% 52%;
    --destructive-foreground: 0 0% 100%;
    --border: 220 16% 18%;
    --input: 220 16% 18%;
    --ring: 220 14% 96%;
  }
}

@layer base {
  * {
    @apply border-border;
  }

  body {
    @apply bg-background text-foreground antialiased;
  }

  /**
   * Global motion opt-out.
   *
   * Blocks guard their own animations with Tailwind's `motion-safe:`, but
   * third-party CSS and anything you add later will not. This is the
   * backstop: it neutralises every animation and transition on the page
   * for users who have asked the OS for reduced motion, rather than
   * relying on each author to remember.
   */
  @media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

More Landing Pages

Open the full page for this template

Startup Waitlist

The waitlist hero with the count on it

A pre-launch site in violet: one email field, a blog to keep the list warm, and no pricing to be held to. The smallest honest thing to put in front of a product that does not exist yet.

4 routes4 pages13 blocksUltraviolet
Pro
Open the full page for this template

Mobile App

The store-badge download hero

Emerald and 16px corners, built around one conversion: the store install. Badges and the App Store rating above the fold, a single price, and an account area for the subscription.

5 routes5 pages18 blocksSignal
Pro
Open the full page for this template

Agency Studio

Case studies that name the constraint

Terracotta on warm paper, with no blue in it anywhere. Full-bleed hero, client list, the actual team, a journal and a careers page — and no pricing, on purpose.

5 routes5 pages15 blocksSandstone
Pro
Open the full page for this template

Local Service

Hours, address and phone above the fold

Deep teal, for a business people let into their house. A booking widget above the fold, every price published, and a compliance footer with the registrations a regulated trade has to show.

4 routes4 pages14 blocksHarbour
Pro
Open the full page for this template

Marketplace

Both sides of the market on one page

Dark olive on warm off-white, built for two audiences at once: search and real listings for buyers, the seller economics below the fold, and a browse route behind it.

5 routes5 pages19 blocksMoss
Pro
Open the full page for this template

Enterprise

The security posture band

Burgundy and square corners — the register of things bought in a boardroom. Numbers in the hero, a comparison table that concedes rows, and published prices instead of a sales wall.

5 routes5 pages18 blocksClaret
Pro
Open the full page for this template

Integration Platform

The integration grid, sorted by depth

High-chroma blue. The connector names in the hero, a catalogue with honest live/beta/planned status, four SDK languages and a dated roadmap for everyone who is not on the list.

4 routes4 pages14 blocksCobalt
Pro
Open the full page for this template

Creator Course

The curriculum, module by module

Magenta-plum with the softest corners in the set, for one person selling one thing. A student testimonial as the hero, a long instructor section, one price and the refund policy on the page.

5 routes5 pages15 blocksPlum
Open the full page for this template

Newsletter

The archive, above the testimonials

One decision, made from the archive: a hero with the field in it, the back issues as the actual argument, and the three worries about handing over an address answered as content.

6 routes6 pages22 blocksTideline