VIP Early Access & Beta Waitlist Form
A high-converting SaaS beta and product launch waitlist form styled with a sleek obsidian cyan aesthetic. Features role selection, priority queue bumps for social handles, invisible honeypot anti-spam protection, and automated subscriber alerts dispatched to your marketing stack via Backforms.
Request Early Access
Minimalist horizontal waitlist bar. Captures work email and primary role with zero backend setup.
style="color:#9ece6a;">"use client";
import { useState } from style="color:#9ece6a;">"react";
import { Zap, Check, ArrowRight } from style="color:#9ece6a;">"lucide-react";
export default function EarlyAccessWaitlistForm() {
const [email, setEmail] = useState(style="color:#9ece6a;">"");
const [role, setRole] = useState(style="color:#9ece6a;">"Frontend");
const [handle, setHandle] = useState(style="color:#9ece6a;">"");
const [status, setStatus] = useState<style="color:#9ece6a;">"idle" | style="color:#9ece6a;">"loading" | style="color:#9ece6a;">"success" | style="color:#9ece6a;">"error">(style="color:#9ece6a;">"idle");
const [errorMessage, setErrorMessage] = useState(style="color:#9ece6a;">"");
const roles = [style="color:#9ece6a;">"Frontend", style="color:#9ece6a;">"Fullstack", style="color:#9ece6a;">"Founder", style="color:#9ece6a;">"Agency"];
async function handleSubmit(e: React.FormEvent<style="color:#f7768e;font-weight:600;">HTMLFormElement>) {
e.preventDefault();
setStatus(style="color:#9ece6a;">"loading");
setErrorMessage(style="color:#9ece6a;">"");
const form = e.currentTarget;
const formData = new FormData(form);
formData.set(style="color:#9ece6a;">"role", role);
try {
style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">// Replace YOUR_FORM_ID with your Backforms endpoint ID from app.backforms.com
const response = await fetch(style="color:#9ece6a;">"https:style="color:#565f89;font-style:italic;style="color:#9ece6a;">">//backforms.com/f/YOUR_FORM_ID", {
method: style="color:#9ece6a;">"POST",
headers: {
Accept: style="color:#9ece6a;">"application/json",
},
body: formData,
});
if (response.ok) {
setStatus(style="color:#9ece6a;">"success");
form.reset();
} else {
const data = await response.json().catch(() => null);
setErrorMessage(data?.error || style="color:#9ece6a;">"Waitlist registration failed. Please try again.");
setStatus(style="color:#9ece6a;">"error");
}
} catch {
setErrorMessage(style="color:#9ece6a;">"Network error. Please check your internet connection.");
setStatus(style="color:#9ece6a;">"error");
}
}
return (
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"flex flex-col items-center justify-center min-h-[500px] p-4">
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"w-full max-w-md bg-gradient-to-b from-[#0c161d] to-[#070d13] border border-cyan-500/30 rounded-2xl p-6 sm:p-7 shadow-2xl text-zinc-100">
{style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">/* Header Status */}
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"flex items-center justify-between mb-4 pb-3 border-b border-cyan-500/20">
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"flex items-center gap-2">
<style="color:#f7768e;font-weight:600;">span className=style="color:#9ece6a;">"size-2 rounded-full bg-cyan-400 animate-pulse"></style="color:#f7768e;font-weight:600;">span>
<style="color:#f7768e;font-weight:600;">span className=style="color:#9ece6a;">"text-[11px] font-mono uppercase tracking-wider text-cyan-300 font-bold">
Private Beta style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">// Wave 3
</style="color:#f7768e;font-weight:600;">span>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">span className=style="color:#9ece6a;">"text-[10px] font-mono text-emerald-300 bg-emerald-950/80 border border-emerald-500/30 px-2.5 py-0.5 rounded-full">
Limited Spots
</style="color:#f7768e;font-weight:600;">span>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">h2 className=style="color:#9ece6a;">"text-xl sm:text-2xl font-extrabold text-white mb-1 tracking-tight">
Join the Developer Beta
</style="color:#f7768e;font-weight:600;">h2>
<style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"text-xs text-zinc-400 mb-5 leading-relaxed">
Be the first to access next-generation serverless form tools before general release.
</style="color:#f7768e;font-weight:600;">p>
{status === style="color:#9ece6a;">"success" ? (
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"p-5 bg-cyan-950/50 border border-emerald-500/40 text-emerald-300 rounded-xl text-center space-y-2">
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"size-8 mx-auto rounded-full bg-emerald-950/70 border border-emerald-500/40 flex items-center justify-center text-emerald-400">
<style="color:#f7768e;font-weight:600;">Check className=style="color:#9ece6a;">"size-4 stroke-[2.5]" />
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"font-bold text-base text-white">You're On The Priority List!</style="color:#f7768e;font-weight:600;">p>
<style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"text-xs text-zinc-300">
Check your inbox for your access confirmation and exclusive invite link.
</style="color:#f7768e;font-weight:600;">p>
<style="color:#f7768e;font-weight:600;">button
type=style="color:#9ece6a;">"button"
onClick={() => setStatus(style="color:#9ece6a;">"idle")}
className=style="color:#9ece6a;">"mt-3 px-4 py-1.5 bg-cyan-600 hover:bg-cyan-500 text-zinc-950 font-bold rounded-lg text-xs transition cursor-pointer"
>
Add Another Email
</style="color:#f7768e;font-weight:600;">button>
</style="color:#f7768e;font-weight:600;">div>
) : (
<style="color:#f7768e;font-weight:600;">form onSubmit={handleSubmit} className=style="color:#9ece6a;">"space-y-3.5">
{style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">/* Invisible Honeypot Spam Trap */}
<style="color:#f7768e;font-weight:600;">input
type=style="color:#9ece6a;">"text"
name=style="color:#9ece6a;">"_gotcha"
style={{ display: style="color:#9ece6a;">"none" }}
tabIndex={-1}
autoComplete=style="color:#9ece6a;">"off"
/>
{status === style="color:#9ece6a;">"error" && (
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"p-3 bg-red-950/80 border border-red-500/50 text-red-300 text-xs rounded-lg">
{errorMessage}
</style="color:#f7768e;font-weight:600;">div>
)}
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1" htmlFor=style="color:#9ece6a;">"waitlist-email">
Work Email
</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">input
id=style="color:#9ece6a;">"waitlist-email"
name=style="color:#9ece6a;">"email"
type=style="color:#9ece6a;">"email"
required
placeholder=style="color:#9ece6a;">"alex@company.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
className=style="color:#9ece6a;">"w-full bg-[#121f29] text-white border border-cyan-500/25 rounded-lg px-3.5 py-2 text-sm placeholder:text-zinc-500 focus:outline-none focus:border-cyan-400 transition"
/>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1.5">
Primary Developer Role
</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"grid grid-cols-4 gap-1.5">
{roles.map((r) => (
<style="color:#f7768e;font-weight:600;">button
key={r}
type=style="color:#9ece6a;">"button"
onClick={() => setRole(r)}
className={`py-2 px-1 text-xs font-mono rounded-lg transition-all text-center cursor-pointer ${
role === r
? style="color:#9ece6a;">"bg-cyan-400 text-zinc-950 font-bold shadow-xs"
: style="color:#9ece6a;">"bg-[#121f29] text-zinc-400 border border-cyan-500/20 hover:text-white"
}`}
>
{r}
</style="color:#f7768e;font-weight:600;">button>
))}
</style="color:#f7768e;font-weight:600;">div>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1" htmlFor=style="color:#9ece6a;">"waitlist-handle">
GitHub or X Handle <style="color:#f7768e;font-weight:600;">span className=style="color:#9ece6a;">"text-cyan-400 text-[11px] font-mono">(Priority Queue Jump)</style="color:#f7768e;font-weight:600;">span>
</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">input
id=style="color:#9ece6a;">"waitlist-handle"
name=style="color:#9ece6a;">"handle"
type=style="color:#9ece6a;">"text"
placeholder=style="color:#9ece6a;">"@username"
value={handle}
onChange={(e) => setHandle(e.target.value)}
className=style="color:#9ece6a;">"w-full bg-[#121f29] text-white border border-cyan-500/25 rounded-lg px-3.5 py-2 text-sm placeholder:text-zinc-500 focus:outline-none focus:border-cyan-400 transition"
/>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">button
type=style="color:#9ece6a;">"submit"
disabled={status === style="color:#9ece6a;">"loading"}
className=style="color:#9ece6a;">"w-full mt-2 bg-gradient-to-r from-cyan-400 via-teal-300 to-emerald-400 hover:from-cyan-300 hover:to-emerald-300 text-zinc-950 font-extrabold py-2.5 px-4 rounded-xl transition cursor-pointer shadow-lg shadow-cyan-500/25 disabled:opacity-60 flex items-center justify-center gap-2"
>
<style="color:#f7768e;font-weight:600;">Zap className=style="color:#9ece6a;">"size-4 fill-zinc-950" />
<style="color:#f7768e;font-weight:600;">span>{status === style="color:#9ece6a;">"loading" ? style="color:#9ece6a;">"Claiming Access..." : style="color:#9ece6a;">"Claim Priority Access"}</style="color:#f7768e;font-weight:600;">span>
<style="color:#f7768e;font-weight:600;">ArrowRight className=style="color:#9ece6a;">"size-4" />
</style="color:#f7768e;font-weight:600;">button>
</style="color:#f7768e;font-weight:600;">form>
)}
</style="color:#f7768e;font-weight:600;">div>
</style="color:#f7768e;font-weight:600;">div>
);
}Connect this component to your Backforms endpoint
Create a free form endpoint in under 30 seconds. Zero backend servers or databases required.
Frequently Asked Questions & Technical Integration
How does Backforms handle early access waitlists?
Backforms captures waitlist signups in real-time, logs user metadata (roles, timestamps, referrers), and integrates directly with email autoresponders and Google Sheets.
Can I assign automated queue numbers or trigger verification emails?
Yes! You can configure Backforms auto-reply emails to send custom welcome notes, access tokens, or invite links automatically.
Does this template include honeypot anti-spam protection?
Yes, an invisible _gotcha trap is embedded in the form markup, ensuring bots and fake signups are filtered out without interrupting real humans.