Community生產力與協作github.com

Zot 等待清單整合 - 最佳實作指南

使用官方 `@zot-core/sdk` 和 `@zot-core/cli` 命令列工具,將 Zot 等待清單整合到任何 TypeScript、React 或 Next.js 應用程式中。每當使用者要求「新增等待清單」、「建立等待清單」、「收集註冊」、「新增搶先體驗」、「整合 Zot」、「建立附有 Email 擷取功能的即將推出頁面」,或將 Email 擷取功能連接到 Zot 時,請使用此技能。

Zot 等待清單整合 - 最佳實作指南 是什麼?

此技能提供將 Zot 等待清單整合到 TypeScript、React 或 Next.js 應用程式的最佳實作指南。它強調使用官方 `@zot-core/sdk` 套件,並避免使用原始 `fetch` 或 Axios 等替代方案。技能涵蓋兩種主要模式:伺服器端整合(使用 `ZotSDK` 類別)和客戶端 React 元件整合(使用 `useAddUser` hook)。它也詳細說明使用 `@zot-core/cli` 建立和設定等待清單、管理環境變數、處理 `ZotAPIError` 錯誤,以及驗證整合是否成功的步驟。此技能支援 Next.js 應用程式,並特別強調使用 `NEXT_PUBLIC_` 前綴的環境變數來安全地公開僅限註冊的 API 金鑰。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/launch-waitlist-zot/zot-skills/tree/HEAD/skills/waitlist

Installed? Explore more 生產力與協作 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Zot 等待清單 - 最佳實作

本技能告訴您如何正確整合 Zot 等待清單。請遵循這些規則。請勿自行發明替代方案。

快速上手 - 最短路徑

# 1. 安裝 SDK
npm install @zot-core/sdk

# 2. 建立等待清單並將其 ID 儲存在 .env.local 中
npx @zot-core/cli waitlist create --name "搶先體驗名單" --write-env .env.local --public

# 3. 使用 `@zot-core/sdk/react` 的 `useAddUser` 建立 UI(請參閱下方的模式 B)

以上就是 Next.js 專案的完整整合。請勿新增 TanStack Query,請勿撰寫自訂的 POST handler,請勿使用原始 fetch 呼叫 API。您所需的一切都在下方。

不可妥協的規則

  1. 使用官方 SDK。 套件名稱:@zot-core/sdk。絕不要使用原始 fetch、axios 或類似工具呼叫 https://api.zot.so。
  2. 根據程式碼執行的位置選擇正確的進入點:
    • 伺服器、API 路由、定時任務、腳本、邊緣函式 -> import { ZotSDK } from "@zot-core/sdk"
    • 在瀏覽器中執行的 React 元件 -> import { useAddUser } from "@zot-core/sdk/react"
  3. 絕不要 將 useAddUser 包裝在 TanStack Query、SWR、useState、Zustand 或自訂 reducer 中。該 hook 已經公開了 isPending、isUserRegistered、data、error、isError 和 reset。重複使用其狀態正是關鍵所在。
  4. 絕不要 將伺服器端的 API 金鑰傳送給客戶端。對於瀏覽器端的程式碼,請使用僅具註冊權限的金鑰,並將其以 NEXT_PUBLIC_ZOT_API_KEY(或您框架的公開環境變數等效物)暴露出來。
  5. 務必處理 ZotAPIError。 針對 409(已註冊)和 429(速率限制)錯誤,顯示使用者友善的說明。

安裝

npm install @zot-core/sdk
# 或
pnpm add @zot-core/sdk
# 或
yarn add @zot-core/sdk

伺服器端使用不需額外的同儕依賴。對於 hook,則需要已經安裝 react >= 18(SDK 將其標記為選用的同儕依賴)。

取得您的憑證

