·6 min read

Add a Waitlist to a Next.js App (3 Ways, ~5 Minutes)

Add a Waitlist to a Next.js App (3 Ways, ~5 Minutes)

The short answer

The fastest way to add a waitlist to a Next.js app is to point a plain HTML form at a hosted waitlist endpoint; no backend code at all. If you want the signup handled server-side (custom UI, position shown in your own page), use a server action or route handler with the waitlister SDK. All three patterns below are copy-paste and were verified against the live API.

Prerequisite for all three: a waitlist and its waitlist key. Create one free at Waitlister (the key is on your waitlist's Overview page — quickstart here). Options 2 and 3 also need an API key (waitlist Settings; API access needs the Growth plan). Option 1 works on every plan.

Building this with an AI coding agent? Hand it waitlister.me/skill.md; it contains everything on this page in one fetchable file.

Option 1 — plain form action, no backend (any plan)

Point a form straight at the waitlist's form-action endpoint. Works in Next.js, plain React, or raw HTML; the subscriber is redirected to a hosted thank-you page showing their queue position and referral link.

tsx
// app/page.tsx — works as-is in a server or client component
export default function Home() {
  return (
    <form action="https://waitlister.me/s/YOUR_WAITLIST_KEY" method="POST">
      <input type="email" name="email" placeholder="you@example.com" required />
      <button type="submit">Join the waitlist</button>
    </form>
  )
}

One setup step: add your site's domain to the waitlist's whitelisted domains (waitlist → Settings), or submissions return 403. Optional fields: name, phone, referred_by; any other input name is stored as metadata.

Use this when you want zero server code and the hosted thank-you page is fine.

Option 2 — server action + SDK (App Router)

Keep users on your page and control the whole experience. Install the SDK:

bash
npm install waitlister

Set your keys in .env.local (the SDK reads these names automatically):

bash
WAITLISTER_API_KEY=your-api-key
WAITLISTER_WAITLIST_KEY=your-waitlist-key
ts
// app/actions.ts
'use server'
import { Waitlister } from 'waitlister'

const wl = new Waitlister() // picks up the env vars

export async function joinWaitlist(formData: FormData) {
  const result = await wl.signUp({
    email: formData.get('email') as string,
    name: (formData.get('name') as string) || undefined
  })
  return {
    position: result.position,
    referralCode: result.referral_code
  }
}

Wire it to a client component and show the position on success. Two behaviors worth knowing: signups are idempotent per email (re-submitting returns the existing position, not an error), and the API key never reaches the browser because the action runs server-side.

Plan notes: wl.signUp needs API access (Growth plan). On a plan without it, the SDK throws a typed PlanError rather than failing silently. On the free plan you can keep the exact same server-action pattern with signUpViaForm from the same package — no API key, and it returns the hosted thank-you page URL to redirect() to instead of position data.

Option 3 — REST route handler (no SDK, or Pages Router)

The same thing with a route handler and plain fetch, if you'd rather not add a dependency:

ts
// app/api/waitlist/route.ts
export async function POST(req: Request) {
  const { email, name } = await req.json()

  const res = await fetch(
    `https://waitlister.me/api/v1/waitlist/${process.env.WAITLISTER_WAITLIST_KEY}/sign-up`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Api-Key': process.env.WAITLISTER_API_KEY!
      },
      body: JSON.stringify({ email, name })
    }
  )

  const data = await res.json()
  return Response.json(data, { status: res.status })
}

Auth is the X-Api-Key header (not a Bearer token). The full request/response schema, including error codes, is in the machine-readable OpenAPI spec; the human version is in the API reference.

Verify it works

  1. Submit a real email address. Deliverability is validated at signup, so fake test addresses get rejected with a 400.
  2. Expect success: true with a position (options 2–3) or a redirect to the thank-you page (option 1).
  3. Submit the same email again: you should get is_new_sign_up: false with the same position. That confirms the signup persisted.

FAQ

Can I add a waitlist to Next.js without a backend?

Yes. Point any form's action at https://waitlister.me/s/{your-waitlist-key} (option 1). No API key, no server code; it works on static exports and every plan, as long as your domain is whitelisted in the waitlist settings.

Does this work with plain React or Vite apps?

Options 1 and 3 do, unchanged: option 1 is plain HTML, and option 3's route handler can live in any backend. Option 2's server action is Next.js App Router-specific.

How do subscribers see their queue position?

Option 1 redirects them to a hosted thank-you page with their position and referral link. Options 2–3 return position and referral_code in the response, so you render it however you want — or use the returned redirect_url to send them to the hosted thank-you page.

How do referrals work in a custom integration?

Every signup gets a referral_code. Put it in your share links as ?ref=<code>, then pass incoming codes back as referredBy (SDK), metadata.referred_by (REST), or referred_by/ref (form fields). Points, position changes, and fraud detection are handled for you. Details: referral program.

Helpful resources

Share this article