Skip to main content

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.

Dynamic queue position & viral priority bump
Developer role & persona selector
Invisible honeypot (_gotcha) spam trap
Full React / Next.js client component with state
Instant subscriber sync to Google Sheets & Email
Live Form PreviewComponent Sandbox

Request Early Access

Minimalist horizontal waitlist bar. Captures work email and primary role with zero backend setup.

What describes your role best?
Pre-configured for Backforms endpoint with CSV export and Sheets sync
Honeypot anti-spam active
Zero backend needed
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&apos;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>
  );
}
Replace YOUR_FORM_ID with your Backforms key

Connect this component to your Backforms endpoint

Create a free form endpoint in under 30 seconds. Zero backend servers or databases required.

Get Free Endpoint Key

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.