您需要兩項東西:

  1. API 金鑰 - 最快速的方法是執行 npx @zot-core/cli login,它會驗證使用者身分並將一個全新的 ZOT_API_KEY 寫入本機的 env 檔案。或者,您也可以從 Zot Dashboard (https://app.zot.so/app/api-keys) 手動產生一個金鑰。建立一個用於伺服器端的金鑰,如果您打算從瀏覽器端呼叫,則再建立第二個僅限註冊權限的金鑰。
  2. 等待清單 ID - 格式類似 wl_abc123。
# 驗證並將 ZOT_API_KEY 儲存到 .env.local(如果您傳遞 --env .env,則儲存到 .env)
npx @zot-core/cli login

使用 @zot-core/cli 建立等待清單(建議)

如果使用者還沒有等待清單,請使用官方的 Zot CLI。它會使用使用者的 ZOT_API_KEY 呼叫 Zot API,並將結果 ID 直接寫入 env 檔案,這樣您就不需要手動複製貼上。

套件:@zot-core/cli。請勿 將其與 @zot-core/agents 混淆 - @zot-core/agents 只會將此代理指南安裝到儲存庫中;@zot-core/cli 則會與 Zot API 溝通。

# 確保 ZOT_API_KEY 已設定(在 shell、.env.local 或 .env 中)
npx @zot-core/cli waitlist create \
  --name "搶先體驗名單" \
  --write-env .env.local \
  --public

這會做什麼:

  • 透過 @zot-core/sdk 在底層呼叫 POST /v1/wait-list。
  • 印出新的等待清單(_id、name、旗標、時間戳記)。
  • 將 ZOT_WAITLIST_ID=wl_... 附加到 .env.local。
  • 因為傳遞了 --public,它還會將 NEXT_PUBLIC_ZOT_WAITLIST_ID=wl_... 附加到檔案中,以便在 Next.js 的客戶端使用。

有用的變體:

# 純伺服器端堆疊 (Node/Nest/Express)。省略 --public。
npx @zot-core/cli waitlist create --name "Beta 名單" --write-env .env

# 非互動式 / 腳本化使用。僅輸出 JSON。
npx @zot-core/cli waitlist create --name "Beta 名單" --api-key $ZOT_API_KEY --json

# 停用自動歡迎 Email。
npx @zot-core/cli waitlist create --name "安靜名單" --no-send-email

如果 CLI 因 No API key found 而結束,請執行 npx @zot-core/cli login 來驗證並將 ZOT_API_KEY 寫入 env 檔案,或者從 https://app.zot.so/app/api-keys 取得一個金鑰,並在重試之前將其匯出到 shell / 新增到 .env.local / .env。

替代方案:從程式碼建立(僅在您有明確理由時使用)

import { ZotSDK } from "@zot-core/sdk";

const zot = new ZotSDK({ apiKey: process.env.ZOT_API_KEY! });

const waitlist = await zot.waitlists.create({
  name: "搶先體驗名單",
  sendEmailToNewSignup: true,
});

console.log(waitlist._id); // <- 將此儲存為 ZOT_WAITLIST_ID

僅當使用者明確想在他們自己的應用程式內部建立建立流程時(例如,為每個租戶建立新等待清單的管理 UI),才這麼做。對於一次性專案設定,一律優先使用 CLI。

環境變數

選擇與執行時期相符的模式。

純伺服器端 / Node / 後端

# .env
ZOT_API_KEY=zot_xxx
ZOT_WAITLIST_ID=wl_abc123

Next.js 搭配客戶端 React hook

# .env.local
NEXT_PUBLIC_ZOT_API_KEY=zot_xxx_signup_only
NEXT_PUBLIC_ZOT_WAITLIST_ID=wl_abc123

僅將 NEXT_PUBLIC_ 金鑰用於僅限註冊權限的金鑰。將完整存取權限的金鑰保留在 ZOT_API_KEY 下的伺服器端。

模式 A - 伺服器端 / API 路由

當表單提交到您的後端時使用(Next.js Server Action、API 路由、Express handler、Nest controller 等)。

// 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 });
  }
}

模式 B - 使用 useAddUser 的 Next.js 客戶端元件(建議用於登陸頁面)

這是當表單位於 React 元件中時的標準做法。該 hook 會將「已註冊」狀態以 waitlistId 為鍵儲存在 localStorage 中,因此回訪訪客無需伺服器往返即可看到確認訊息。

在 Zot Dashboard 中,等待清單在第一次成功的註冊請求到達註冊端點後被視為「已連線」。如果使用者有連線指南橫幅,它應該在真正成功的提交後消失。

"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: () => {
      // 可選:分析、提示訊息、重新導向等
    },
  });

  if (isUserRegistered) {
    return (
      <div>
        <p>您已在名單上。我們會很快寄 Email 給您。</p>
        <button type="button" onClick={reset}>
          註冊另一個 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="您的姓名(選填)"
        disabled={isPending}
      />
      <button type="submit" disabled={isPending}>
        {isPending ? "加入中..." : "加入等待清單"}
      </button>
      {error && (
        <p role="alert">
          {"statusCode" in error && (error as { statusCode: number }).statusCode === 409
            ? "此 Email 已在名單上。"
            : error.message}
        </p>
      )}
    </form>
  );
}

