Skip to Content

配置

让每个文件只负责一种运行环境或一类配置,可以降低仓库维护成本。

文件职责表

文件负责不负责
.env.locallocal-app 的应用/本地密钥与运行时值Wrangler 专用本地变量、预览/生产租户身份
.dev.vars.devlocal-worker 的本地 Wrangler 变量app 环境默认值、预览/生产密钥
.env.cloudflare / .env.cloudflare.preview远端辅助程序、seed 与 Cloudflare API 凭据提交到仓库的部署身份
wrangler.toml受版本控制的模板安全基线与本地开发配置私有预览/生产租户 ID 和路由
wrangler.remote.toml私有预览/生产 Cloudflare 租户配置仅本地开发的默认值

从仓库中的 wrangler.remote.example.toml 创建 wrangler.remote.toml。

应用组合

src/config/product.ts 拥有可安全用于客户端的品牌信息与显式能力选择。SaaS 基础模板没有默认示例业务或组织模块。

capabilities: { docs: true, blog: true, ...productCompositions.core, // or productCompositions["personal-paid"] feedbackAttachments: false, analyticsClient: false, analyticsServer: false, devReview: false, }
组合新购买所需能力
core关闭认证与已初始化数据库;基本资料和后台管理
personal-paid真实结账核心能力,加受支持的 Stripe 配置及已发布的产品/报价版本

随附配置选择真实结账。供应商或目录配置缺失时仍不可用。live 允许现有 Stripe 流程使用测试或真实凭据,但不能证明支付或生产就绪。demo 不能用于真实购买,也不会授予访问权限。

新购买需要可信 APP_URL、受支持的 STRIPE_SECRET_KEY、PAYMENT_PROVIDER=stripe、同源返回路径与准确的已发布报价版本。配置 STRIPE_WEBHOOK_SECRET 以接收签名回执。结账为 off 时,/pricing 返回 404,新结账命令被拒绝;/me/billing 保留已有购买、原尝试恢复与受支持的账单管理。只要这些义务仍存在,就应保留供应商配置。

客户从 /me 查看基本资料和修改已有密码。注册与登录默认进入该账户页。模板不再公开 Bookmark、Decision Log、组织协作、工具仪表盘、客户收件箱、API 凭据、导出、用量或偏好中心。源码退场不会清除历史数据库记录。

选择能力不等于授权。按业务集成指南添加真实领域;其命令和查询必须执行当前身份与资源归属检查。Docs、Blog 和分析仍独立选择。

条款、隐私与支持链接

在 src/config/product.ts 的 brand.links 中设置可选目的地址:

links: { terms: null, privacy: null, support: null, repository: null, docsRepositoryBase: null, }

只有具备要发布的目的地址时才替换 null。使用 /policies/terms 这样的本地绝对路径,或 https://help.your-domain.com/support 这样的无凭据 HTTPS URL。允许本地查询参数和片段。相对路径、协议相对 URL、HTTP、可执行 scheme、内嵌凭据、错误转义、空白与控制字符,会在配置加载或构建时被拒绝。这些是公开源码值,绝不能放入访问令牌或私有 URL。修改后重新构建;无需新增环境变量。

已配置入口会一致出现在主站页脚、文档页脚及登录/注册信息链接中。未设置的入口保持隐藏,空页脚或导航也不显示。链接在当前标签页打开;外部链接不发送来源页面信息。模板不创建目的页面或探测其可用性。请发布并维护自己的文档与支持入口。

这些链接只提供信息,不增加接受复选框、不记录同意、不改变认证,也不证明政策在法律上充分或已被用户接受。

可选内容模块

在 src/config/product.ts 设置 capabilities.docs 与 capabilities.blog,然后重新构建并启动应用。两者默认均为 true。

选择应用行为
关闭 Docs隐藏导航,/docs 及下级文档路由返回未找到
关闭 Blog隐藏导航与编辑路由;公开列表/详情返回未找到,编辑 Actions 返回不可用,不注册 Blog 刷新任务
启用 Blog,未配置 CMS随附 MDX 与已配置的数据库发布内容可用;不加载外部 CMS 来源
启用 Blog,CMS 输入不全系统诊断指出缺失输入名,该来源报告不可用,其他内容仍可使用

Notion 需要 NOTION_TOKEN 与 NOTION_DATABASE_ID;Sanity 需要 SANITY_PROJECT_ID 与 SANITY_DATASET,可选 SANITY_READ_TOKEN。Blog 关闭时忽略残留 CMS 凭据。配置允许初始化,不能证明连通性。编辑操作始终检查当前管理员权限。停用模块会保留已存内容与构建依赖。

带类型的环境变量层

应用运行时值由 @t3-oss/env-nextjs 验证。标准类型入口是 src/env.ts,它组合 src/env/* 下的领域 schema。

新增变量通常按以下流程:

  1. 在 src/env/ 下正确的 schema 文件中添加变量。
  2. 通过 src/env.ts 重新导出。
  3. 确定默认应由哪个配置文件保存值。
  4. 更新对应示例文件。

只有需要直接访问进程环境的地方(如 CLI 脚本或运行时桥接)才直接使用 process.env。

local-app 示例

APP_URL="http://localhost:3101" AUTH_SECRET="replace-me-with-a-local-secret" DATABASE_URL="file:./dev.db" XADMIN_SECRET="replace-me-for-local-seeding"

这是标准 Next.js + Playwright 开发环境。

local-worker 示例

将 .dev.vars.example 复制为 .dev.vars.dev,本地 Wrangler 地址保持使用端口 8787:

APP_URL="http://localhost:8787" AUTH_SECRET="replace-me-with-a-local-worker-secret" XADMIN_SECRET="replace-me-for-local-worker-seeding" CRON_SECRET="replace-me-for-local-worker-cron" TRIGGER_SECRET="replace-me-for-local-worker-triggers"

即使同时在本地使用 Wrangler,.env.local 仍只用于 app 环境。

远端辅助配置示例

生产辅助流程使用 .env.cloudflare,预览辅助流程使用 .env.cloudflare.preview:

CLOUDFLARE_API_TOKEN="replace-me-with-api-token" CLOUDFLARE_D1_TOKEN="replace-me-with-d1-or-api-token" APP_URL="https://your-app.example.com" XADMIN_SECRET="replace-me-with-remote-admin-secret"

这些文件存放辅助凭据与远端脚本输入,不应存放预览或生产的账户 ID、路由或绑定 ID。

Cloudflare 配置文件

  • wrangler.toml
    • 受版本控制
    • 模板安全基线
    • 本地开发默认值
  • wrangler.remote.toml
    • 不纳入版本控制
    • 私有预览与生产租户身份
    • 从 wrangler.remote.example.toml 创建

不要将真实预览或生产租户 ID 直接写入受版本控制的 wrangler.toml。

端口与地址

  • local-app:http://localhost:3101
  • local-worker:http://localhost:8787
  • remote-cloudflare:私有远端配置中指定的域名或路由

明确区分各环境地址,不要让三个环境复用同一个 APP_URL。

常用可选环境变量组

账户与商业能力

从 /me 与选定的管理员路由开始。基本资料和密码流程不需要商业报价。Auth 拥有账户身份;Payments 拥有已发布产品、不可变报价版本、已确认支付事实与个人账单。目录标签或返回 URL 不会授予业务访问权限。

付费业务操作必须通过明确的领域权益策略与真实调用方接入。基础模板没有默认 Bookmark 或 Decision 规则。已有购买身份与账单恢复独立于新销售,仍然有效。

OAuth 供应商

AUTH_GITHUB_ID="your-github-client-id" AUTH_GITHUB_SECRET="your-github-client-secret" AUTH_GOOGLE_ID="your-google-client-id" AUTH_GOOGLE_SECRET="your-google-client-secret" AUTH_DISCORD_ID="your-discord-client-id" AUTH_DISCORD_SECRET="your-discord-client-secret"

支付

PAYMENT_PROVIDER="mock" STRIPE_SECRET_KEY="sk_test_..." STRIPE_WEBHOOK_SECRET="whsec_..." NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_..."

邮件

SMTP_HOST="smtp.example.com" SMTP_PORT="587" SMTP_USER="smtp-user" SMTP_PASS="smtp-pass" SMTP_FROM="Product <no-reply@example.com>"

分析

浏览器分析默认关闭。构建时设置 NEXT_PUBLIC_ANALYTICS_ENABLED="true" 与供应商 key,无需修改源码。显式 false 同时关闭 GA4 与 PostHog。未设置或为空时,沿用 src/config/product.ts 的 capabilities.analyticsClient(模板默认为 false)。

Google Analytics 4 配置:

NEXT_PUBLIC_ANALYTICS_ENABLED="true" NEXT_PUBLIC_GOOGLE_ANALYTICS_ID="G-XXXXXXXXXX"

创建 GA4 网站数据流,使用其衡量 ID,而不是 GTM 或 Universal Analytics ID。关闭该数据流的增强型衡量:应用在首次加载与每次 pathname 变化时发送一次页面浏览。页面 URL 与来源信息不带 query/hash,标题使用 pathname。修改任一公开值后,重新构建并部署;本地开发则重启。仅运行时 Worker secret 无法改变已构建的浏览器包。部署后在 GA 实时报告中验证接收。

PostHog 可选且独立,可替代 GA4 或与其同时配置:

NEXT_PUBLIC_POSTHOG_KEY="phc_..." NEXT_PUBLIC_POSTHOG_HOST="https://app.posthog.com"

服务端认证事件使用现有 PostHog 选择 capabilities.analyticsServer=true,以及以下仅服务端输入:

POSTHOG_API_KEY="phc_..." POSTHOG_HOST="https://app.posthog.com"

浏览器页面浏览只包含 origin 与路径,排除查询参数、片段、来源页面及自动营销归因;会话回放和自动采集已禁用。缺少 key 或 host 无效时,所选能力保持不可用。修改配置后重启本地应用;公开配置改变时重新构建部署。

Google 登录与 Search Console

数据库和部署初始化后,可与上述分析配置一并设置:

APP_URL="https://www.your-company.com" AUTH_SECRET="your-stable-random-secret" AUTH_TRUST_HOST="1" AUTH_GOOGLE_ID="your-client-id.apps.googleusercontent.com" AUTH_GOOGLE_SECRET="your-client-secret" GOOGLE_SITE_VERIFICATION="your-meta-content-token"

本地应用使用 .env.local。生产环境将公开值提供给 Next 构建,将服务端凭据提供给运行时;生产构建校验也需要 AUTH_SECRET。构建与运行时的 APP_URL、GOOGLE_SITE_VERIFICATION 应保持一致,修改后重新构建,保持编译配置与运行时一致。Docs 按请求解析语言。保留已有认证密钥;新部署可用 openssl rand -base64 32 生成。只对自己控制的部署入口启用 Trust Host。安装与部署步骤初始化 SQLite 或 D1 DB 及 Worker KV;Google 配置不会创建这些资源。

  • **Google 登录:**在 Google Auth Platform 创建 OAuth Web 应用。注册准确的重定向 URI https://your-domain/api/auth/callback/google;本地使用准确主机与端口,如 http://localhost:3101/api/auth/callback/google。按该 Google 项目要求配置受众与测试用户。两项凭据会启用已有登录和注册按钮,不需改动 UI 或认证源码。供应商账户关联规则仍然适用。
  • Search Console:创建匹配 APP_URL 的 URL 前缀资源,选择 HTML 标签验证,只填写标签的 content 值。部署并完成验证后,提交 https://your-domain/sitemap.xml。网域资源需要 DNS TXT 验证,不能用此 meta 标签替代。保留所用验证方式。

GA4、Google OAuth 与 Search Console 使用不同标识符。部署后,用自己的 Google 账户检查登录,检查响应 HTML 中的验证 meta 标签与 /sitemap.xml;本地测试不能证明 Google 已接受配置或完成索引。

应避免的配置方式

  • 常规本地开发不要用通用 .env 流程替代 .env.local。
  • 不要将本地 Wrangler 变量放入 .env.local。
  • 不要将远端租户身份存入受版本控制的 wrangler.toml。
  • 不要将 .env.cloudflare* 当作部署身份文件。

数据库说明

修改 schema 后,生成并审阅 SQL,再将完整迁移链应用到受保护的 local-app 数据库:

npm run db:generate npm run db:push

远端 D1 使用显式迁移发布流程。这里的 db:push 是 local-app 命令,不发布远端结构。

下一步

完成配置后,可继续阅读:

公开发现与规范地址

将 APP_URL 设为站点 HTTPS origin,例如 https://www.your-company.com,不要包含凭据、路径、查询参数或片段。生产发现拒绝 loopback 与保留的 example/test/invalid 主机。本地开发接受显式配置的 loopback HTTP origin,如 http://127.0.0.1:3101;请求 Host 与转发头永远不决定规范地址。构建与运行时保持 APP_URL 一致,修改后重新构建:发现过程使用可信配置值,Docs 按请求解析语言。

/sitemap.xml 在构建时自动发现公开 App Router 页面文件,包括定价页及选中的 Docs/Blog 页面。新增普通页面后部署即可,无需维护 URL 列表。动态 /blog/[slug] 地址在请求时从当前公开文章展开。其他动态领域每个领域需要一个公开数据 reader,而非每个 URL 一条记录;未解析占位符不会输出。新增私有区域必须加入 src/config/sitemap-policy.ts 的集中排除项。/robots.txt 声明 sitemap,并建议爬虫不要抓取账户、运营与已停用内容路由。Robots 仅提供建议,私有页面仍由认证和授权保护。在 src/config/product.ts 关闭 Blog 或 Docs 后,发现过程不初始化该模块的 reader 或供应商。

生产快照使用已有 SQLite 缓存或 Worker KV,最长一小时。每次请求检查当前 Blog 发布版本,因此发布或撤回文章会立即改变缓存键。过期条目在下次请求时重新生成,无需额外 cron 或 sitemap 环境设置。源码 MDX 变化仍需构建。Google 自行决定何时抓取与索引这些 URL。

APP_URL 缺失或不安全时,保留页面文字 metadata,省略规范/分享 URL,并请求不索引。Robots 禁止抓取且不提供 sitemap 地址;sitemap 请求返回错误。格式错误的 URL 可能在应用提供服务前就使环境校验失败。向爬虫开放前应修复配置。已配置内容来源失败时,sitemap 也失败,不发布不完整列表;有意为空的来源仍有效。

当前单个 sitemap 最多支持 10,000 个不同 URL,每个最长 2,048 字符。若转义后的 UTF-8 大小加保守 XML 标记余量超过 50 MiB,也会被拒绝。超过限制时明确失败。它复用已有完整 Blog 列表与来源限制,包括 Notion 单页限制,不增加搜索服务或分页框架。不输出虚构修改时间。手工恢复或导入旧发布代次后,清除 public-sitemap 缓存,或使用新 build ID 重建。

数据库文章的保存草稿保留已发布标题、地址、描述和分享图片。发布已保存草稿选择新值;撤回、归档、删除或发布非公开受众都会使文章退出公开发现。Meta Description 回退到摘要或标题;Cover Image URL 提供可选分享图片。外部 CMS 卡片保留外部目的地址,不作为本地文章页发布。

语言与隐私就绪情况

应用共用一套路由和组件,提供英文与简体中文界面消息。Blog 与 Docs 使用明确的 /en/...、/zh-CN/... 内容地址,独立维护完整版本。随附的全部八篇 Docs 与三篇 Blog 均有完整英中版本。没有已发布译文的内容提供英文阅读链接。

NEXT_PUBLIC_ANALYTICS_ENABLED 只选择可选集成,不授权采集。先在 src/privacy/config.ts 中填写真实的双语发布主体、联系方式、处理、保留与翻译审阅字段;设备必须显式保存同意选择后,符合条件的分析服务才会加载。没有符合条件的可选服务时不显示横幅。阅读 /privacy 与 /cookies,使用页脚隐私设置查看或撤回选择。缺少所需当前主体、用途与权限时,服务端分析不发送事件。不要编造运营方资料来制造模板已就绪的假象。