Zum Inhalt springen
    WingoUI
    KomponentenVorlagenDokuPreiseKI-AgentenBlogChangelog
    1. Startseite
    2. Blog
    3. Praxis: Screens und Apps
    4. Nextjs Waitlist Page: Countdown, Empfehlungen, echte Zahlen
    Read in English
    1. Blog
    2. Praxis: Screens und Apps
    3. Nextjs Waitlist Page: Countdown, Empfehlungen, echte Zahlen
    Praxis: Screens und Apps
    Praxis: Screens und Apps

    Nextjs Waitlist Page: Countdown, Empfehlungen, echte Zahlen

    SR
    Serban Rusu · Gründer von Wingo UI
    16. Okt. 2026 · 10 Min. Lesezeit

    Auf dieser Seite

    0%
    1. Was braucht eine Warteliste-Landingpage?
    2. Wie installiere ich die Next.js-Waitlist-Vorlage?
    3. Wie speichere ich Anmeldungen und berechne den Platz auf der Liste?
    4. Wie verbinde ich das Formular mit einer Server Action?
    5. Sollte eine Waitlist Page die Anmeldezahl zeigen?
    6. Wie baue ich einen Launch-Countdown in Next.js ein?
    7. Was sollte ich ergänzen, bevor ich den Link zur Warteliste teile?
    8. Wie geht es weiter?
    9. Häufige Fragen
      1. Wie baue ich eine Waitlist Page in Next.js?
      2. Wie berechnet eine Referral-Warteliste den Platz auf der Liste?
      3. Sollte eine Waitlist Page zeigen, wie viele sich angemeldet haben?
      4. Ist die Waitlist-Vorlage von Wingo UI kostenlos?
      5. Wie verhindere ich, dass jemand eine Referral-Warteliste austrickst?

    Kurz gesagt

    Eine Next.js Waitlist Page braucht fünf Teile: einen Countdown bis zum Launch, ein einziges E-Mail-Feld, den Platz der Person auf der Liste, einen Empfehlungslink, der sie nach vorn bringt, und eine Anmeldezahl, die nur erscheint, wenn sie echt ist. Den Screen baust du mit der Vorlage Waitlist Page von Wingo UI, die Anmeldungen speicherst du über eine Server Action in einer einzigen Postgres-Tabelle. Position und Empfehlungscode kommen dann aus deiner Datenbank statt aus den Beispielzahlen der Vorlage.

    Veröffentlicht am 16. Okt. 2026

    Eine Nextjs Waitlist Page ist oft die erste Seite, die ein Produkt hat, und sie geht schnell mit den Beispielzahlen der Vorlage online. Die Defaults unserer eigenen Vorlage zeigen eine Zeile „Join 4,812 people“, eine Position, die einfach die Zahl plus eins ist, und einen Empfehlungscode, den keine Datenbank kennt. Dieses Tutorial baut eine Pre-Launch-Seite in Next.js 16 mit einem Countdown bis zum Launch, einer E-Mail-Anmeldung, dem echten Platz der Person auf der Liste, einem Empfehlungslink, der sie nach vorn bringt, und einer Anmeldezahl, die nur erscheint, wenn sie stimmt.

    Was braucht eine Warteliste-Landingpage?

    Eine Warteliste-Landingpage braucht fünf Teile, denn sie hat nur eine Aufgabe: die E-Mail-Adresse von jemandem bekommen, der interessiert ist, und ihm einen Grund geben, einen Freund mitzubringen.

    1. Ein Launch-Datum oder ein klares „bald verfügbar“. Ein Countdown funktioniert, wenn du ein Datum hast, das du auch hältst. Ohne Datum schreibst du „bald verfügbar“ und lässt den Timer weg.
    2. Ein einziges E-Mail-Feld. Jedes weitere Feld ist eine Sache mehr, die vor der Belohnung ausgefüllt werden muss. Mehr als ein optionales Select für die Rolle würden wir nicht ergänzen.
    3. Ein Platz auf der Liste nach der Anmeldung. „Du bist #213“ ist die Belohnung für das Eintippen der E-Mail und gibt dem Empfehlungslink einen Zweck.
    4. Ein Empfehlungslink, den man mit einem Tipp kopiert und teilt. Jede Anmeldung bekommt einen eigenen Code; Freunde, die sich damit eintragen, bringen die empfehlende Person nach vorn.
    5. Social Proof nur, wenn er echt ist. Der Pre-Launch-Waitlist-Guide von KickoffLabs (opens in a new tab) empfiehlt, die Zahl zu zeigen, und sagt, dass kleine Zahlen schaden: Null und zehn fühlen sich beide schlecht an. Als Größe, ab der eine Zahl FOMO auslöst, nennt er 500 oder mehr (geprüft am 16. Oktober 2026). Genau dieser Druck bringt gefälschte Zahlen in die Produktion. Die Lösung: Lies die Zahl aus der Datenbank und blende sie aus, bis sie es wert ist, gezeigt zu werden.

    Wenn du lieber einen Next.js-Starter als eine Komponentenbibliothek willst, findest du bei Vercel Waitly (opens in a new tab). Waitly speichert Anmeldungen in Notion, begrenzt die Rate mit Upstash Redis und verschickt E-Mails über Resend; sein Notion-Schema enthält Felder für den Empfehlungscode und die empfehlende Person (geprüft am 16. Oktober 2026). Dieser Beitrag geht den anderen Weg: ein fertiger Screen aus einer Komponentenbibliothek und ein Speicher, der dir gehört.

    Wie installiere ich die Next.js-Waitlist-Vorlage?

    Wingo UI liefert den Screen als Vorlage Waitlist Page: den Countdown, das E-Mail-Formular, die Erfolgskarte mit Position und Empfehlungslink, Feature-Teaser und ein FAQ. Falls du nach „nextjs waitlist template“ gesucht hast: Das hier ist eins im Sinne von shadcn. Der Quellcode wird in dein Projekt kopiert, du kannst also jede Zeile ändern.

    bash
    npx wingo-ui@latest add waitlist-page

    Das fügt components/templates/waitlist-page.tsx hinzu, dazu die Datei mit den Beispieldaten und die Teile, die die Vorlage nutzt: den Countdown, den Copy Button für den Empfehlungslink, das Accordion für das FAQ, das Select für die optionale Rolle, außerdem Marketing-Header, Footer und die Section-Blöcke.

    Probier den Ablauf aus, bevor du irgendetwas verdrahtest. Die Demo unten nutzt ein simuliertes Backend, das 900 ms wartet und eine Position zurückgibt.

    Gib eine E-Mail ein und drück Join the waitlist: Der Button dreht sich, dann wird aus dem Formular dein Platz auf der Liste mit einem Empfehlungslink zum Kopieren und Teilen. Eine ungültige Adresse zeigt zuerst einen Fehler direkt am Feld
    $ npx wingo-ui@latest add waitlist-page
    ProDoku: Waitlist Page

    Die Props, auf die es in diesem Tutorial ankommt, alle aus dem Quellcode der Vorlage:

    PropDefaultWas es macht
    launchAt"2026-11-17T17:00:00.000Z"Ziel des Countdowns und Datum in der Pill; null ergibt eine Seite „bald verfügbar“
    count4812Die Zeile „Join N people“ und die Fallback-Position (count + 1)
    peoplesechs BeispielnamenDer Stapel mit Initialen neben der Zahl
    onJoinwartet 900 msBekommt { email, role }; darf { position, referralCode } zurückgeben; ein abgelehntes Promise zeigt den Formularfehler
    referralUrlhttps://acme.com/mobile?ref=Der Link zum Teilen ist dieser Wert plus der Code
    spotsPerReferral10Die Zahl in „Move up 10 spots for every friend who joins“
    rolessechs BeispielrollenOptionen des optionalen Rollen-Selects; [] blendet es aus
    showSocialstrueDas Band „Follow the build“ mit Beispiel-Links zu sozialen Netzwerken
    labels, features, faqsAcme-BeispieltexteJeder sichtbare Text

    Achte auf die Defaults für count und people. Es gibt sie, damit der Screen in einer Vorschau fertig aussieht. Wenn du sie auslieferst, behauptet deine Seite 4.812 Anmeldungen, die du nicht hast. Der Rest dieses Tutorials ersetzt beide durch echte Daten.

    Wie speichere ich Anmeldungen und berechne den Platz auf der Liste?

    Eine einzige Postgres-Tabelle reicht für die Daten. Der Empfehlungsbonus steht in einer winzigen gemeinsamen Datei, weil sowohl die Abfrage als auch der Text auf der Seite ihn brauchen:

    ts
    // app/waitlist/config.ts
    export const SPOTS_PER_REFERRAL = 10

    Die Tabelle hält den Rest. Jede Zeile hat die E-Mail, eine optionale Rolle, einen zufälligen Empfehlungscode und den Code der Person, die empfohlen hat.

    sql
    create table waitlist (
    id bigserial primary key,
    email text not null unique,
    role text,
    referral_code text not null unique,
    referred_by text references waitlist (referral_code),
    created_at timestamptz not null default now()
    );
    create index waitlist_referred_by on waitlist (referred_by);

    Die Regel für die Position: Dein Score ist deine Anmeldereihenfolge minus 10 für jede Person, die mit deinem Code beigetreten ist. Deine Position ist eins plus die Zahl der Leute mit niedrigerem Score, bei Gleichstand gewinnt, wer sich früher angemeldet hat. Die Reihenfolge kommt aus row_number() und nicht direkt aus id: Ein insert ... on conflict verbraucht auch dann einen Wert der Sequenz, wenn es nur aktualisiert. Wiederholte Anmeldungen hinterlassen also Lücken in id, und durch eine Lücke wäre ein Bonus von 10 Plätzen weniger als 10 Personen wert. Diese Skizze nutzt den Client postgres (opens in a new tab) (npm install postgres); jeder Treiber, der SQL ausführt, funktioniert genauso.

    ts
    // app/waitlist/waitlist-db.ts
    import "server-only"
    import { randomBytes } from "node:crypto"
    import postgres from "postgres"
    import { SPOTS_PER_REFERRAL } from "./config"
    const sql = postgres(process.env.DATABASE_URL!)
    export async function waitlistCount() {
    const [row] = await sql`select count(*)::int as count from waitlist`
    return row.count as number
    }
    async function positionOf(code: string) {
    const [row] = await sql`
    with scored as (
    select w.id, w.referral_code,
    row_number() over (order by w.id) - ${SPOTS_PER_REFERRAL} * (
    select count(*) from waitlist r where r.referred_by = w.referral_code
    ) as score
    from waitlist w
    )
    select count(*)::int + 1 as position
    from scored s
    join scored me on me.referral_code = ${code}
    where s.score < me.score or (s.score = me.score and s.id < me.id)`
    return row.position as number
    }
    export async function addToWaitlist(input: { email: string; role?: string; ref?: string }) {
    // eine empfehlung zählt nur, wenn der code existiert
    const [referrer] = input.ref
    ? await sql`select referral_code from waitlist where referral_code = ${input.ref}`
    : []
    // wer zweimal beitritt, bekommt die erste zeile zurück: gleicher code, gleiche empfehlung
    const [row] = await sql`
    insert into waitlist (email, role, referral_code, referred_by)
    values (
    ${input.email},
    ${input.role ?? null},
    ${randomBytes(6).toString("hex")},
    ${referrer?.referral_code ?? null}
    )
    on conflict (email) do update set email = excluded.email
    returning referral_code`
    const referralCode = row.referral_code as string
    return { referralCode, position: await positionOf(referralCode) }
    }

    Zwei Details tragen hier das meiste Gewicht. Die Klausel on conflict sorgt dafür, dass eine wiederholte Anmeldung den ursprünglichen Code zurückgibt statt eines Fehlers; wer zweimal beitritt, sieht also denselben Link. Und weil die empfehlende Person nur beim ersten Insert gespeichert wird, ändert eine erneute Anmeldung über deinen eigenen Link nicht, wer dich empfohlen hat. Die Vorlage exportiert auch einen Helper referralCode(email), der aus der Adresse einen kurzen Code ableitet. Für Vorschauen taugt das als Fallback, aber einen zufälligen Code aus der Datenbank kann niemand aus einer E-Mail-Adresse erraten.

    Jede Abfrage der Position berechnet den Score für die ganze Tabelle. Das ist günstig, solange die Liste klein ist und referred_by einen Index hat. Wenn sie wächst, leg eine Zählerspalte referrals an, erhöh sie, sobald eine empfohlene Anmeldung eintrifft, und berechne den Score aus dieser Spalte statt aus der Unterabfrage.

    Wie verbinde ich das Formular mit einer Server Action?

    Die Vorlage ist eine Client-Komponente, also teilt sich die Seite in zwei Teile: eine Server Component, die Daten liest, und einen kleinen Client-Wrapper, der die Vorlage rendert. Das Speichern läuft über eine Server Action, die die E-Mail prüft und genau die Form zurückgibt, die onJoin erwartet.

    ts
    // app/waitlist/actions.ts
    "use server"
    import { addToWaitlist } from "./waitlist-db"
    const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    export async function joinWaitlist(entry: { email: string; role?: string }, ref?: string) {
    const email = entry.email.trim().toLowerCase()
    if (email.length > 254 || !EMAIL.test(email)) throw new Error("Ungültige E-Mail-Adresse")
    return addToWaitlist({ email, role: entry.role?.slice(0, 40), ref })
    }

    Wirft die Action einen Fehler, wird das Promise abgelehnt und das Formular zeigt seine Meldung „That didn't work“. Wird es erfüllt, zeigt die Erfolgskarte die Position und baut den Link zum Teilen aus referralUrl plus dem zurückgegebenen Code.

    Die Seite selbst ist eine Server Component und liest den Code ref aus der URL und die echte Zahl. In Next.js 16 ist searchParams ein Promise, und sobald du es liest, rendert die Seite pro Request. Genau das willst du hier ohnehin, weil sich die Zahl ändert.

    tsx
    // app/waitlist/page.tsx
    import type { Metadata } from "next"
    import { Waitlist } from "./waitlist"
    import { waitlistCount } from "./waitlist-db"
    export const metadata: Metadata = {
    title: "Warteliste für Acme Notes",
    description: "Acme Notes startet am 1. Dezember. Trag dich auf die Warteliste ein und hol dir eine Einladung.",
    }
    export default async function WaitlistRoute({ searchParams }: PageProps<"/waitlist">) {
    const { ref } = await searchParams
    const count = await waitlistCount()
    return <Waitlist count={count} referredBy={typeof ref === "string" ? ref : undefined} />
    }

    Sollte eine Waitlist Page die Anmeldezahl zeigen?

    Zeig sie nur, wenn sie echt ist und groß genug, um zu helfen. Übergib die echte Zahl aus der Datenbank und übergib 0, bis sie eine Schwelle überschreitet, die du festlegst: Die Vorlage rendert die Zeile „Join N people“ und den Stapel mit Initialen nur, wenn count größer als null ist. Der Wrapper unten nutzt 500, die Größe, die der Guide von KickoffLabs nennt. Übergib in jedem Fall people={[]}: Das sind Beispielnamen, und für die Initialen echter Menschen brauchst du deren Erlaubnis.

    tsx
    // app/waitlist/waitlist.tsx
    "use client"
    import Link from "next/link"
    import { WaitlistPage } from "@/components/templates/waitlist-page"
    import { joinWaitlist } from "./actions"
    import { SPOTS_PER_REFERRAL } from "./config"
    // darunter schadet eine kleine zahl, also bleibt die zeile verborgen
    const MIN_SOCIAL_PROOF = 500
    export function Waitlist({ count, referredBy }: { count: number; referredBy?: string }) {
    return (
    <WaitlistPage
    linkComponent={Link}
    launchAt="2026-12-01T17:00:00Z"
    count={count >= MIN_SOCIAL_PROOF ? count : 0}
    people={[]}
    roles={[]}
    spotsPerReferral={SPOTS_PER_REFERRAL}
    referralUrl="https://example.com/waitlist?ref="
    onJoin={(entry) => joinWaitlist(entry, referredBy)}
    showSocials={false}
    labels={{
    pillSoon: "Acme Notes · Bald verfügbar",
    pillLaunch: (date) => `Acme Notes · Start am ${date}`,
    title: "Notizen, die sich selbst sortieren",
    description: "Schreib, wo du willst. Acme Notes legt es ab, verknüpft es und findet es wieder. Trag dich auf die Warteliste ein und hol dir eine frühe Einladung.",
    countdownDone: "Acme Notes ist offen. Die Einladungen gehen jetzt raus.",
    shareText: "Ich stehe jetzt auf der Warteliste von Acme Notes.",
    emailSubject: "Komm mit auf die Warteliste von Acme Notes",
    }}
    features={[
    { title: "Erst schreiben", description: "Öffne die App und tipp los. Ordner und Tags kommen später oder nie." },
    { title: "Von Anfang an verknüpft", description: "Erwähne eine Notiz und Acme verlinkt in beide Richtungen." },
    { title: "Suche, die mitliest", description: "Finde eine Notiz an dem, was drinsteht, nicht an ihrem Namen." },
    ]}
    faqs={[
    { question: "Wann startet Acme Notes?", answer: "Am 1. Dezember 2026. Die Einladungen gehen in der Reihenfolge der Liste raus." },
    { question: "Wie komme ich nach vorn?", answer: `Jeder Freund, der über deinen Link beitritt, bringt dich ${SPOTS_PER_REFERRAL} Plätze nach vorn.` },
    { question: "Kann ich die Liste wieder verlassen?", answer: "Jederzeit, über den Link in jeder E-Mail, die wir dir schicken." },
    ]}
    />
    )
    }

    Die Konstante kommt aus config.ts und nicht aus waitlist-db.ts, denn wenn du die Datenbank-Datei in eine Client-Komponente importierst, ziehst du den Postgres-Treiber und DATABASE_URL Richtung Browser-Bundle. Die Zeile import "server-only" oben in waitlist-db.ts macht aus diesem Fehler einen Build-Fehler statt einer Überraschung zur Laufzeit; Next.js behandelt den Import selbst, das Paket server-only zu installieren ist optional.

    Halte FAQ und Erfolgskarte auf dem Stand deiner tatsächlichen Regeln. Das Beispiel-FAQ der Vorlage verspricht 10 Plätze pro Empfehlung; wenn deine Abfrage 5 nutzt, müssen Prop und Text beide 5 sagen. Ersetz vor dem Launch jeden Beispieltext in labels, features und faqs, auch die Pill: Die Vorlage formatiert das Launch-Datum in der Zeitzone von New York. Startest du um Mitternacht in Europa, schreib das Datum in pillLaunch selbst, statt das übergebene Argument zu nutzen.

    Das ist der ganze Ablauf einer Referral-Warteliste in React: Jemand öffnet /waitlist?ref=3f9a1c2b7d04, die Seite liest auf dem Server den Code, das Formular schickt ihn mit der E-Mail mit, und die neue Zeile schreibt die Empfehlung bei der nächsten Abfrage der Position gut.

    Wie baue ich einen Launch-Countdown in Next.js ein?

    Übergib den Launch-Zeitpunkt als ISO-String an launchAt, und die Vorlage reicht ihn an die Countdown-Komponente weiter. Die übernimmt für dich das Ticken, die Zeit bis zur Hydration und das Ende. Mit der Zeit lässt der Countdown führende Einheiten weg, die auf null stehen (Tage, solange der Launch weit weg ist, in der letzten Stunde nur noch Minuten und Sekunden), tickt an den Grenzen der Einheiten und zeigt bei null die Meldung aus countdownDone. Bis der Client nach der Hydration die Uhrzeit kennt, rendern die Ziffern als -- in ihrer endgültigen Breite, also verschiebt sich nichts. Renderst du die Seite für Screenshots oder brauchst du festes Server-HTML, legt das Prop now die Uhrzeit fest.

    Dieselbe Komponente kannst du auch außerhalb der Seite nutzen, zum Beispiel in einer Ankündigungsleiste auf der Hauptseite. Die Variante text schreibt die verbleibende Zeit in Worten mitten in einen Satz:

    tsx
    import { Countdown } from "@/components/ui/countdown"
    export function LaunchBar() {
    return (
    <p className="text-sm text-muted-foreground">
    Acme Notes startet{" "}
    <Countdown to="2026-12-01T17:00:00Z" variant="text" completedContent="heute" />
    </p>
    )
    }

    Screenreader hören nicht jeden Tick; die Komponente aktualisiert einmal pro Minute einen Satz und kündigt das Ende einmal an.

    Wähl mit den Buttons unter der Karte, wann der Launch ist: In 10 Sekunden tickt er herunter und zeigt die Meldung zum Ende, in 45 Tagen zeigt er Tage, und ein Datum in der Vergangenheit rendert sofort den fertigen Zustand
    $ npx wingo-ui@latest add countdown
    ProDoku: Countdown

    Was sollte ich ergänzen, bevor ich den Link zur Warteliste teile?

    Ergänz ein Rate Limit, eine E-Mail-Bestätigung und einen Weg, die Liste zu verlassen. Die Seite funktioniert an diesem Punkt, aber diese drei Dinge gehören auf den Server, bevor der Link rausgeht:

    • Rate Limit. Eine Server Action ist ein öffentlicher Endpoint. Begrenz sie pro IP, so wie jedes Anmeldeformular; Waitly nutzt dafür Upstash Redis.
    • E-Mail-Bestätigung. Schick einen Bestätigungslink und zähl eine Empfehlung erst, wenn die empfohlene Person bestätigt hat. Sonst klettert ein Skript mit falschen Adressen auf Platz 1. Ergänz eine Spalte confirmed_at und filtere die Zählung der Empfehlungen danach.
    • Abmelden und Löschen. Wenn dein FAQ verspricht, dass man die Liste jederzeit verlassen kann, bau diesen Weg vor dem Launch.

    Auf Smartphones erledigt die Vorlage die mobile Arbeit schon selbst: Behältst du das Rollen-Select, öffnet es sich unter 768px als Bottom Sheet mit seinem Label als Titel, und mit layout="split" rutscht das Smartphone-Mockup unter 1024px unter den Text. Kommt der Launch-Tag, kann die Vorlage Launch Page dieselbe URL mit ihrer Live-Phase übernehmen, und die Vorlage Referral Page deckt ein dauerhaftes Empfehlungsprogramm ab, wenn die Warteliste geschlossen ist.

    Weitere Screens, die so gebaut sind, findest du in der Kategorie Praxis: Screens und Apps, angefangen mit dem Tutorial zum Next.js Admin Dashboard (auf Englisch). Sobald die Leute drin sind, übernimmt der Guide zum React Onboarding Flow den ersten Start, und das Tutorial zur shadcn Pricing Page behandelt die Seite, die sie sehen, wenn die kostenlose Einladung endet.

    Wie geht es weiter?

    Installier die Vorlage mit npx wingo-ui@latest add waitlist-page, tausch die Beispieltexte und -daten gegen deine eigenen und verbinde die Server Action mit deiner Datenbank. Waitlist Page und Countdown gehören zu Wingo UI Pro, das $8 im Monat, $80 im Jahr oder einmalig $150 kostet, Stand Oktober 2026 (Preise); Copy Button, Accordion und Select, die die Vorlage nutzt, sind kostenlos.

    Komponenten in diesem Artikel

    • Waitlist Page

      React waitlist page template: a launch countdown, an email signup with social proof, your place in line with a referral link and FAQ.

      Pro
    • Countdown

      A React countdown timer to a launch, sale or deadline, shown as rolling digit blocks, inline in a sentence or in words, with done content.

      Pro

    Häufige Fragen

    Wie baue ich eine Waitlist Page in Next.js?

    Render die Seite aus einer Server Component, die die echte Anmeldezahl und den ?ref=-Code liest, gib beides an eine Client-Komponente mit dem Formular weiter und speichere jede E-Mail über eine Server Action, die Position und Empfehlungscode zurückgibt. Die Vorlage Waitlist Page von Wingo UI liefert den Screen, den Speicher bringst du mit.

    Wie berechnet eine Referral-Warteliste den Platz auf der Liste?

    Eine einfache Regel ist die Reihenfolge der Anmeldung minus ein Bonus pro Empfehlung: Jeder Freund, der sich über deinen Link einträgt, zieht eine feste Zahl an Plätzen von deinem Score ab, und deine Position ist eins plus die Zahl der Leute mit niedrigerem Score. Eine einzige Postgres-Abfrage mit row_number() und einer Zählung der Empfehlungen berechnet das.

    Sollte eine Waitlist Page zeigen, wie viele sich angemeldet haben?

    Nur wenn die Zahl echt ist. Lies sie aus deiner Datenbank und blende die Zeile aus, bis sie groß genug ist, um etwas zu bedeuten; die Vorlage Waitlist Page versteckt die Zahl und den Avatar-Stapel, wenn du count={0} übergibst.

    Ist die Waitlist-Vorlage von Wingo UI kostenlos?

    Nein. Die Vorlage Waitlist Page und der Countdown gehören zu Wingo UI Pro, während die Teile, auf denen sie aufbaut, etwa Copy Button, Accordion, Button und Select, kostenlos sind. Alles installierst du mit npx wingo-ui@latest add.

    Wie verhindere ich, dass jemand eine Referral-Warteliste austrickst?

    Mach die E-Mail-Spalte eindeutig, lass eine zweite Anmeldung nie ändern, wer jemanden empfohlen hat, setz ein Rate Limit auf die Action und zähl eine Empfehlung erst, wenn die neue Person ihre E-Mail bestätigt hat. Ein paar falsche Adressen kommen trotzdem durch, versprich die Einladungen also nicht streng nach Position.

    • Next.js
    • Warteliste
    • Landingpage
    • React
    • Tailwind CSS

    Teilen

    SR

    Über den Autor

    Serban Rusu

    Gründer von Wingo UI

    Serban Rusu hat Wingo UI gegründet. Er baut die Komponenten, die CLI und den MCP-Server und schreibt über React-UIs für Smartphones und KI-Agents.

    Mehr von Serban
    Weiterlesen

    Ähnliche Artikel

    Alle Artikel
    Komponenten-Guides

    React Countdown Timer: Blöcke, Inline, schlafende Tabs

    Bau einen React Countdown Timer als rollende Ziffernblöcke, im Fließtext oder in Worten, und behandle Zeitzonen, schlafende Tabs, Hydration und das Ende sauber.

    SRSerban Rusu·19. Okt. 2026·9 Min. Lesezeit
    Praxis: Screens und Apps

    Next.js Blog Template: Markdown, Live-Demos und JSON-LD

    So haben wir ein Next.js Blog Template auf Markdown gebaut: zod-Frontmatter, Live-Demos, Sticky-Inhaltsverzeichnis, JSON-LD, Feeds und ein strenger Validator.

    SRSerban Rusu·16. Okt. 2026·10 Min. Lesezeit
    Praxis: Screens und Apps

    Next.js SaaS Landing Page: Was jeder Abschnitt beweisen muss

    Bau eine Next.js SaaS Landing Page Abschnitt für Abschnitt: was Hero, Social Proof, Features, Preise und FAQ beweisen müssen, was rausfliegt, was mobil zählt.

    SRSerban Rusu·16. Okt. 2026·11 Min. Lesezeit
    Newsletter

    Neue Artikel per E-Mail

    Neue Guides, Tutorials und Vergleiche aus dem Wingo UI Blog, sobald sie erscheinen. Die meisten Artikel sind auf Englisch.

    Kein Spam. Du kannst dich jederzeit abmelden.

    WingoUI

    Animierte, konfigurierbare, mobile-first React-Komponenten und Blöcke. Kopier den Quellcode, pass ihn an und lass deinen Coding-Agenten damit bauen.

    Produkt

    • Komponenten
    • Vorlagen
    • Preise
    • KI-Agenten
    • Theme-Generator

    Ressourcen

    • Doku
    • Blog
    • Changelog
    • Changelog-RSS
    • llms.txt

    Rechtliches

    • AGB
    • Datenschutz
    • Rückerstattung
    • Lizenz
    • Impressum

    Komponenten-Kategorien

    • Buttons & Actions
    • Inputs
    • Forms
    • Navigation
    • Overlays
    • Feedback
    • Data Display
    • Tables & Lists
    • Charts & Stats
    • Layout
    • Media
    • AI Kit
    • Text & Effects
    • Mobile
    • Commerce
    • Marketing Sections
    • Blocks
    • Hooks & Utilities

    © 2026 Wingo UI

    Wingo UI