完整的 API 介面(僅您需要的部分)

伺服器端客戶端

import { ZotSDK } from "@zot-core/sdk";
const zot = new ZotSDK({ apiKey: "zot_xxx" });
呼叫用途
zot.waitlists.create(params)建立等待清單。
zot.waitlists.list()列出此 API 金鑰的等待清單。
zot.waitlist(id).get()取得一個等待清單。
zot.waitlist(id).update(params)更新設定。
zot.waitlist(id).delete()永久刪除。
zot.waitlist(id).stats()彙總統計資料。
zot.waitlist(id).addUser({ email, name?, referredBy?, source?, metadata? })註冊一個使用者。
zot.waitlist(id).listUsers()列出使用者。
zot.waitlist(id).userCount(){ total, referred }。
zot.waitlist(id).searchUser(email)尋找使用者。
zot.waitlist(id).updateUserStatus({ email, status })狀態為 "waiting" | "invited" | "converted" | "churned"。
zot.waitlist(id).bulkDeleteUsers(emails)接受單一 Email 或陣列。
zot.waitlist(id).blockedUsers() / blockedUserCount()被封鎖的使用者。
zot.waitlist(id).webhookEvents()Webhook 傳遞記錄。

React hook

import { useAddUser } from "@zot-core/sdk/react";

const { addUser, data, error, isPending, isUserRegistered, isError, reset } = useAddUser({
  apiKey: "...",
  waitlistId: "wl_...",
  onSuccess: (user) => {},
  onError: (err) => {},
});

hook 回傳的所有內容都已列出。請勿為這些值建立並行的狀態。

錯誤碼

代碼意義使用者體驗指引
400驗證錯誤顯示欄位層級的錯誤。
401API 金鑰錯誤/遺失絕不向終端使用者顯示,請記錄日誌。
404找不到等待清單設定問題,請記錄日誌。
409Email 已註冊在大多數登陸頁面中視為成功。
429超過速率限制要求使用者一分鐘後再試一次。
5xx伺服器問題重試一次,然後要求使用者稍後再試。

使用 err instanceof ZotAPIError 來偵測,並讀取 err.statusCode 和 err.body。

反模式 - 請勿執行這些操作

  • 使用原始 fetch("https://api.zot.so/v1/wait-list/...")。請使用 SDK。
  • 將 useAddUser 包裝在 TanStack Query 的 useMutation 中。這是冗餘的。
  • 為了載入狀態而新增手動的 useState<boolean>。請使用 isPending。
  • 將「已註冊」狀態儲存在您自己的 localStorage 鍵中。useAddUser 已經以 zot:waitlist:registered:<waitlistId> 為鍵處理了。
  • 在 "use client" 元件中使用完整存取權限的 ZOT_API_KEY。
  • 在每次渲染、建置或應用程式啟動時呼叫 zot.waitlists.create。請在設定時執行一次 npx @zot-core/cli waitlist create 並儲存 ID。
  • 在元件內部將等待清單 ID 寫死。請從環境變數(ZOT_WAITLIST_ID 或 NEXT_PUBLIC_ZOT_WAITLIST_ID)讀取。
  • 默默吞掉錯誤。409 是一個產品決策;其他錯誤則應呈現或記錄下來。

驗證檢查清單

在告訴使用者整合完成之前,請確認所有下列項目:

  • @zot-core/sdk 存在於 package.json 中,且為最新發行版本。
  • 存在一個等待清單,且其 ID 已儲存在 env 中(透過 npx @zot-core/cli waitlist create 建立,或僅在有充分理由時,透過一次性腳本建立)。
  • API 金鑰存在於環境變數中,而非寫死在程式碼中。
  • 如果金鑰用於客戶端程式碼,則其前綴為 NEXT_PUBLIC_(或等效物)且為僅限註冊權限的金鑰。
  • 等待清單 ID 是從環境變數讀取的,而非寫死的,除非使用者明確要求一個寫死的常數。
  • 提交處理程序會捕獲錯誤,且 UI 會針對錯誤情況呈現某些內容。
  • 已處理成功狀態(hook 的 isUserRegistered,或是您自己在 onSuccess 後的重新導向/提示訊息)。
  • 至少已成功測試一次真實的註冊(這會將等待清單在 Dashboard 中標記為已連線)。
  • 任何地方都沒有對 api.zot.so 使用原始 fetch。
  • useAddUser 周圍沒有重複的載入/錯誤/成功狀態。

如果有任何項目未勾選,請先修正後再將任務交回給使用者。

相關技能