Zot Waitlist - Bonnes Pratiques
Ce skill explique comment intégrer correctement une liste d'attente Zot. Suivez ces règles. N'inventez pas d'alternatives.
TL;DR - le chemin le plus court
# 1. Installer le SDK
npm install @zot-core/sdk
# 2. Créer la liste d'attente et persister son ID dans .env.local
npx @zot-core/cli waitlist create --name "Early Access" --write-env .env.local --public
# 3. Construire l'interface utilisateur (voir Patron B ci-dessous) avec `useAddUser` depuis "@zot-core/sdk/react"
Ceci est l'intégration complète pour un projet Next.js. N'ajoutez pas TanStack Query, n'écrivez pas de gestionnaire POST personnalisé, n'appelez pas l'API avec fetch brut. Tout ce dont vous avez besoin se trouve ci-dessous.
Règles non-négociables
- Utilisez le SDK officiel. Nom du package :
@zot-core/sdk. N'appelez jamaishttps://api.zot.soavecfetch,axiosou équivalent brut. - Choisissez le bon point d'entrée selon l'endroit où le code s'exécute :
- Serveur, route API, cron, script, fonction edge ->
import { ZotSDK } from "@zot-core/sdk" - Composant React s'exécutant dans le navigateur ->
import { useAddUser } from "@zot-core/sdk/react"
- Serveur, route API, cron, script, fonction edge ->
- N'enveloppez jamais
useAddUserdans TanStack Query, SWR,useState, Zustand ou un reducer personnalisé. Le hook expose déjàisPending,isUserRegistered,data,error,isErroretreset. Réutiliser son état est tout l'intérêt. - N'expédiez jamais une clé API serveur au client. Pour le code navigateur, utilisez une clé avec les permissions d'inscription uniquement et exposez-la sous
NEXT_PUBLIC_ZOT_API_KEY(ou l'équivalent public-env de votre framework). - Gérez toujours
ZotAPIError. Affichez un message explicite pour les codes 409 (déjà inscrit) et 429 (limite de débit).
Installer
npm install @zot-core/sdk
# ou
pnpm add @zot-core/sdk
# ou
yarn add @zot-core/sdk
Aucune dépendance supplémentaire n'est requise pour une utilisation serveur. Pour le hook, react >= 18 doit déjà être installé (le SDK le marque comme dépendance optionnelle).
Obtenir vos identifiants
Vous avez besoin de deux choses :
- Clé API - le chemin le plus rapide est
npx @zot-core/cli login, qui authentifie l'utilisateur et écrit une nouvelleZOT_API_KEYdans le fichier d'environnement local. Sinon, générez-en une manuellement depuis le tableau de bord Zot à https://app.zot.so/app/api-keys. Créez une clé pour le serveur et, si vous prévoyez d'appeler depuis le navigateur, une seconde clé limitée aux inscriptions. - ID de la liste d'attente - ressemble à
wl_abc123.
# S'authentifier et persister ZOT_API_KEY dans .env.local (ou .env si vous passez --env .env)
npx @zot-core/cli login
Créer la liste d'attente avec @zot-core/cli (recommandé)
Si l'utilisateur n'a pas déjà de liste d'attente, utilisez le CLI officiel de Zot. Il appelle l'API Zot avec la ZOT_API_KEY de l'utilisateur et écrit l'ID résultant directement dans le fichier d'environnement pour éviter tout copier-coller.
Package :
@zot-core/cli. Ne le confondez pas avec@zot-core/agents-@zot-core/agentsinstalle uniquement ce guide d'agent dans un dépôt ;@zot-core/clicommunique avec l'API Zot.
# Assurez-vous que ZOT_API_KEY est définie (dans le terminal, dans .env.local ou dans .env)
npx @zot-core/cli waitlist create \
--name "Early Access" \
--write-env .env.local \
--public
Ce que cela fait :
- Appelle
POST /v1/wait-listvia@zot-core/sdken coulisse. - Affiche la nouvelle liste d'attente (
_id,name, flags, timestamps). - Ajoute
ZOT_WAITLIST_ID=wl_...à.env.local. - Parce que
--publica été passé, il ajoute égalementNEXT_PUBLIC_ZOT_WAITLIST_ID=wl_...pour une utilisation côté client dans Next.js.
Variantes utiles :
# Stack purement serveur (Node/Nest/Express). Supprimez --public.
npx @zot-core/cli waitlist create --name "Beta list" --write-env .env
# Utilisation non interactive / scriptée. Affiche uniquement du JSON.
npx @zot-core/cli waitlist create --name "Beta list" --api-key $ZOT_API_KEY --json
# Désactiver l'email de bienvenue automatique.
npx @zot-core/cli waitlist create --name "Quiet list" --no-send-email
Si le CLI se termine avec No API key found, exécutez npx @zot-core/cli login pour vous authentifier et écrire ZOT_API_KEY dans le fichier d'environnement, ou récupérez-en une depuis https://app.zot.so/app/api-keys et exportez-la dans le terminal / ajoutez-la à .env.local / .env avant de réessayer.
Alternative : créer la liste depuis le code (uniquement si vous avez une raison claire)
import { ZotSDK } from "@zot-core/sdk";
const zot = new ZotSDK({ apiKey: process.env.ZOT_API_KEY! });
const waitlist = await zot.waitlists.create({
name: "Early Access",
sendEmailToNewSignup: true,
});
console.log(waitlist._id); // <- enregistrez cet ID comme ZOT_WAITLIST_ID
Faites ceci uniquement si l'utilisateur souhaite explicitement un flux de création dans sa propre application (par exemple, une interface d'administration qui crée de nouvelles listes d'attente par locataire). Pour une configuration de projet ponctuelle, préférez toujours le CLI.
Variables d'environnement
Choisissez le motif correspondant à l'environnement d'exécution.
Serveur pur / Node / backend
# .env
ZOT_API_KEY=zot_xxx
ZOT_WAITLIST_ID=wl_abc123
Next.js avec le hook React côté client
# .env.local
NEXT_PUBLIC_ZOT_API_KEY=zot_xxx_inscriptions_uniquement
NEXT_PUBLIC_ZOT_WAITLIST_ID=wl_abc123
Utilisez la clé NEXT_PUBLIC_ uniquement pour la clé limitée aux inscriptions. Gardez la clé avec accès complet côté serveur sous ZOT_API_KEY.
Patron A - Serveur / Route API
Utilisez ceci lorsque le formulaire est soumis à votre backend (Server Action Next.js, route API, gestionnaire Express, contrôleur Nest, etc.).
// app/api/waitlist/route.ts (Next.js App Router)
import { NextResponse } from "next/server";
import { ZotSDK, ZotAPIError } from "@zot-core/sdk";
const zot = new ZotSDK({ apiKey: process.env.ZOT_API_KEY! });
export async function POST(request: Request) {
const { email, name } = await request.json();
try {
const user = await zot.waitlist(process.env.ZOT_WAITLIST_ID!).addUser({
email,
name,
});
return NextResponse.json({ ok: true, user });
} catch (err) {
if (err instanceof ZotAPIError) {
if (err.statusCode === 409) {
return NextResponse.json(
{ ok: false, reason: "already_registered" },
{ status: 409 },
);
}
return NextResponse.json(
{ ok: false, reason: "zot_error", details: err.body },
{ status: err.statusCode },
);
}
return NextResponse.json({ ok: false }, { status: 500 });
}
}
Patron B - Composant client Next.js avec useAddUser (recommandé pour les pages d'atterrissage)
C'est la manière canonique lorsque le formulaire se trouve dans un composant React. Le hook persiste l'état "déjà inscrit" dans localStorage avec la clé waitlistId, de sorte que les visiteurs réguliers voient la confirmation sans aller-retour vers le serveur.
Dans le tableau de bord Zot, une liste d'attente est considérée comme "connectée" après que la première inscription réussie atteint le point de terminaison d'enregistrement. Si l'utilisateur a une bannière de guide de connexion, elle devrait disparaître après une soumission réussie réelle.
"use client";
import { useState } from "react";
import { useAddUser } from "@zot-core/sdk/react";
export function WaitlistForm() {
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const { addUser, isPending, isUserRegistered, error, reset } = useAddUser({
apiKey: process.env.NEXT_PUBLIC_ZOT_API_KEY!,
waitlistId: process.env.NEXT_PUBLIC_ZOT_WAITLIST_ID!,
onSuccess: () => {
// Optionnel : analytics, toast, redirection, etc.
},
});
if (isUserRegistered) {
return (
<div>
<p>Vous êtes sur la liste. Nous vous enverrons un email bientôt.</p>
<button type="button" onClick={reset}>
Enregistrer un autre email
</button>
</div>
);
}
return (
<form
onSubmit={(event) => {
event.preventDefault();
addUser({ email, name: name || undefined });
}}
>
<input
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
placeholder="[email protected]"
required
disabled={isPending}
/>
<input
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Votre nom (optionnel)"
disabled={isPending}
/>
<button type="submit" disabled={isPending}>
{isPending ? "Inscription..." : "Rejoindre la liste d'attente"}
</button>
{error && (
<p role="alert">
{"statusCode" in error && (error as { statusCode: number }).statusCode === 409
? "Cet email est déjà sur la liste."
: error.message}
</p>
)}
</form>
);
}
Surface API complète (uniquement ce dont vous avez besoin)
Client côté serveur
import { ZotSDK } from "@zot-core/sdk";
const zot = new ZotSDK({ apiKey: "zot_xxx" });
| Appel | Objectif |
|---|---|
zot.waitlists.create(params) | Créer une liste d'attente. |
zot.waitlists.list() | Lister les listes d'attente pour la clé API. |
zot.waitlist(id).get() | Récupérer une liste d'attente. |
zot.waitlist(id).update(params) | Mettre à jour les paramètres. |
zot.waitlist(id).delete() | Supprimer définitivement. |
zot.waitlist(id).stats() | Statistiques agrégées. |
zot.waitlist(id).addUser({ email, name?, referredBy?, source?, metadata? }) | Enregistrer un utilisateur. |
zot.waitlist(id).listUsers() | Lister les utilisateurs. |
zot.waitlist(id).userCount() | { total, referred }. |
zot.waitlist(id).searchUser(email) | Rechercher un utilisateur. |
zot.waitlist(id).updateUserStatus({ email, status }) | Le statut est `"waiting" |
zot.waitlist(id).bulkDeleteUsers(emails) | Accepte un email unique ou un tableau. |
zot.waitlist(id).blockedUsers() / blockedUserCount() | Utilisateurs bloqués. |
zot.waitlist(id).webhookEvents() | Historique de livraison des webhooks. |
Hook React
import { useAddUser } from "@zot-core/sdk/react";
const { addUser, data, error, isPending, isUserRegistered, isError, reset } = useAddUser({
apiKey: "...",
waitlistId: "wl_...",
onSuccess: (user) => {},
onError: (err) => {},
});
Tout ce que le hook retourne est listé ci-dessus. Ne créez pas d'état parallèle pour ces valeurs.
Codes d'erreur
| Code | Signification | Conseil UX |
|---|---|---|
| 400 | Erreur de validation | Affichez une erreur au niveau du champ. |
| 401 | Clé API mauvaise/manquante | Jamais affiché aux utilisateurs finaux, enregistrez-la dans les logs. |
| 404 | Liste d'attente introuvable | Problème de configuration, enregistrez-la dans les logs. |
| 409 | Email déjà enregistré | Traitez comme un succès dans la plupart des pages d'atterrissage. |
| 429 | Limite de débit atteinte | Demandez à l'utilisateur de réessayer dans une minute. |
| 5xx | Problème serveur | Réessayez une fois, puis demandez à l'utilisateur de réessayer plus tard. |
Détectez avec err instanceof ZotAPIError et lisez err.statusCode et err.body.
Anti-patrons - ne faites PAS ceci
- Appel
fetchbrut vershttps://api.zot.so/v1/wait-list/.... Utilisez le SDK. - Envelopper
useAddUserdansuseMutationde TanStack Query. Redondant. - Ajouter un
useState<boolean>manuel pour le chargement. UtilisezisPending. - Stocker "déjà enregistré" dans votre propre clé
localStorage.useAddUserle fait déjà souszot:waitlist:registered:<waitlistId>. - Utiliser la clé
ZOT_API_KEYavec accès complet dans un composant"use client". - Appeler
zot.waitlists.createà chaque rendu, build ou démarrage d'application. Utiliseznpx @zot-core/cli waitlist createune fois lors de la configuration et stockez l'ID. - Coder en dur l'ID de la liste d'attente dans le composant. Lisez-le depuis l'environnement (
ZOT_WAITLIST_IDouNEXT_PUBLIC_ZOT_WAITLIST_ID). - Avaler silencieusement les erreurs. Le code 409 est une décision produit ; les autres doivent être affichées ou enregistrées.
Liste de vérification
Avant de dire à l'utilisateur que l'intégration est terminée, confirmez TOUS les points suivants :
-
@zot-core/sdkest présent danspackage.jsonà la dernière version publiée. - Une liste d'attente existe et son ID est stocké dans l'environnement (créé via
npx @zot-core/cli waitlist createou, uniquement si justifié, via un script unique). - La clé API est dans les variables d'environnement, pas codée en dur.
- Si la clé est utilisée dans du code client, elle est préfixée par
NEXT_PUBLIC_(ou équivalent) ET est une clé limitée aux inscriptions. - L'ID de la liste d'attente est lu depuis l'environnement, pas codé en dur, sauf si l'utilisateur a explicitement demandé une constante codée en dur.
- Le gestionnaire de soumission attrape les erreurs et l'interface utilisateur affiche quelque chose en cas d'erreur.
- L'état de succès est géré (soit
isUserRegistereddu hook, soit votre propre redirection/toast aprèsonSuccess). - Au moins une inscription réelle a été testée avec succès (c'est ce qui marque la liste d'attente comme connectée dans le tableau de bord).
- Aucun appel
fetchbrut versapi.zot.sonulle part. - Aucun état de chargement/erreur/succès dupliqué autour de
useAddUser.
Si une case n'est pas cochée, corrigez-la avant de remettre la tâche à l'utilisateur.