Waitlist Form Block React component
A waitlist signup block: one email field, then your place in line counting into view with a progress bar, an invite link to copy or share that moves you up for every friend who joins, reward tiers that unlock, and a live waiting count.
About the Waitlist Form Block component
Waitlist Form Block turns a plain email signup into a reason to come back. After someone joins, the form becomes a card with their place in line, counting into view, a progress bar and the reward they have unlocked or are close to.
Their invite link sits underneath with Copy and Share buttons, and every friend who joins with it moves them up a set number of places. Reward tiers show what the front of the line gets, and a live count of people waiting keeps the page feeling busy.
When to use it
Use it on a coming-soon page, a product launch page or a private beta signup.
Pair it with a server that records referrals by the ref in the invite link.
Installation
Add the Waitlist Form Block component to your project with the shadcn CLI. It lands in components/waitlist-form-block.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/waitlist-form-blockOr copy the source by hand and install its dependencies:
npm install motion clsx tailwind-mergeProps
<WaitlistFormBlock /> accepts 11 props, all optional.
| Prop | Type | Default |
|---|---|---|
| badge | string | "Launching February 2027" |
| title | string | "Be first in line for Nexora mobile" |
| description | string | "Plan from your phone, offline, with the same docs and boards. Join the waitlist and move… |
| initialCount People already on the list, shown under the form. | number | 12480 |
| avatars Avatars next to the count. Pass [] to hide them. | string[] | ["/demo/41.webp", "/demo/42.webp", "/demo/44.webp", "/demo/49.webp", "/demo/47.webp"] |
| placesPerReferral Places someone moves up for each friend who joins with their link. | number | 250 |
| rewards What people get as they move up, from the top of the list down. | { places: number; label: string }[] | DEFAULT_REWARDS |
| onJoin Called with the email. Return { position, referralUrl } (or a promise of it). A rejection or a returned string shows an error. Without it a demo position is generated. | (email: string) => WaitlistJoinResult | string | Promise<WaitlistJoinResult | string> | — |
| liveCount Grow the joined count now and then, so the list feels alive. | boolean | true |
| theme | "dark" | "light" | "dark" |
| className | string | — |
- badgestringDefault: "Launching February 2027"
- titlestringDefault: "Be first in line for Nexora mobile"
- descriptionstringDefault: "Plan from your phone, offline, with the same docs and boards. Join the waitlist and move…
- initialCount
People already on the list, shown under the form.
numberDefault: 12480 - avatars
Avatars next to the count. Pass [] to hide them.
string[]Default: ["/demo/41.webp", "/demo/42.webp", "/demo/44.webp", "/demo/49.webp", "/demo/47.webp"] - placesPerReferral
Places someone moves up for each friend who joins with their link.
numberDefault: 250 - rewards
What people get as they move up, from the top of the list down.
{ places: number; label: string }[]Default: DEFAULT_REWARDS - onJoin
Called with the email. Return { position, referralUrl } (or a promise of it). A rejection or a returned string shows an error. Without it a demo position is generated.
(email: string) => WaitlistJoinResult | string | Promise<WaitlistJoinResult | string> - liveCount
Grow the joined count now and then, so the list feels alive.
booleanDefault: true - theme"dark" | "light"Default: "dark"
- classNamestring
npm dependencies
Installed for you by the shadcn CLI.
Waitlist Form Block FAQ
- How do I connect it to my backend?
- Handle onJoin(email) and return { position, referralUrl } from your API. Read the ref query parameter on the page and send it with the email so your server can credit the person who invited them.
- How do referrals move people up?
- Each referral moves the visitor up placesPerReferral places. In your app, recalculate positions on the server; the Simulate a friend joining link in the demo shows how the card reacts.
- What are the reward tiers?
- Pass rewards as { places, label } in order from the front of the line, for example { places: 100, label: "First 100: lifetime 50% off" }. The card names the reward reached and how many friends are needed for the next.
- Is the live count real?
- No, liveCount just nudges the number up every few seconds so the page feels active. Pass the real number as initialCount and set liveCount={false} if you prefer it to stay still.
- Does sharing work on phones?
- Share uses the device's share sheet where it exists (most phones) and falls back to copying the link elsewhere.