使用官方 @bachs/sdk 处理托管结账、产品设置、客户门户和 Webhook 验证
bachs-nextjs-saas — Next.js SaaS模板
作者 bachsdev
基于 Next.js App Router 与 Bachs SDK 的本地开发订阅模板,演示托管结账、Webhook 验证、访问控制与客户账单门户。
看看你的网站会是什么样
浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。
全部页面与视图 2
截图用于了解视觉与布局,交互效果请以实际项目为准。
值得关注的模板亮点
从已有项目资料中,快速了解它的特点。
结账 API 在服务端映射套餐并保存持久化操作键,忽略客户端价格和产品 ID
Webhook 路由使用 SDK 验证原始请求体和事件信封,lib/webhooks.ts 跳过重复和较旧事件
lib/store.ts 以序列化、原子替换方式将状态与已处理事件 ID 一起提交到本地文件
提供 npm run verify 运行单元/路由测试、TypeScript 检查、生产构建和 HTTP 冒烟测试
包含 AGENTS.md、CLAUDE.md 和可独立使用的 Bachs skill 文件,便于 AI 辅助开发
模板详细介绍
这是一个用于演示 Bachs 月度与年度订阅流程的 Next.js App Router 起步模板,使用官方 @bachs/sdk 处理结账、产品设置、客户门户和 Webhook 验证。README 明确说明它是本地开发起步模板:所有访客共享一个演示用户,账单数据保存在本地 JSON 文件,部署前需要替换认证与存储;演示认证会拒绝实时 API 密钥。模板包含结账 API、Webhook 处理、访问控制、客户门户会话创建和成功页面等模块,并提供了单元测试、类型检查、生产构建和 HTTP 冒烟测试的验证脚本。README 还记录了 2026 年 10 月 9 日一次手动沙箱检查通过,但后续计费周期续费尚未验证。
适合你的项目吗?
适用场景
- 在本地沙箱中体验 Bachs 订阅结账、Webhook 激活访问和客户账单门户的完整流程
- 作为学习 Next.js App Router 与 Bachs SDK 集成方式的参考项目
- 通过替换认证、存储和套餐配置,作为构建自有 SaaS 订阅功能的起点
- 利用内置测试和验证脚本检查订阅生命周期中的签名、续费恢复、取消和并发事件处理
适合人群
- 需要了解 Bachs 订阅集成方式的开发者
- 希望以本地开发模板为起点搭建 Next.js SaaS 订阅功能的团队
- 需要参考 Webhook 验证、访问控制和幂等结账处理实现的人员
上手与定制指南
结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。
- 1
需要 Node.js 22 或更高版本、沙箱 API 密钥和 Bachs CLI;密钥需具备 products:write、payments:write 和 customers:write 权限
- 2
运行 npm ci 后复制 .env.example 为 .env,设置 BACHS_API_KEY,再运行 npm run setup:products 并将打印的两个产品 ID 填入 .env
- 3
在第二个终端运行 npm run listen,将打印的 whsec_ 密钥复制到 BACHS_WEBHOOK_SECRET,然后运行 npm run dev
- 4
Bachs 拒绝 localhost 和私有 IP 的结账重定向 URL,本地开发默认不设置重定向;如需自动返回需使用公网部署或隧道并设置 CHECKOUT_SUCCESS_URL 和 CHECKOUT_CANCEL_URL
- 5
每次新的 listen 会话会生成新的签名密钥,需更新 .env 并重启应用;不要将密钥粘贴到聊天或提交 .env
授权与来源资料
使用条件与限制
免费使用 · 保留许可声明本次收录的是公开仓库中采用 MIT 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。
使用时需要遵守
- 允许免费使用、修改、商用和分发该版本代码。
- 分发代码副本或实质性部分时,保留原作者版权声明和完整 MIT 许可声明。
- 代码按现状提供;担保与责任限制以原许可证及适用法律为准。
额外费用与待核对事项
- 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
- 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
- 这是本地开发起步模板:所有访客共享一个演示用户,账单数据保存在一个本地 JSON 文件中。
- 部署前必须替换认证与存储实现。
- 演示认证会拒绝实时 API 密钥,因此不能直接用于生产。
- 当前 npm 上的 0.0.1 包只是占位符,SDK 实现打包在 vendor/ 中。
- 需要 Node.js 22 或更高版本、沙箱 API 密钥以及 Bachs CLI。
- API 密钥需要 products:write、payments:write 和 customers:write 权限。
- Bachs 即使在沙箱中也拒绝 localhost 和私有 IP 的结账重定向 URL。
- 每次新的 listen 会话都会生成新的签名密钥,重启监听器后需更新 .env 并重启应用。
- 不要将密钥粘贴到聊天中,也不要提交 .env 文件。
- 调查丢失的结账响应时需停止应用后再编辑本地 .data/store.json 文件。
- 冒烟测试使用虚拟密钥和固定 API 响应,不进行真实的 Bachs 支付。
- 后续计费周期续费尚未验证,生命周期测试使用固定事件,不能证明真实二次扣款。
- lib/store.ts 的本地序列化仅适用于单个 Node.js 进程,无法协调多实例或无服务器存储。
- 该起步模板的测试仅针对共享的演示身份,需自行添加会话、授权和部署测试。
- 上线需创建生产产品、设置 BACHS_ENVIRONMENT=production、使用生产 API URL 和实时密钥。
查看原文依据
Permission is hereby granted, free of charge
许可证原文
**This is a local development starter.** Every visitor shares one demo user,
README 原文
and billing data lives in one local JSON file. Replace authentication and the
README 原文
store before deploying. Demo authentication refuses live API keys.
README 原文
vendor/ so npm ci works before its npm release. The current npm 0.0.1
README 原文
You need Node.js 22 or later, a [sandbox API key](https://docs.bachs.io/authentication),
README 原文
The key needs `products:write`, `payments:write`, and `customers:write`.
README 原文
Bachs refuses localhost and private-IP checkout redirect URLs, even in sandbox.
README 原文
Each new `listen` session has a new signing secret. Update `.env` and restart
README 原文
the app when you restart the listener. Do not paste keys into chats or commit
README 原文
`checkouts` in `.data/store.json`. Stop the app before editing that local file.
README 原文
The smoke test uses dummy keys and fixture API responses. It makes no real
README 原文
A subsequent billing-cycle renewal remains unverified. Lifecycle tests above
README 原文
- Replace `lib/store.ts` with a transactional database. Its local serialization
README 原文
- Add your app's session, authorization and deployment tests. This starter's
README 原文
https://github.com/bachsdev/bachs-nextjs-saas/blob/main/LICENSEhttps://github.com/bachsdev/bachs-nextjs-saas/blob/main/README.mdCreate products in production, set BACHS_ENVIRONMENT=production, use the production API URL and live key, and
README 原文
DeepSeek 根据仓库许可证和 README 整理 ·2026-10-09。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。
项目核对记录与介绍依据
模板资料
- 来源平台
- GitHub
- 资料与维护参考分
- 资料较完整 · 85 / 100
- 技术栈
- Next.js · React
- 网站类型
- SaaS · 启动器
这个分数如何计算
本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。
这个项目需要核对什么
- 记录的仓库更新时间
- 2026-10-09
- 截图检查日期
- 2026-10-16
已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。
目录记录的主要技术栈是 Next.js。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。
查看具体选型方法 →介绍的制作与核对状态
介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。
审核声明: codex-user-requested-batch-review-20261017 · 2026-10-16
查看当时使用的来源资料
SHA-256: c8c48b0d73b53905c513962052f1efc5fb5ce6f3fac7a5cc142a839e69815208
2026-10-09T19:52:15.773Z
来源文件 / 仓库# Bachs Next.js SaaS starter A Next.js App Router starter for monthly and yearly [Bachs](https://bachs.io) subscriptions using the official [Bachs SDK](https://github.com/bachsdev/bachs-node): hosted checkout, access from verified webhooks, and customer billing through the Bachs customer portal. Follow the [SaaS subscriptions walkthrough](https://docs.bachs.io/build/use-cases/saas-subscriptions) for the payment flow and the [Build with AI subscription workflow](https://docs.bachs.io/build/ai#sell-subscriptions) for a prompt that adapts it to your app. **This is a local development starter.** Every visitor shares one demo user, and billing data lives in one local JSON file. Replace authentication and the store before deploying. Demo authentication refuses live API keys. ## SDK dependency This starter imports @bachs/sdk for checkout, product setup, the customer portal and webhook verification. The tested SDK implementation is packaged in vendor/ so npm ci works before its npm release. The current npm 0.0.1 package is a placeholder. See [package provenance and the npm transition](vendor/README.md). ## Run in sandbox You need Node.js 22 or later, a [sandbox API key](https://docs.bachs.io/authentication), and the [Bachs CLI](https://docs.bachs.io/cli/overview#install). The key needs `products:write`, `payments:write`, and `customers:write`. ```bash npm ci cp .env.example .env # Set BACHS_API_KEY in .env, then: npm run setup:products ``` On Windows PowerShell, use `Copy-Item .env.example .env` instead of `cp`. Copy the two product IDs printed by the setup script into `.env`. You can also create the recurring products in the Bachs dashboard and save their IDs there. In a second terminal: ```bash npm run listen ``` Copy the `whsec_` secret it prints into `BACHS_WEBHOOK_SECRET` in `.env`, then start the app: ```bash npm run dev ``` Open http://localhost:3000, click **Subscribe**, and complete the sandbox checkout using its test controls. Subscription webhooks activate access. Return to http://localhost:3000 after paying to see access activate. Click **Manage billing** to open the portal. Bachs refuses localhost and private-IP checkout redirect URLs, even in sandbox. The starter leaves checkout redirects unset for local development. If you want an automatic return, use a public deployment or tunnel and set `CHECKOUT_SUCCESS_URL` and `CHECKOUT_CANCEL_URL` in `.env`. `APP_URL` remains the app's own URL; the CLI forwards webhooks without a public webhook URL. Each new `listen` session has a new signing secret. Update `.env` and restart the app when you restart the listener. Do not paste keys into chats or commit `.env`. ## How it works | File | Responsibility | | --- | --- | | `app/api/checkout/route.ts` | Maps the plan on the server, reserves a persistent operation key, and creates checkout. Client prices and product IDs are ignored. | | `app/api/webhooks/bachs/route.ts` | Uses SDK webhooks.constructEvent to verify the raw body and event envelope, then processes the event. | | `lib/webhooks.ts` | Saves subscription state; skips duplicates and older events. | | `lib/store.ts` | Commits state and processed-event IDs together in a serialized, atomic local file replacement. | | `lib/access.ts` | Decides access. The default gives a grace period while a renewal is past due. | | `app/api/billing/portal/route.ts` | Creates a fresh session for the demo user's saved Bachs customer. | | `app/billing/success/page.tsx` | Reads stored access and waits for the webhook; never grants access. | | `lib/bachs.ts` | Maps app inputs to the official SDK; the SDK handles transport, typed responses and uncertain errors. | ### When a checkout response is lost The starter saves a checkout attempt before calling Bachs. A repeated click reuses a confirmed, unexpired checkout. A timeout, 5xx, or failure to save the response leaves the attempt awaiting confirmation and blocks another POST. Check the checkout or subscription in Bachs and allow its webhook to arrive. Keep the stored operation key while investigating. Only after confirming the original checkout had no effect should you clear that user's entry in `checkouts` in `.data/store.json`. Stop the app before editing that local file. In a production implementation, replace this manual step with an authenticated reconciliation process following the [idempotency guide](https://docs.bachs.io/guides/idempotency). Do not delete the store or generate a replacement key just because a response was lost. ## Verification ```bash npm run verify ``` This runs: 1. Unit and route tests for signatures, secret rotation, checkout and portal ownership, access, renewal recovery, cancellation, duplicate and concurrent events, failed persistence, and uncertain checkout recovery. 2. TypeScript checks. 3. A production build. 4. HTTP smoke checks against the built Next.js server and a local Bachs API fixture, with isolated billing data. The smoke test uses dummy keys and fixture API responses. It makes no real Bachs payment. Run the sandbox checkout above to verify a real integration. CI runs the same gates on Node.js 22 and 24 without secrets. A manual SDK-backed sandbox check on October 9, 2026 also passed: hosted checkout and the first payment, a real signed subscription event forwarded through the CLI after replay, stored access activation, and the signed-in demo customer's billing portal. The user submitted the simulated card payment. A subsequent billing-cycle renewal remains unverified. Lifecycle tests above use fixture events; they are not evidence of a real second charge. To run an individual gate: ```bash npm test npm run typecheck npm run build npm run test:smoke # requires npm run build first ``` ## Make it yours - Replace `lib/auth.ts` with authenticated users and protect billing routes. - Replace `lib/store.ts` with a transactional database. Its local serialization applies to one Node.js process; it cannot coordinate multiple instances or serverless storage. Preserve atomic event completion and stale-event checks. - Set your plans in `lib/plans.ts` and create matching Bachs products. Prices displayed in the app should match those products. - Choose the access policy in `lib/access.ts`. - Configure the [customer portal](https://docs.bachs.io/guides/customer-portal/overview#configuring-the-portal) for card updates and plan switching if needed. - Add your app's session, authorization and deployment tests. This starter's tests exercise a shared demo identity. ## Go live After replacing the demo components, follow the [go-live checklist](https://docs.bachs.io/build/use-cases/saas-subscriptions#go-live-checklist). Create products in production, set BACHS_ENVIRONMENT=production, use the production API URL and live key, and register the five subscription/invoice events in `npm run listen` on your production webhook endpoint. Its signing secret differs from the local one. Production subscriptions are not shared with sandbox. ## Building with an AI assistant `AGENTS.md` explains the project and checks; `CLAUDE.md` points to it. [Build with AI](https://docs.bachs.io/build/ai) has three complete workflows and an optional Bachs skill. The shared [Bachs skill](skills/bachs/SKILL.md) covers payments, subscriptions and marketplaces. You can use it in any app, independently of this starter. For Claude Code, copy skills/bachs/SKILL.md into your app at .claude/skills/bachs/SKILL.md, then use /bachs followed by what you want to build. For another tool that supports Agent Skills, install the same file using its instructions. Prefer no installation? Copy one of the three prompts from Build with AI; each includes the rules it needs. ## License MIT. See [LICENSE](LICENSE).
看看同类模板
对比同技术栈与用途的模板,找到更适合的视觉与内容结构。

ai-website-cloner-template
Clone any website with one command using AI coding agents
Next.js · 启动器

Next.js SaaS Starter
Next.js SaaS Starter 是 Next.js 官方维护的 SaaS 起点模板,定位介于学习资源和可直接部署的脚手架之间。
Next.js · SaaS

Next.js Commerce
Next.js Commerce 是 Vercel 团队维护的电商启动模板,基于 Next.js App Router 构建,采用服务端渲染、React Server Components、Server Actions …
Next.js · 电商

Next-js-Boilerplate
Next-js-Boilerplate 是一个面向 Next.js 16、Tailwind CSS 4 和 TypeScript 的启动器,核心定位是开发者体验优先。
Next.js · 启动器

tailwind-nextjs-starter-blog
tailwind-nextjs-starter-blog 是一个面向个人技术博客的 Next.js 与 Tailwind CSS 启动模板,其 v2 版本基于 App Router 与 React Server Comp…
Next.js · 博客

next-forge
Production-grade Turborepo template for Next.js apps.
Next.js · 启动器
