Community编程与开发github.com

redoy49/nextjs-production-stack

当用户要求构建、搭建、扩展、审查或调试 Next.js 应用程序(App Router)时使用此技能。覆盖完整的生产栈——TypeScript、服务器组件/动作、Tailwind + shadcn/ui、React Hook Form + Zod、PostgreSQL + Drizzle、Better Auth、缓存/渲染策略、SEO、无障碍、测试、监控、代码质量和 DevOps。在提及“Next.js 应用”、“新项目”、“添加功能/页面/路由”、“设置认证”、“添加表单”、“数据库 schema”、“部署到 Vercel”或任何涉及 app/ 下文件的请求时触发,以及在为 Next.js 代码库编写代码时(即使没有显式调用)。

nextjs-production-stack 是什么?

redoy49/nextjs-production-stack 是一个为 AI 代理(如 Claude Code、Cursor、Codex)设计的技能,用于指导构建和维护生产级 Next.js 应用程序(App Router)。它提供了一套有主见的默认配置,涵盖从项目搭建到部署的整个开发周期,包括 TypeScript、Tailwind CSS、shadcn/ui、React Hook Form + Zod、PostgreSQL + Drizzle ORM、Better Auth 等精选工具。该技能强调遵循最佳实践,如严格类型检查、服务器组件优先、高效数据获取、缓存策略、SEO、无障碍、错误处理、测试和监控。它适用于新项目搭建、现有项目扩展以及代码审查场景。在用户已有不同配置时,技能会灵活匹配现有模式,而不是强制替换;引入或更换工具前会要求用户确认,提供选项并说明权衡,确保遵循用户偏好。

兼容平台✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/redoy49/agent-skills/tree/main/skills/web/nextjs-production-stack

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Next.js 生产栈

构建和维护 Next.js 应用程序的有主见默认配置。在搭建新项目或扩展现有项目时,请遵循以下约定,除非用户的现有代码库明显采用不同做法——当存在冲突时,匹配现有模式而非本文档,并简要说明偏差。

0. 栈概览

层推荐(首选,非强制)如果要求更改时可提供的选项
框架Next.js (App Router)、TypeScript、服务器组件 + 服务器动作不需要,这是核心
包管理器pnpmnpm、yarn、bun
UITailwind CSS、shadcn/ui、react-icons、Motion (motion.dev)Radix UI 或 Mantine、lucide-react、CSS Modules
表单React Hook Form + ZodTanStack Form、Valibot(替代 Zod)
数据库PostgreSQL + Drizzle ORMPrisma、Kysely;小型应用可用 MySQL 或 SQLite
认证Better Auth、RBACAuth.js、Clerk、Supabase Auth
媒体CloudinaryUploadThing、S3 + CDN、Vercel Blob
测试Vitest(单元/集成)、Playwright(端到端)Jest、Cypress
监控Sentry、结构化日志Datadog、Highlight、Axiom + pino
代码检查/格式化ESLint、Prettier、TypeScript strictBiome
CI/CDGitHub + GitHub Actions、Vercel、预览部署GitLab CI、Netlify、Cloudflare Pages

切勿静默地将表中的包替换为替代方案(例如用 Prisma 代替 Drizzle,用 next-auth 代替 Better Auth)。如果用户的项目已使用不同选择,请继续使用并标记不一致之处,而不是混合两种解决方案。

这些工具是推荐使用的:用户偏好它们,但并非强制。

  • 当后续章节提到特定工具(pnpm、Drizzle、Better Auth、Cloudinary、Sentry 等)时,请将其视为本规则下的推荐默认值。
  • 在更改、替换或跳过表中的任何工具之前,请先询问用户。提供选项:保留推荐工具,或使用最后一列的替代方案(或其他最佳实践),为每个选项提供一行权衡说明以及您自己的推荐。
  • 在推荐替代方案之前,请检查当前状态(维护情况、重大更改)。不要仅凭记忆。
  • 在获得答案之前,切勿更改工具。在用户回答之前,请保留推荐的默认值。

