Communitygithub.com

rbikbov/frontend-starter

用來啟動新的 Next.js (App Router) + TypeScript 前端專案:在開發第一個功能之前就先打好基礎。

frontend-starter 是什麼?

此技能旨在為新的前端專案建立堅實的基礎,特別聚焦於 Next.js (App Router) 與 TypeScript。它提供了一套結構化的決策順序與設定清單,從技術選擇(例如 Next.js 或 SPA、Monorepo 或單一應用程式)開始,逐步涵蓋嚴格 TypeScript 設定、FSD (Feature-Sliced Design) 專案結構、環境變數配置、錯誤處理模式與 API 客戶端、UI 基礎建設、測試(Vitest、Playwright)、Git hooks、CI/CD 以及預設安全性措施。整個過程以一份詳細的 SKILL.md 文件為指導,該文件明確定義了 MUST(必須)和 SHOULD(應該)的規則,幫助開發者或 AI 代理人在第一天就做出正確的技術決策,避免後續的技術債與重構成本。文件中也指定了如何正確地銜接 Next.js 的 App Router 與 FSD 分層架構,以及如何透過 `shared/config` 模組安全地管理環境變數。此技能支援所有使用 Next.js 進行開發的 AI 代理平台,例如 Claude Code 或 Cursor,並假設用戶已安裝 `pnpm` 與 Node 20.9+。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/rbikbov/frontend-starter/tree/HEAD/.claude/skills/frontend-bootstrap

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

使用 Next.js 啟動專案

地基在第一天鋪設最便宜:之後每一條規則都得覆蓋在違反它的程式碼之上。如果有 frontend-starter 範本——請從範本的副本開始: 範本中的步驟已經完成並驗證,而這份文件則保留作為決策說明與稽核查核清單。 這份文件定義了 步驟的順序與最小集合。如何編寫程式碼本身——請見技能 fsd-frontend(如果專案中有此技能),授權——請見 frontend-auth-session,提交前檢查——請見 anti-slop-review。 現成設定檔——請見 references/configs.md,Next + FSD 結構與程式碼範例——請見 references/next-structure.md。

規則優先順序。 使用者的明確指示與專案的 agent 檔案(AGENTS.md、CLAUDE.md)的權重高於此文件。套件版本會變更:在複製設定檔之前,請先比對已安裝版本的官方文件,並且在實際執行之前不要聲稱它能夠正常運作。

關於 Next.js 的事實——請參考套件內的文件,而非此文件或記憶。 自 16.2 版起,文件位於 node_modules/next/dist/docs/,專案的 AGENTS.md 也會引用它。如果與此處的範例有出入,請以已安裝版本的官方文件為準。

標記:MUST — 不得違反;SHOULD — 預設為是,偏離需要有原因。


1. 編碼前的決策

表格中的每個決策都必須記錄在 README(「決策」章節)或 ADR 中,並附上原因。未記錄原因就偏離預設值——不要這麼做。

問題預設值何時例外
Next.js 或 SPA如果需要至少以下一項,就使用 Next.js:SSR/SEO、BFF(機密、HttpOnly-cookie)、route handlers內部應用程式已登入、無 SEO 且無 BFF → 使用 Vite + React Router:建置與部署更簡單
路由器App RouterPages Router — 僅適用於現有專案
Monorepo否,單一應用程式當確有第二個應用程式或套件出現 → 使用 pnpm workspaces;Nx/Turborepo — 當建置或 CI 開始變慢時
Multi-Zones、微前端否具有獨立發布的獨立團隊
伺服端資料Server Components 用於初始載入;TanStack Query 用於互動性的客戶端資料與 Mutation純客戶端應用程式 → 僅使用 TanStack Query
文字與 i18n從第一天起就建立翻譯模組(next-intl 或類似套件),即使是單一語言環境,如果專案遵循 fsd-frontend 的話明確的「不使用 i18n」的決策已記錄在 README 中
套件管理工具pnpm,版本寫在 packageManager 中—
部署立即決定:Vercel、Node 伺服器(output: "standalone")或 Docker這會影響 env、快取、CI

MUST: 不要為了「未來」而加入技術。Monorepo、第二個路由器、Storybook、狀態管理工具、MSW(作為後端類型)只有在它們有第一個真正的使用者時才出現。


