Live · this page runs WaitlistKit

Capture real launch intent, not just emails.

A drop-in waitlist that asks why people want in — use case, the feature they'd actually pay for, and how much. Abuse-hardened, privacy-friendly, and stored in your own database.

Your own Cloudflare D1 No raw IPs, no trackers Spam-hardened by default

One row, captured

email "founder@launch.dev"
use_case "Beta for a CI dashboard"
desired_feature "csv-export"
wtp "19"
ip_hash "a91f… (salted)"
created_at "2026-…Z"

Every signup is a structured, deduplicated row you own — ready to read, export, or act on.

Try it live

This form is the real product.

Fill it in and your answer is stored the moment you submit — the same hardened endpoint you'd ship. No payment is taken and no email is sent; it only records intent.

email use case desired feature willingness to pay

Submit twice with the same email and it updates your one row — it never creates a duplicate.

No payment. No email sent. Just one row in the database.

Drop it in

Three files. Your database. Done.

WaitlistKit is the same hardened handler this page runs on. Point it at your D1, wire the endpoint, and call the client from your form.

1 · Database

# 1. Create your D1 database, paste the id into wrangler.toml
wrangler d1 create yourapp_waitlist

# 2. Apply the generated schema (local for dev, --remote on deploy)
wrangler d1 migrations apply yourapp_waitlist --local

2 · Endpoint

// src/routes/api/waitlist/+server.ts
import { createWaitlistHandler, methodNotAllowed } from "@micro/waitlist/server";
import { waitlistConfig } from "$lib/waitlist-config";

const handle = createWaitlistHandler(waitlistConfig);

export const POST = (event) => handle(event);
export const fallback = () => methodNotAllowed(); // others -> 405

3 · Your form

import { submitWaitlist } from "@micro/waitlist/client";

const res = await submitWaitlist({
  email, useCase, desiredFeature, willingnessToPay,
});
// res.ok === true the moment the row is upserted into your D1

Any framework

Works wherever you ship.

The API is a plain JSON POST — drop the snippet into your existing form, no SDK required.

<form id="wk-form">
  <input type="email" name="email" placeholder="you@example.com" required>
  <input type="text" name="website" style="display:none"> <!-- honeypot -->
  <button type="submit">Join waitlist</button>
  <p id="wk-msg"></p>
</form>
<script>
  document.getElementById('wk-form').addEventListener('submit', async (e) => {
    e.preventDefault();
    const form = e.target;
    const res = await fetch('/api/waitlist', {
      method: 'POST',
      headers: {'content-type': 'application/json'},
      body: JSON.stringify({ email: form.email.value, website: '' })
    });
    const data = await res.json();
    document.getElementById('wk-msg').textContent = data.ok ? "You're on the list!" : data.error;
  });
</script>

Hardened by default

A public write endpoint that won't get wrecked.

A waitlist is the first server surface most launches expose. WaitlistKit ships the defenses so a script kiddie can't drain your free tier or your wallet.

Idempotent upsert

Repeat submissions update one row on a UNIQUE natural key — they can never inflate row count or burn write quota.

Content-Length guard

Oversized bodies are rejected before they are ever parsed, so a giant payload can't tie up CPU.

Strict validation + clipping

Email regex, enum whitelists, and per-field length caps bound every row before it touches the database.

Honeypot

A hidden field silently rejects the simplest bots without a single third-party script.

Salted IP hash

IPs are stored only as SHA-256(salt:ip), never raw — and only when you set a salt. No raw PII.

Rate limit + Turnstile-ready

A per-IP throttle runs before the write; drop in a Turnstile key and server-side verification switches on automatically.

Pricing

Free to launch. Pay once when you outgrow it.

Start free with 100 submissions, referrals, and CSV export. The paid tiers are one-time — no subscription. Pick one to register interest; nothing is charged.

Free

$0 forever

Everything you need to launch a real waitlist.

  • 100 submissions
  • Referrals
  • CSV export
Most popular

Pro

$19 one-time

Pay once, point it at your own database, ship it as your own.

  • ~1,000 submissions
  • Your-own-DB webhook
  • Remove branding
Get on the list →

Scale

$49 one-time

Higher volume for launches that go big.

  • Everything in Pro
  • Higher submission limits
  • Priority support
Get on the list →

WaitlistKit

Privacy-friendly intent capture · your data stays in your Cloudflare account.

Not logged in · Free Log in →