1. 项目设置

  • 使用 pnpm create next-app@latest 搭建——启用 TypeScript、App Router、Tailwind、ESLint,拒绝 src/ 目录,使 app/ 保留在项目根目录(仅限新项目)。
  • 已使用 src/ 的现有项目: 保留 src/——src/app/、src/components/、src/lib/、src/actions/。仅在项目没有 src/ 目录时使用 app/。遵循现有布局和导入别名(@/* → src/*);切勿在不相关的任务中将文件移出 src/。
  • 每个安装/运行命令都使用 pnpm(pnpm add、pnpm dlx、pnpm dev)。切勿混入 npm/yarn 锁文件。
  • 通过 pnpm dlx shadcn@latest init 初始化 shadcn/ui,然后按需添加组件(pnpm dlx shadcn@latest add button),而不是预安装整套组件。
  • 基础文件夹结构(无 src/——app/ 位于项目根目录):
# 新项目(无 src/)
app/                   # 路由、布局、error/loading/not-found 边界
components/            # 共享 UI(ui/ = shadcn 原语)
lib/                   # 数据库、认证、验证、工具函数、速率限制、日志
actions/               # 按领域分组的服务器动作
hooks/
types/
drizzle/               # 迁移

现有 src/ 项目:在 src/ 下保持相同结构(src/app/、src/components/、src/lib/、src/actions/)——文件夹名称完全相同,仅前缀更改。

2. TypeScript 与代码质量

  • tsconfig 中 strict: true,无 any(除非有注释证明其合理性),无 @ts-ignore(除非有链接的问题或理由)。
  • 配置 ESLint(next/core-web-vitals + typescript-eslint)和 Prettier,并在代码被视为完成之前通过检查;运行它们,而不仅仅是假设。
  • 优先为导出的函数和服务器动作添加显式返回类型。
  • 保持服务器组件为默认;仅在需要交互性、浏览器 API 或 hooks 时添加 "use client",并尽可能将边界推低(到叶子级别)。
  • 每个文件/模块一个职责;将路由的服务器动作放在 actions/ 或路由旁边的 _actions.ts 文件中,而不是内联在巨大的页面文件中。
  • 架构约定: 每种逻辑保持在一个位置——数据访问在 lib/db,变更操作在 actions/,共享 UI 在 components/,横切助手在 lib/。遵循项目现有的命名约定(文件大小写、组件命名),而不是中途引入新约定。
  • 代码审查: 将每个非琐碎的更改视为 PR 规模——清晰的差异,在请求审查之前通过 lint/类型检查/测试,并描述更改内容和原因。在审查时(人工或 AI 辅助),检查缺失的身份验证检查、未处理的错误和约定偏离,而不仅仅是代码是否运行。

3. 渲染、数据与性能

  • 静态与动态渲染: 默认静态;仅在路由真正需要每次请求的数据时选择动态(export const dynamic = 'force-dynamic'、cookies()、headers())。
  • 数据获取: 直接在服务器组件中获取;使用服务器动作进行变更,而不是客户端获取到 API 路由(除非消费者是外部的)。
  • 流式传输与 Suspense: 将慢速/可流式传输的部分包裹在 <Suspense> 中,使用真实的骨架回退(而非仅旋转器),以便页面的其余部分可以立即渲染和流式传输——这也就是 loading.tsx 在路由级别提供的功能。
  • 缓存与重新验证: 对昂贵的读取使用 use cache / unstable_cache(根据 Next.js 版本);在变更后精确地使用 revalidatePath / revalidateTag 进行失效,而不是使用 force-dynamic 来“修复”过时数据。
  • 预取: 预取用户可能点击的链接——<Link> 会自动执行此操作;除非有特定原因,否则不要禁用它(prefetch={false})。
  • 懒加载与代码分割: 对折叠下方或很少使用的客户端组件使用 next/dynamic 进行懒加载;避免仅在一个页面上使用的大型客户端捆绑包。
  • 图像与字体优化: 始终对光栅图像使用 next/image(显式 width/height 或 fill + 尺寸容器),对字体使用 next/font——切勿使用原始的 <img> 或指向 Google Fonts 的 <link>。
  • 核心 Web 指标: 将 LCP、CLS、INP 视为真实约束——没有布局偏移的后期内容,没有未调整大小的媒体,没有阻塞同步脚本。

4. UI

  • 使用 Tailwind 进行样式设计;shadcn/ui 组件作为基础原语,通过项目的主题令牌(CSS 变量)进行自定义,而不是在文件中分散使用一次性内联覆盖。
  • react-icons 用于图标(每个项目选择一个图标集,例如 react-icons/lu 或 /hi2,并保持一致)。
  • Motion (motion.dev,前身为 Framer Motion) 用于动画;保持动画组件为客户端且小型,并尊重 prefers-reduced-motion。
  • 默认进行响应式设计(移动端优先的 Tailwind 断点);不要提供仅限桌面的布局。

5. 表单与验证

  • 每个表单/数据结构定义一个 Zod schema;对客户端验证(通过 @hookform/resolvers/zod)和服务器动作内的服务器端验证都复用相同的 schema——绝不信任仅客户端的验证。
  • React Hook Form (useForm) 驱动客户端状态;提交时,调用服务器动作,从动作的结构化返回值(而非导致通用错误的抛出异常)中显示字段错误。
  • 在启动时使用 Zod schema 验证 process.env 本身(一个 lib/env.ts),以便缺失或错误的配置快速失败,而不是在首次使用时才出错。

6. 数据库(PostgreSQL + Drizzle)

  • Schema 位于 lib/db/schema.ts(或按领域拆分),迁移通过 drizzle-kit generate 生成,并通过 drizzle-kit migrate 应用——切勿手动编辑生成的迁移文件。
  • 在无服务器/边缘上下文中使用池化连接(例如通过驱动程序的池或 Neon/Supabase 池化);不要为每个请求打开没有池化的新客户端。
  • 查询优化与 N+1 预防: 使用 Drizzle 的关系查询(db.query.x.findMany({ with: {...} }))或显式连接,而不是循环和逐行查询;只选择您需要的列,而不是 select * 风格的全行获取;对可能返回无限结果集的查询进行分页/限制。
  • 对 WHERE/ORDER BY/连接中使用的列建立索引;在 schema 中添加索引,而不是事后才考虑。
  • 为生产数据库记录备份/恢复方案(至少是托管提供商的快照)——如果用户的设置没有,请指出这一点。

7. 认证与安全

  • 使用 Better Auth 进行认证(会话、OAuth 提供商、电子邮件/密码根据需要);绝不手动编写密码哈希或会话令牌。
  • RBAC:显式建模角色/权限(一个 role 列加上一个小型权限检查辅助函数),并在 服务器动作/数据访问层 中强制执行授权,而不仅仅是隐藏 UI——隐藏的按钮不是访问控制。
  • 对敏感端点进行速率限制(认证、表单提交、任何昂贵的操作)——例如通过 Upstash Redis 或等效的令牌桶/滑动窗口限制器。
  • 设置安全头(通过 next.config.js 头或中间件):Content-Security-Policy、X-Frame-Options、Referrer-Policy、Permissions-Policy、Strict-Transport-Security。
  • Cookie:在所有认证/会话 Cookie 上设置 httpOnly、secure、sameSite: 'lax'(或 'strict',如果可行)。
  • 在边界处使用 Zod 验证每个外部输入(表单数据、查询参数、webhook 负载),然后再触及业务逻辑或数据库。
  • 绝不记录密钥、令牌或包含凭据的完整请求体。

8. SEO

  • 每条路由使用 Metadata API(generateMetadata / 静态 metadata 导出)——标题、描述、Open Graph、Twitter 卡片。
  • 提供从真实路由数据生成的 app/sitemap.ts 和 app/robots.ts,而不是硬编码的陈旧列表。
  • 通过元数据 alternates.canonical 设置规范 URL,尤其是对于可以通过多个查询字符串变体访问的任何路由。
  • 为受益的内容类型(文章、产品、面包屑导航、组织)添加 JSON-LD 结构化数据,使用 type="application/ld+json" 的 script 标签。

9. 无障碍

  • 语义 HTML 优先(button、nav、main、header、label)——仅当语义 HTML 无法覆盖真实缺口时才使用 ARIA。
  • 所有内容均可通过键盘单独到达和操作;可见的焦点状态(不要在没有替换的情况下移除 :focus-visible 轮廓)。
  • 每个图像都有有意义的 alt(仅对真正装饰性的图像使用空 alt="")。
  • 每个表单输入都有真正的关联 <label>(而不仅仅是占位符)。
  • 检查文本和交互元素与 WCAG AA 的最低色彩对比度。

10. 错误处理与加载状态

每个可能失败或耗时的路由段都应具有:

  • error.tsx——段级错误边界,带有重试操作。
  • global-error.tsx——error.tsx 无法捕获的错误的高级回退。
  • not-found.tsx——用于 404,包括数据查找中的 notFound() 调用。
  • loading.tsx——Suspense 回退;使其成为匹配最终布局的真实骨架,而不是裸旋转器。

11. 测试

  • Vitest 用于单元测试(纯函数、schema 验证、工具逻辑)和组件测试(React Testing Library)——放在 *.test.ts(x) 或 __tests__/ 下。
  • Playwright 用于端到端流程:认证、关键用户旅程、表单提交。针对预览部署或本地构建运行,而不是针对生产环境。
  • 新的服务器动作和验证 schema 应附带至少一个基本测试;不要让关键业务逻辑默认未经测试。

12. 监控与日志记录

  • Sentry 用于客户端和服务器的错误跟踪(instrumentation 文件 + sentry.client.config / sentry.server.config),部署时上传 source map。
  • 结构化日志(JSON 格式,包含请求 ID、路由、用户 ID(如果可用)),而不是临时的 console.log。
  • 在生产环境中跟踪核心 Web 指标(Vercel Analytics 或 Sentry Performance),并在部署的 URL 上设置正常运行时间监控。

13. DevOps

  • Git 具有常规的范围提交;受保护的 main 分支。
  • 每个 PR 上的 GitHub Actions CI:安装 → 代码检查 → 类型检查 → 单元测试 → 构建(较大更改添加端到端测试)。
  • 部署到 Vercel;每个 PR 在合并前都有一个预览部署。
  • 环境变量在 Vercel 中按环境管理,在启动时通过第 5 节的 Zod env schema 进行验证。

14. 媒体

  • Cloudinary 用于用户上传的动态媒体:通过签名、服务器颁发的上传参数上传(绝不公开 API 密钥到客户端),并通过 Cloudinary 的转换 URL 提供,而不是重新实现调整大小。

15. Claude 的工作约定

当被要求在使用此栈的项目中添加功能时:

  1. 在创建新 schema/动作/组件之前检查现有的——扩展,不要重复。
  2. 新的数据库字段 → 更新 schema.ts,生成迁移,不要手动编辑 SQL。
  3. 新表单 → Zod schema → RHF 表单 → 带有服务器端重新验证和授权检查的服务器动作。
  4. 新路由 → 有意决定静态还是动态;如果缺少 loading.tsx/error.tsx,添加它们;添加元数据。
  5. 变更后,重新验证受影响的具体路径/标签——不要全面重新验证整个应用。
  6. 在提供代码之前,在严格模式下进行 lint/类型检查的心理审查;标记任何 any、未检查的输入或缺失的身份验证检查,而不是静默交付。
  7. 在引入、替换或跳过第 0 节中的任何工具之前,向用户提供选项(参见第 0 节中的“推荐,非强制”规则)。

16. 配套规则文件

  • AGENTS.md——项目工作流程规则(主流程、功能流程、审批流程……)

…

[为翻译截断]

相关技能