2. 步驟順序

  1. 建立專案(pnpm create next-app@latest):TypeScript、ESLint、Tailwind、App Router。固定 packageManager、engines.node(Next 16 需要 Node 20.9+)以及 .nvmrc。
  2. 立即刪除產生器範本: 起始頁面、public/ 中的 SVG、範本 README、示範樣式。將 README 替換為 references/configs.md 中的基礎架構。留下來「以後再處理」的範本會存活到正式環境。create-next-app 產生的 AGENTS.md 與 CLAUDE.md 不要刪除: <!-- BEGIN:nextjs-agent-rules --> 與 <!-- END:nextjs-agent-rules --> 之間的區塊會導引 agent 至已安裝版本的官方文件,next dev 會自行維護它。你自己的專案規則應該寫在這些標記之外。
  3. 嚴格 TypeScript(references/configs.md 的第 4 節)與 typecheck 腳本(tsc --noEmit)。
  4. 在 Next 之上疊加 FSD 結構(下面的第 3 節)。
  5. Linter 與格式化: 來自 eslint-config-next 的 ESLint flat config + 類型感知規則 + 邊界 lint + Prettier。Next 16 移除了 next lint,並且在 next build 時不會執行 lint——linter 需透過獨立腳本執行並在 CI 中執行。
  6. Env 設定(第 4 節)。
  7. shared/api 中的錯誤模型與 API 客戶端(第 5 節)。
  8. _app 層中的 Provider: QueryClient、主題、i18n、全域服務(toast、confirm)作為 shared 中的 port + 在 _app 中實作。
  9. UI 基礎(第 6 節)。
  10. 測試: Vitest + Testing Library + MSW、用於 e2e 的 Playwright(第 7 節)。
  11. Git hooks: husky + lint-staged (eslint --fix, prettier) + commitlint。
  12. CI: 每次 push 與 PR 都執行 lint、typecheck、test、build(第 8 節)。
  13. 預設安全性(第 9 節)。
  14. README 已經填入真實的內容(第 10 節),並且已完成「完成定義」(第 11 節)。

步驟 1–3 應作為一個獨立的「scaffold」提交:這樣在歷史中就能清楚看到產生器做了什麼,而你做了什麼。


3. 在 Next 路由之上疊加 FSD

根據 App Router 的官方 FSD 指南:Next 的服務資料夾 app/ 位於專案根目錄,FSD 層位於 src/,而 app 與 pages 層則加上前綴 _,以避免與 Next 的服務資料夾混淆。

app/                         Next 路由:僅包含路徑檔案
├── layout.tsx               根層佈局 → 來自 src/_app 的 Provider
├── (auth)/sign-in/page.tsx  export { SignInPage as default } from "@/_pages/sign-in"
└── api/auth/login/route.ts  route handler (BFF),薄層
proxy.ts                     Next 16+(以前是 middleware.ts),位於 app/ 旁
src/
├── _app/                    app 層:Provider、全域樣式、服務實作
├── _pages/                  pages 層
├── widgets/                 (如果專案使用它們)
├── features/
├── entities/
└── shared/{ui,api,lib,config}

