·7 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: a waitlist. Two ways to get one:

  • Dashboard: create one free at Waitlister; the waitlist key is on its Overview page (quickstart). That's all option 1 needs.
  • From code: with an account API key (wl_acct_…, Settings → API keys) you can create the waitlist programmatically and sign up subscribers with the same key — no dashboard step, works on every plan including free.

Building this with an AI coding agent? Hand it waitlister.me/skill.md (everything on this page in one fetchable file), or add the official MCP server, @waitlister/mcp, and the agent can create the waitlist, wire the form, and verify the signup itself. When we tested this with a fresh coding agent and only an account key, it had a live waitlist created in about three minutes and a verified real signup in about seven.

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
# Account key (Settings → API keys) — works on every plan:
WAITLISTER_ACCOUNT_KEY=wl_acct_your-key
WAITLISTER_WAITLIST_KEY=your-waitlist-key

# Or the classic pair: a per-waitlist API key (waitlist Settings, Growth plan+)
# WAITLISTER_API_KEY=your-api-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 key never reaches the browser because the action runs server-side.

Plan notes: with an account key, signUp works on every plan, including free (with lower rate limits). A per-waitlist API key needs the Growth plan; on a plan without API access the SDK throws a typed PlanError rather than failing silently. The zero-key fallback still exists: signUpViaForm from the same package uses the public form endpoint and returns the hosted thank-you page URL to redirect() to.

Create the waitlist from code

If you don't have a waitlist yet, an account key lets the SDK create one. Useful in setup scripts, CLIs, and agent workflows:

ts
import { Waitlister } from 'waitlister'

const wl = new Waitlister({ accountKey: process.env.WAITLISTER_ACCOUNT_KEY })

const { waitlist } = await wl.waitlists.create({ name: 'My Product' })
waitlist.key             // use as WAITLISTER_WAITLIST_KEY
waitlist.form_action_url // option 1's form target — signups work immediately

Works on every plan, within your plan's waitlist cap. Waitlist names and URL slugs are unique across all of Waitlister, so a taken name is rejected with a message telling you what to change. One key then covers everything: wl.waitlist(waitlist.key).signUp(…), .stats(), and (on Growth+) API subscriber management.

Show a live signup count

Social proof for your landing page: the stats endpoint works with an account key on every plan, and its counters update within about ten seconds of a signup:

ts
const { subscribers_total } = await wl.waitlist(key).stats()
// → "Join 1,204 people waiting"

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_ACCOUNT_KEY!  // or a per-waitlist 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) and accepts either key type — account keys work on every waitlist you own. The full request/response schema, including the account-scoped POST /api/v1/waitlists for creating waitlists, 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.

Can I create the waitlist itself from code?

Yes. wl.waitlists.create({ name }) with an account key (wl_acct_…, Settings → API keys) returns the waitlist key and a working form URL in one call. It works on every plan within your plan's waitlist cap. The same key signs up subscribers and reads stats; managing the subscriber list via the API needs Growth or higher.

Can my AI coding agent set this up for me?

Yes. Give the agent an account key plus waitlister.me/skill.md, or install @waitlister/mcp in your MCP client. The API returns actionable error messages (plan caps, taken names, auth mistakes) that agents can self-correct from. In our test, a fresh agent with only an account key created the waitlist in about three minutes and had a verified real signup in about seven.

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