多租户隔离在数据访问层实现,每个查询通过 TenantScopedRepository 自动注入租户过滤条件
saas-genai-starter — Next.js SaaS模板
作者 delmalih
面向多租户 GenAI 产品的开源 SaaS 启动器,基于 Next.js 与 FastAPI,内置 BYO-key 模型接入、带引用的 RAG、用量计费与评估工具。
看看你的网站会是什么样
浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。
全部页面与视图 2
截图用于了解视觉与布局,交互效果请以实际项目为准。
值得关注的模板亮点
从已有项目资料中,快速了解它的特点。
支持 BYO-key 模式,可为每个组织配置 Anthropic、OpenAI、Gemini、Mistral、xAI、DeepSeek、Groq 或 OpenRouter 等聊天提供商
RAG 管道包含异步文档解析、分块、嵌入和 pgvector HNSW 检索,回答附带页面级引用
每次 LLM 调用记录 token、成本、延迟和状态,支持按功能与模型查看每日花费
内置评估工具,使用真实管道和 LLM 评判对忠实度与引用正确性打分
提供 Terraform 部署配置,可在多个服务的免费额度内运行,并包含 CI/CD 流程
模板详细介绍
这是一个面向多租户 GenAI 产品的开源 SaaS 启动器,仓库采用 MIT 许可,代码可免费使用、修改和分发。项目由 Next.js 前端与 FastAPI 后端组成,配合 PostgreSQL + pgvector、Redis 和 Terraform 部署脚本,提供从认证、租户隔离到 RAG 对话与用量追踪的完整基础结构。
在能力层面,它实现了数据层强制的多租户隔离、基于 Better Auth 的认证与团队邀请、支持 8 家聊天提供商和 5 家嵌入提供商的 BYO-key 密钥管理(Fernet 加密、只写接口)、按组织统计的 LLM 调用成本、带页面级引用的异步 RAG 管道、OpenTelemetry 可观测性以及基于 LLM 评判的评估工具。计费模块通过 Stripe 实现但默认关闭,需要显式启用。
使用限制方面,仓库代码本身免费,但演示图片、字体、图标等第三方素材需单独核对许可;域名、托管、数据库、支付和 AI 服务可能产生费用。README 中提到的 $0/月部署依赖各服务的免费额度,并非代码自带保证。项目状态为 v1 已上线,但评估基线等数据来自特定模型与配置,不构成通用性能承诺。
适合你的项目吗?
适用场景
- 需要快速搭建多租户 GenAI SaaS 产品原型的团队
- 希望让每个客户自带模型 API 密钥并独立计费的产品
- 构建基于文档的问答或知识库对话应用
- 需要评估 RAG 回答质量与引用准确性的开发流程
- 在免费额度内验证 GenAI 产品全栈架构的个人或小团队
适合人群
- 熟悉 Next.js 与 FastAPI 的全栈开发者
- 需要多租户与用量追踪的 GenAI 产品团队
- 希望以 MIT 许可代码为基础进行二次开发的开发者
- 关注 RAG 引用与评估工具链的技术团队
上手与定制指南
结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。
- 1
需要 Node 22 及以上、pnpm、uv 以及 Docker 运行环境
- 2
执行 make setup、make migrate、make dev 启动本地开发环境,另开终端运行 make worker 处理文档摄取
- 3
在 Settings → AI Provider 中粘贴自己的提供商密钥,或在 apps/api/.env 中设置服务端全局密钥作为回退
- 4
RAG 功能需要额外的嵌入模型密钥,例如 Voyage AI 或 OpenAI/Gemini/Mistral 的密钥
- 5
计费功能默认关闭,启用前需配置 Stripe 相关环境变量
授权与来源资料
使用条件与限制
免费使用 · 保留许可声明本次收录的是公开仓库中采用 MIT 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。
使用时需要遵守
- 允许免费使用、修改、商用和分发该版本代码。
- 分发代码副本或实质性部分时,保留原作者版权声明和完整 MIT 许可声明。
- 代码按现状提供;担保与责任限制以原许可证及适用法律为准。
额外费用与待核对事项
- 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
- 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
- 使用 RAG 功能需要额外的嵌入模型密钥:搭配 Anthropic 时需 Voyage AI 密钥(有免费额度),或使用 OpenAI/Gemini/Mistral 密钥同时覆盖聊天与嵌入。
- 必须自行提供并配置 AI 提供商 API 密钥:可在设置中按组织粘贴,或在 apps/api/.env 中设置服务端全局密钥作为回退。
- 计费功能默认关闭,需通过 BILLING_ENABLED 标志显式启用;启用后需使用 Stripe 订阅服务并配置 Stripe 账户。
- $0/月部署依赖各外部服务的免费额度(Cloud Run、Neon、Upstash、GCS、Vercel 等),超出免费额度可能产生费用,并非代码自带保证。
- 运行需要 Node 22 及以上、pnpm、uv 以及 Docker 运行环境。
查看原文依据
Permission is hereby granted, free of charge
许可证原文
For RAG you also need an embeddings key: **Voyage AI** (free tier) with Anthropic, or your OpenAI/Gemini/Mistral key covers both.
README 原文
paste your provider key in *Settings → AI Provider* (per-organization, encrypted at rest), or - set server-wide keys in `apps/api/.env` (`ANTHROPIC_API_KEY`, `VOYAGE_API_KEY`, …) as the fallback for every org.
README 原文
**Billing, opt-in** — Stripe subscriptions (Checkout + customer portal + signature-verified webhooks) behind a `BILLING_ENABLED` flag, with plan-based rate limits (free/pro) and upgrade prompts when quotas are hit. Off by default: no Stripe code runs and no Stripe account is needed.
README 原文
The [Terraform in `infra/`](infra/terraform) deploys the whole stack inside free tiers, with CI/CD included:
README 原文
https://github.com/delmalih/saas-genai-starter/blob/main/LICENSEhttps://github.com/delmalih/saas-genai-starter/blob/main/README.md**Prerequisites**: Node ≥ 22, pnpm (`corepack enable pnpm`), [uv](https://docs.astral.sh/uv/), and a Docker runtime (Docker Desktop or `brew install colima docker-compose && colima start`).
README 原文
DeepSeek 根据仓库许可证和 README 整理 ·2026-10-05。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。
项目核对记录与介绍依据
模板资料
- 来源平台
- GitHub
- 资料与维护参考分
- 资料较完整 · 88 / 100
- 技术栈
- Next.js · React
- 网站类型
- SaaS · 启动器
这个分数如何计算
本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。
这个项目需要核对什么
- 记录的仓库更新时间
- 2026-06-25
- 截图检查日期
- 2026-10-05
已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。
目录记录的主要技术栈是 Next.js。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。
查看具体选型方法 →介绍的制作与核对状态
介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。
审核声明: [email protected] · 2026-10-05
查看当时使用的来源资料
SHA-256: 8a7a639f77a5044f18e0de2d839e954ad49a8524d2acb9197c84e9ed0716faf5
2026-10-05T03:25:28.434Z
来源文件 / 仓库# saas-genai-starter
[](https://github.com/delmalih/saas-genai-starter/actions/workflows/ci.yml)
[](LICENSE)
[](https://saas-genai-starter-web.vercel.app)
**A production-grade, open-source starter for multi-tenant GenAI SaaS** — the
parts demo-grade starters ignore: multi-tenancy enforced at the data layer,
LLM cost tracking per organization, provider resilience, bring-your-own-key
support for 8 chat providers, observability, async ingestion, an eval harness
that caught real bugs before launch, and a $0/month deployment.
Built with **Next.js 15 · FastAPI · PostgreSQL + pgvector · Terraform**.
## ✨ Try it now
**[saas-genai-starter-web.vercel.app](https://saas-genai-starter-web.vercel.app)**
— sign up, paste your own API key (Anthropic, OpenAI, Gemini, Mistral, xAI,
DeepSeek, Groq or OpenRouter) in *Settings → AI Provider*, upload a PDF and
chat with it. Streamed answers, page-level citations, live cost tracking.
The demo runs the exact code in this repo on infrastructure that costs its
maintainer **0€/month** (details [below](#the-0month-deployment)). Your keys
are Fernet-encrypted at rest and write-only through the API.
## What's inside
- **Multi-tenancy you can't bypass** — every query goes through a
tenant-scoped repository that injects the filter at construction;
forgetting it is structurally impossible. Cross-tenant isolation has
dedicated tests.
- **Auth done right** — [Better Auth](https://better-auth.com) in Next.js
(email/password + Google/GitHub SSO, env-gated), FastAPI validates its
JWTs via JWKS. Roles (owner/admin/member), team invitations with
single-use hashed tokens.
- **Bring-your-own-key, multi-provider** — each organization picks its
provider (Anthropic, OpenAI, Google Gemini, Mistral, xAI, DeepSeek, Groq
or OpenRouter for chat; Voyage, OpenAI, Gemini, Mistral or Cohere for
embeddings), its model, and pastes its own API keys — encrypted at rest
(Fernet), write-only through the API, never logged. Server-wide env keys
remain as the self-host fallback, and OpenAI-compatible providers are a
[catalog entry away](docs/extending-llm-providers.md).
- **LLM costs under control** — every call (chat, RAG, ingestion,
extraction) writes a usage row: tokens (including cache reads), cost in
USD from a versioned pricing table, latency, status. Usage survives
client disconnects and mid-stream failures. A dashboard shows daily
spend per feature and model.
- **Resilience as a layer, not an afterthought** — provider-agnostic
retries with jitter, `retry-after` honored, circuit breaker with
half-open probes (429s don't trip it — throttling isn't an outage).
- **RAG pipeline** — async ingestion (parse → chunk with page numbers →
embed → pgvector HNSW), agentic chat with a search tool, citations
persisted with messages, per-tenant rate limiting (Redis, fail-open),
structured-output metadata extraction.
- **Observability** — OpenTelemetry traces (FastAPI/SQLAlchemy/httpx +
`llm.call` spans carrying model, tokens and cost), structured logs with
request and tenant ids.
- **Evals from day one** — `make evals` runs the real pipeline against a
fixture corpus and scores it with an LLM judge. Current baseline:
**0.96 overall** (faithfulness 0.99, citations 0.93) on
`claude-sonnet-4-6`. The first run scored 0.57 and exposed two real
bugs — see [Why these choices](#why-these-choices).
- **Billing, opt-in** — Stripe subscriptions (Checkout + customer portal +
signature-verified webhooks) behind a `BILLING_ENABLED` flag, with
plan-based rate limits (free/pro) and upgrade prompts when quotas are
hit. Off by default: no Stripe code runs and no Stripe account is
needed.
- **Agent-bootstrappable** — point Claude Code (or any coding agent) at
[`BOOTSTRAP.md`](BOOTSTRAP.md) with five parameters and it turns the
starter into *your* named, branded product with green tests
(`make bootstrap` for humans).
## Architecture
```mermaid
flowchart LR
subgraph web["apps/web — Next.js 15 (Vercel)"]
UI[App UI] --> BA[Better Auth<br/>sessions + EdDSA JWT]
end
subgraph api["apps/api — FastAPI (Cloud Run, scale-to-zero)"]
MW[JWT via JWKS<br/>+ X-Org-Id tenant scope] --> DOM[Domains<br/>chat · documents · usage<br/>billing · admin]
DOM --> LLM[LLM layer<br/>catalog · resilience · pricing]
DOM --> RL[Rate limiter<br/>per-tenant, plan-aware]
JOBS["/internal/jobs<br/>parse → chunk → embed"]
end
UI -->|"typed client (OpenAPI)"| MW
BA -.->|JWKS| MW
LLM --> CHAT["Chat: Anthropic · OpenAI · Gemini<br/>Mistral · xAI · DeepSeek · Groq · OpenRouter"]
LLM --> EMB["Embeddings: Voyage · OpenAI<br/>Gemini · Mistral · Cohere"]
DOM --> PG[("Postgres + pgvector<br/>(Neon)")]
JOBS --> PG
RL --> RD[("Redis<br/>(Upstash)")]
DOM --> GCS[("Blob storage<br/>local disk / GCS")]
DOM -->|enqueue| CT["Cloud Tasks (prod)<br/>ARQ on Redis (local)"]
CT -->|"OIDC-signed push"| JOBS
```
Background jobs need no always-on worker in production: the API enqueues a
Cloud Tasks task, which pushes an OIDC-signed HTTP request back to the same
scale-to-zero service. Locally the same job code runs on an ARQ worker —
the queue is an interface, the swap is configuration.
## The $0/month deployment
The [Terraform in `infra/`](infra/terraform) deploys the whole stack inside
free tiers, with CI/CD included:
| Piece | Service | Why it's free |
|---|---|---|
| API | Cloud Run | scale-to-zero, CPU billed only while serving |
| Jobs | Cloud Tasks | push queue — no idle worker to pay for |
| Database | Neon Postgres | serverless free tier, pgvector included |
| Rate limiting | Upstash Redis | free tier, per-request pricing model |
| Documents | GCS | always-free tier (US regions) |
| Web | Vercel Hobby | static + serverless |
| LLM usage | — | every org brings its own keys |
| CD | GitHub Actions | keyless deploys via Workload Identity Federation |
`git push` on `main` builds the image, runs Alembic against Neon (connection
string fetched from Secret Manager, masked in logs), deploys the new
revision and smoke-checks `/health` — no JSON service-account keys anywhere.
## Quickstart
**Prerequisites**: Node ≥ 22, pnpm (`corepack enable pnpm`),
[uv](https://docs.astral.sh/uv/), and a Docker runtime (Docker Desktop or
`brew install colima docker-compose && colima start`).
```bash
git clone https://github.com/delmalih/saas-genai-starter && cd saas-genai-starter
make setup # deps + .env files
make migrate # database schema
make dev # postgres+redis (docker), API on :8000, web on :3000
make worker # in a second terminal — document ingestion
```
Sign up on http://localhost:3000, then either:
- paste your provider key in *Settings → AI Provider* (per-organization,
encrypted at rest), or
- set server-wide keys in `apps/api/.env` (`ANTHROPIC_API_KEY`,
`VOYAGE_API_KEY`, …) as the fallback for every org.
For RAG you also need an embeddings key: **Voyage AI** (free tier) with
Anthropic, or your OpenAI/Gemini/Mistral key covers both.
**Making it yours**: [`BOOTSTRAP.md`](BOOTSTRAP.md) — written for coding
agents — renames, rebrands and re-domains the starter from five parameters.
## Evals
```bash
make evals # full run, ~7 min (paced for Voyage free tier)
make evals ARGS="--min-score 0.8"
```
The harness ingests a fixture corpus with **real embeddings** into a
dedicated database, runs the **real agent loop**, and grades every answer
with an LLM judge on faithfulness and citation correctness — including
negative cases where the right answer is "that's not in the documents".
Per-commit results land in [`evals/results/`](evals/results/).
| Metric | Baseline (claude-sonnet-4-6) |
|---|---|
| Overall | **0.963** |
| Faithfulness | 0.993 |
| Citation correctness | 0.933 |
## Why these choices
The decisions that make this starter production-grade rather than demo-grade
— several were validated the hard way:
- **Tenant isolation lives in the repository layer, not in code review.**
`TenantScopedRepository` takes the tenant at construction and injects the
filter into every query; `add()` overwrites forged tenant ids. You can't
forget a `WHERE tenant_id = ...` because you never write one.
- **`lazy="raise"` on every relationship.** Async SQLAlchemy turns implicit
lazy loads into `MissingGreenlet` errors that depend on garbage-collection
timing. A flaky test traced back to exactly that — now any unloaded
relationship access fails loudly and deterministically, and eager loading
is explicit.
- **The eval harness paid for itself on day one.** First run: 0.57. It
exposed that tool results sent the model a 400-char UI snippet instead of
full chunk content (the agent cited the right document while claiming the
information wasn't there), and that the agent answered general-knowledge
questions from memory without searching. Both fixed; baseline 0.96. No
unit test could have caught either.
- **Usage rows survive failure.** Provider costs are incurred even when the
client disconnects mid-stream — so usage records are written and committed
on the error path, with output estimated from streamed characters.
- **429 ≠ outage.** Rate limiting is backpressure with its own pacing
(`retry-after`); only real failures (5xx, timeouts) feed the circuit
breaker.
- **BYO keys are write-only.** Org API keys are Fernet-encrypted at rest and
the API only ever returns `is_set` + the last 4 characters. A database
leak does not leak provider keys.
- **One normalized message format, many providers.** Domain code speaks one
block vocabulary; each provider translates to its own dialect. The agent
loop runs unchanged on Claude, GPT, Gemini, Mistral, Grok and friends —
and a parameterized test enforces the new-provider checklist (pricing
entry, key column, settings field) straight from the catalog.
- **Queues and storage behind interfaces.** ARQ/local-disk for dev,
Cloud Tasks/GCS adapters for prod — swapping is configuration, not
refactoring.
## Project structure
```
apps/
├── web/ # Next.js 15 — Better Auth, typed OpenAPI client, chat UI
└── api/ # FastAPI — src/core (auth, tenancy, telemetry),
# src/llm (catalog, providers, resilience, pricing),
# src/domains (chat, documents, usage, billing, admin, ...)
evals/ # eval harness, fixture corpus, per-commit results
infra/terraform/ # the $0-tier deployment (modules + demo environment)
BOOTSTRAP.md # agent-driven "make it yours" guide + scripts/bootstrap.py
```
More docs: [extending the LLM layer](docs/extending-llm-providers.md) ·
[auth flow](docs/auth-flow.md) · [deployment](docs/deploy.md) ·
[backlog & decisions](tech-steps.md)
## Status
**v1 is live** — [demo](https://saas-genai-starter-web.vercel.app) deployed
from this repo, CI green, eval baseline 0.96. The full build history is
ticket-by-ticket in [`tech-steps.md`](tech-steps.md), including the
decisions and the post-launch roadmap.
## License
[MIT](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 · 启动器