MUST:

  • app/ 中的檔案要薄:從 src/_pages 重新匯出頁面、generateMetadata、解析 params/searchParams(在 Next 15+ 中它們是 Promise,需要 await)並透過 props 傳遞。其中不應包含邏輯。
  • Route handlers 與 Server Actions 要薄:解析並驗證輸入 → 呼叫 src 中的函式 → 回傳回應。每一個都是公開的進入點:自行檢查授權,而不是依賴 proxy.ts。
  • 不要建立 src/app 與 src/pages:Next 會在根目錄與 src 中尋找服務資料夾,具有此名稱的資料夾很容易變成第二個路由器。
  • 邊界 lint 知道前綴:使用 src/_app、src/_pages/* 模式,而非 src/app、src/pages/*(設定檔 — fsd-frontend、references/conventions.md,第 11 節)。
  • "use client" 應盡可能放在樹的底層。頁面預設為伺服器端,客戶端則是具有互動性的葉節點。
  • 包含機密的模組應以 import "server-only" 開頭,包含 window 的模組則以 import "client-only" 開頭。

詳細說明與程式碼:references/next-structure.md。


4. 環境設定

MUST:

  • 變數在兩個模組中讀取:shared/config/env.server.ts(import "server-only")與 shared/config/env.client.ts。模式使用 zod,在匯入時驗證:設定錯誤會在啟動時發生,而不是在第一次請求時。在其他程式碼中禁止使用 process.env(lint 規則)。
  • NEXT_PUBLIC_* 在建置時嵌入 bundle,且僅在直接引用 process.env.NEXT_PUBLIC_X 時才會:不要使用解構賦值或 process.env[name]。這樣無法為具有不同公開值的多個環境建置單一映像——這些值應在伺服器端讀取並向下傳遞。
  • 機密只能使用不含 NEXT_PUBLIC_ 前綴的變數。
  • .env.example 應包含每個變數,附有註解與安全值;.env* 應列入 .gitignore,但 .env.example 除外。CI 建置應使用 .env.example 中的值。

5. 錯誤模型與 API 客戶端

MUST:

  • 錯誤應在 shared/api 的邊界處正規化為帶有 kind 屬性的 AppError(模型 — fsd-frontend、references/conventions.md,第 1 節)。在 shared/api 之外,沒有人應該解析 Response、狀態碼與錯誤訊息。
  • 在 fetch 之上建立一個統一的 request() 函式(或使用同樣包裝過的生成客戶端):它會傳遞 signal、將網路錯誤轉換為 network、將 HTTP 狀態碼轉換為 kind、並使用 schema 驗證回應主體。範例 — references/next-structure.md。
  • 錯誤類型應根據其代碼決定:狀態碼、extensions.code(GraphQL 在錯誤時也回傳 200)、主體中的 code。如果後端只回傳文字,則在單一 mapper 中根據文字進行比對,並附上原因註解與測試。
  • 後端回應應在邊界處映射為領域類型;DTO 不應流入 UI。
  • 使用者資料不應在不同使用者之間快取:對於依賴 session 的回應,不要使用 "use cache"/unstable_cache。
  • 如果存在 schema(OpenAPI、GraphQL),則客戶端應從 schema 生成。Schema 或生成的程式碼應存放在 repository 中:CI 不應連接到真實的後端。

SHOULD: 在傳輸層之上建立介面(AuthApi + factory)——僅當它已經有第二個消費者時(fsd-frontend、references/state-and-data.md,2.1)。不要使用像 type: "mock" 的設定值,它會拋出「未實作」。


6. UI 基礎

  • 設計 Token — 在 :root 中使用 CSS 變數(並用於暗色主題),透過 @theme 連接到 Tailwind v4。在元件中僅使用 token;原始 HEX 與任意值(text-[#3a3a3a])——僅作為一次性例外,並附上註解。
  • 類別必須存在。 從 shadcn/ui 與範例複製過來的元件會帶有自己的 token(bg-card、text-muted-foreground)。你必須建立這些 token,或者替換這些類別——否則元件會默默地沒有樣式。
  • shared/ui 中的基本元件應建立在 headless 函式庫之上(Radix、React Aria)以確保無障礙性;變體使用 cva,類別合併使用 cn(clsx + tailwind-merge)。
  • 字型使用 next/font,圖片使用 next/image 並指定尺寸,images.remotePatterns 應明確列出。
  • Storybook — 僅當 UI Kit 被多個應用程式或團隊重複使用時才使用,不會更早。

7. 測試

  • Vitest + Testing Library + jsdom + MSW 並搭配 onUnhandledFrame: "error"(MSW 3;在 MSW 2 中為 onUnhandledRequest)。設定檔 — references/configs.md。
  • Vitest 無法渲染非同步 Server Components。將其中的邏輯提取到函式中並透過單元測試測試,頁面本身則透過 e2e 測試。
  • Playwright 用於 3–10 個關鍵路徑。在 CI 中,e2e 應針對可預測的後端(mock 伺服器、具有測試資料庫的測試環境)執行,而不是針對會導致測試修改他人資料的共用環境。
  • 第一個測試應在 Day 0 編寫:它會驗證測試基礎設施是否正常運作,並提供一個範例。

8. CI

MUST: 每次 push 到主要分支以及每個 PR 都應執行:lint、typecheck、test、build。GitHub Actions 範本 — references/configs.md。 對於公開 repository,Actions 是免費的;對於私有 repository,則有每月分鐘數配額。

  • CI 建置應使用 .env.example,不含機密。
  • e2e 應作為獨立的 job 執行,當有隔離的後端時;在此之前,應在 README 中明確標記為何 CI 中沒有 e2e。
  • README 中的 CI badge 應與 workflow 同時出現。

9. 預設安全性

  • poweredByHeader: false;透過 next.config.ts 中的 headers() 設定標頭:X-Content-Type-Options: nosniff、Referrer-Policy: strict-origin-when-cross-origin、X-Frame-Options: DENY(或 CSP 中的 frame-ancestors)。CSP 與 nonce 是另一項任務,但「有 / 無及其原因」的決策應立即記錄下來。
  • Server Actions 與 route handlers 是公開端點:每個都應使用 schema 驗證輸入並檢查權限。
  • dangerouslySetInnerHTML — 僅使用 sanitizer 並附上原因註解。
  • 個人資料與 token 不應被記錄。
  • 授權 — 請見 frontend-auth-session。

10. README

基礎架構 — references/configs.md。規則只有一個:README 中只應包含對該提交中的程式碼為真的事實。 每個章節應在描述它的程式碼所在的同一個提交中更新。計劃應放在獨立的「下一步」章節中,並標記為尚未完成。


11. 啟動的完成定義

  • 產生器範本已刪除;README 是基礎架構,並已填入真實內容。
  • packageManager、engines.node、.nvmrc 已固定。
  • TS 嚴格模式已啟用;typecheck、lint、test、build 能在本地通過(已執行,而非假設)。
  • 使用 _app/_pages 前綴的 FSD 佈局已就緒;邊界 lint 能捕獲向上匯入。
  • Env 透過兩個帶有 schema 的模組進行管理;process.env 在這些模組之外被 lint 禁止;.env.example 是完整的。
  • shared/api 中已有 AppError 與 request(),並有測試覆蓋(網路、狀態碼、無效 schema)。
  • _app 中的 Provider 已就緒;QueryClient 不應在伺服器上跨使用者共用。
  • 設計 token 已存在於 CSS 變數中;所有使用的類別都存在。
  • Vitest + MSW + Playwright 已設定完畢,各有一個實際的測試。
  • Git hooks 與 commitlint 正常運作。
  • CI 是綠燈。
  • 安全性標頭已設定,且 poweredByHeader: false。
  • 第 1 節中的決策已記錄。

12. 當你猶豫不決時

  • 在「現在就加入」與「等到需要時再加入」之間——選擇等到需要時再加入。
  • 在「手動設定」與「保留 create-next-app 產生的設定」之間——在沒有理由改變之前先保留,並且在改變時記錄原因。
  • 在「單一應用程式」與「Monorepo」之間——選擇單一應用程式。
  • 在「參考記憶中的設定」與「參考目前版本的官方文件」之間——選擇官方文件。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

rbikbov/frontend-starter

Creates Architecture Decision Records documenting key technical decisions with context, alternatives considered, tradeoffs, consequences, and decision owners. Use when documenting "architecture decisions", "technical choices", "design decisions", or "ADRs".

rbikbov/frontend-starter

Проверка фронтенд-кода и документации на «нейрослоп» перед коммитом, PR или публикацией репозитория: остатки генераторов, мёртвые и недоделанные опции, утверждения в README и комментариях, не подтверждённые кодом, маркетинговый тон и эмодзи, лишние абстракции, хрупкая обработка ошибок, персональные данные в логах, несуществующие классы стилей. Использовать, когда просят проверить код или репозиторий «на слоп», подготовить проект к публикации или показу, сделать ревью кода, написанного с помощью ИИ, или перед тем как закоммитить собственную большую правку.

rbikbov/frontend-starter

Процесс разработки фичи с агентом: PRD с Non-Goals → компактная спецификация → задачи по одной на коммит → read-only исследование → tracer bullet → сборка с тестом сначала → независимое ревью субагентом → проверка в браузере. Использовать, когда просят сделать фичу, экран, пользовательский сценарий или заметное изменение поведения; когда нужно написать PRD, спецификацию или разбить работу на задачи; когда работа больше одного коммита. Не использовать для опечаток и однострочных правок.

rbikbov/frontend-starter

Авторизация и сессия во фронтенде на Next.js (App Router): где хранить токены, BFF на route handlers с HttpOnly-cookie, refresh токена без гонок, определение «не авторизован» (включая GraphQL, который отвечает 200), проверки в proxy.ts и Data Access Layer, безопасный редирект после входа, выход без утечки данных прошлого пользователя, токены в ссылках сброса пароля, формы входа и восстановления. Использовать, когда проектируешь или пишешь вход, регистрацию, восстановление пароля, защищённые страницы, API-клиент с refresh-токеном, или ревьюишь такой код.

相關技能