{
  "id": "build-a-saas-pricing-page",
  "type": "prompts",
  "category": "prompts",
  "locale": "zh",
  "url": "/zh/prompts/build-a-saas-pricing-page",
  "title": "使用 Next.js 构建 SaaS 定价页面的提示",
  "description": "复制粘贴 AI 提示，使用 Next.js 与 Tailwind 构建 SaaS 定价页面，包含账单切换和 Stripe 就绪的计划数据。",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Next.js",
    "TypeScript",
    "Tailwind"
  ],
  "tags": [
    "nextjs",
    "tailwind",
    "typescript",
    "build"
  ],
  "difficulty": "easy",
  "updated": "2026-06-08",
  "markdown": "使用此提示生成一份精美且优化转化的定价页面，包含月度/年度账单切换、高亮的“最受欢迎”层级，以及直接连接 Stripe Checkout 的类型化计划配置——无占位数据。\n\n## 主要提示\n\n```txt title=\"Main Prompt\"\nYou are working in a Next.js App Router project using TypeScript and Tailwind CSS v4.\n\nTask: create a `/pricing` page with the following specification.\n\nPlan data:\n- Starter: $0/mo, $0/yr — 1 user, 5 projects, community support.\n- Pro: $19/mo, $190/yr — 5 users, unlimited projects, email support. Mark as \"Most Popular\".\n- Enterprise: $99/mo, $990/yr — unlimited users, SSO, dedicated support.\n\nUI requirements:\n- A client component `<PricingToggle>` with monthly/annual switch; annual shows \"Save 17%\".\n- A `<PricingCard>` component per plan with: name, price, feature list, CTA button.\n- \"Most Popular\" card has a highlighted border and badge.\n- CTA buttons call `handleCheckout(planId, interval)` — stub it for now, we will wire Stripe later.\n- The page file itself must be a Server Component; only the toggle and cards are Client Components.\n- Use Tailwind utility classes only — no CSS modules, no inline styles.\n\nType requirements:\n- Export a `Plan` interface from `src/lib/pricing.ts`.\n- Plan data lives in that same file as a `const PLANS: Plan[]`.\n\nDo NOT install any new packages. Stop and list all files before writing code.\n```\n\n## 实现说明\n\n- 页面必须是服务器组件以便静态渲染；仅将 `'use client'` 提升到需要 `useState` 的切换和卡片组件上。\n- `handleCheckout` 应接受 `(planId: string, interval: 'monthly' | 'annual')` —— 此签名与 Stripe Checkout 提示匹配，请保持稳定。\n- Tailwind v4 使用 CSS 优先配置；除非已存在，否则避免使用 `tailwind.config.ts`。\n\n## 预期文件更改\n\n```txt\nsrc/app/pricing/page.tsx            (new — Server Component)\nsrc/components/PricingToggle.tsx    (new — Client Component)\nsrc/components/PricingCard.tsx      (new — Client Component)\nsrc/lib/pricing.ts                  (new — Plan type + PLANS constant)\n```\n\n## 验收标准\n\n- `bun run build` 退出码为 0，无 TypeScript 错误。\n- 切换月度/年度会更新所有三个卡片的价格，无需完整页面重新加载。\n- “最受欢迎”徽标在 Pro 卡片上可见。\n- 当点击 CTA 时，`handleCheckout` 被调用并传入正确的 `planId` 和 `interval`。\n\n## 测试命令\n\n```bash\nbun run typecheck\nbun run build\nbun run dev\n# open http://localhost:3000/pricing and verify toggle behavior\n```\n\n## 常见 AI 错误\n\n- 将页面文件本身标记为 `'use client'`，这会破坏服务器渲染。\n- 在 JSX 中硬编码价格，而非从 `PLANS` 派生。\n- 使用不适用于 Tailwind v4 的 `tailwind.config.ts` `theme.extend` 模式。\n- 忘记导出 `Plan` 类型，后续会破坏 Stripe Checkout 集成。\n\n## 修复提示\n\n```txt title=\"Fix Prompt\"\nThe pricing page has type errors or the toggle doesn't work. Fix in this order:\n1. Remove `'use client'` from `src/app/pricing/page.tsx` — only the child components need it.\n2. Make sure `PricingToggle` uses `useState` for the billing interval and passes it down via props.\n3. Confirm `handleCheckout` signature is `(planId: string, interval: 'monthly' | 'annual') => void`.\nShow the corrected diff only — do not rewrite unrelated files.\n```"
}