前端约定的 机器可读化
一个 7 步可视化向导,让团队在 3 分钟内把前端约定转成 frontend-align.md(人读)与 SKILL.md(机器读)——Claude Code、Cursor、Copilot 直接加载并遵守同一份契约。
# razr001/align-dev · Next.js 16 · TypeScript · MIT
WizardState 数据模型
源码:types/wizard.ts。WizardState 是整个 align-dev 的核心数据类型,定义前端项目的完整配置选项——通过 7 个步骤填写,最终驱动两个生成器。
用户通过 Next.js 前端填写 7 个配置维度(core-stack / ui-styles / state-management / toolchain / directory / naming-code / design-tokens),后端据此生成 frontend-align.md 与 SKILL.md。
| 类别 | 字段 | 类型 | 取值 |
|---|---|---|---|
| 核心栈 | framework | Framework | nextjs | react-spa | vue | nuxt | svelte |
language | Language | typescript | javascript | |
pkgMgr | PkgMgr | npm | yarn | pnpm | bun | |
buildTool | BuildTool | vite | rollup | webpack | none | |
i18n | I18n | none | next-intl | i18next | vue-i18n | nuxt-i18n | |
| 国际化 | textDirection | TextDirection | ltr | rtl | bidi |
| UI 与样式 | componentLib | ComponentLib | antd | shadcn | mui | radix | chakra | element-plus | … |
cssSolution | CssSolution | tailwind | css-modules | styled-components | scss | |
iconLib | IconLib | lucide | react-icons | heroicons | none | |
themeStyle | ThemeStyle | 49 种主题风格(minimalism / neumorphism / glassmorphism…) | |
| 状态管理 | globalState | GlobalState | zustand | redux-toolkit | jotai | context-api | pinia | vuex | svelte-store |
serverState | ServerState | tanstack-query | swr | nuxt-built-in | sveltekit-built-in | none | |
| 工具链 | linter | Linter | eslint | biome | oxc |
formatter | Formatter | prettier | biome | oxc | |
preCommit | PreCommit | husky-lint-staged | lefthook | none | |
| 测试 / CI | testing | TestingTool[] | jest | vitest | playwright | cypress(数组,多选) |
cicd | CICD | github-actions | gitlab-ci | none | |
| 目录 / 命名 | dirPattern | DirPattern | feature-based | layer-based | monorepo |
dirDepth | DirDepth | 2 | 3 | 4 | |
fileNaming | FileNaming | kebab-case | camelCase | |
importOrder | ImportOrder | framework-first | absolute-then-relative | |
| 设计令牌 | maxFileLines | MaxFileLines | 200 | 300 | 500 |
customTokens | Record<string,string> | 自定义 CSS 变量令牌 | |
colorDepth | ColorDepth | 3-tier | 5-tier | |
spacingBase | SpacingBase | 4 | 8 | |
tokenConvention | TokenConvention | css-vars | js-object | both | |
typographyScale | TypographyScale | minor-third | major-third | perfect-fourth | major-sixth |
默认配置 DEFAULT_WIZARD_STATE
export const DEFAULT_WIZARD_STATE: WizardState = {
framework: 'nextjs',
language: 'typescript',
pkgMgr: 'pnpm',
buildTool: 'vite',
i18n: 'none',
textDirection: 'ltr',
componentLib: 'shadcn',
cssSolution: 'tailwind',
iconLib: 'lucide',
globalState: 'zustand',
serverState: 'tanstack-query',
linter: 'eslint',
formatter: 'prettier',
preCommit: 'husky-lint-staged',
testing: ['vitest'],
cicd: 'github-actions',
dirPattern: 'feature-based',
dirDepth: 3,
fileNaming: 'kebab-case',
importOrder: 'framework-first',
maxFileLines: 300,
themeStyle: 'minimalism',
customTokens: {},
colorDepth: '5-tier',
spacingBase: 4,
tokenConvention: 'css-vars',
typographyScale: 'major-third',
}
7 个步骤 · STEP_LABELS
document-generator.ts 分段函数
源码:lib/document-generator.ts。一个纯函数把 WizardState 变成完整 Markdown 规范文档,由 13 个分段函数(s1–s13)拼装而成。
核心机制 · 模块级版本状态
文件用模块级变量 _v: VersionMap 存储实时版本,通过 mv() / pd() 在生成文档时插入版本信息——避免在每个分段函数之间反复传参。
// 用常量避免在模板字符串里转义反引号
const B = '`'
const FENCE = B + B + B // 代码块标记 ```
let _v: VersionMap = {}
// 获取包的实时版本,失败时回退
const mv = (pkg: string, fb: string): string => _v[pkg] ?? FALLBACK_VERSIONS[pkg] ?? fb
// 格式化为 package.json 依赖条目
const pd = (pkg: string, fb: string): string => `"${pkg}": "^${mv(pkg, fb)}.x"`
分段函数列表 · s1 → s13
| 函数 | 输出章节 | 关键逻辑 |
|---|---|---|
s1Overview(s) | 1. Document Overview | 技术栈总览表格、standards 等级说明 |
s2TechStack(s) | 2. Core Stack Standards | 版本锁定策略、构建工具配置、依赖管理规则 |
s3Directory(s) | 3. Directory Structure | 按 framework + dirPattern 生成不同目录树 |
s4Naming(s) | 4. Naming Standards | 文件 / 组件 / hooks / 常量 / TS 类型命名规则 |
s5Components(s) | 5. Component Development | 组件模板、Server/Client 决策、Props 规范 |
s6StateManagement(s) | 6. State Management | 按 globalState 生成 Zustand/Redux/Jotai/Context 示例 |
s7Styles(s) | 7. Style Standards | 按 cssSolution 生成 Tailwind/CSS Modules/SCSS 规范 |
s8Toolchain(s) | 8. Development Toolchain | ESLint/Biome/OXC、Prettier、Husky/lint-staged |
s9Testing(s) | 9. Testing Standards | 按 testing 数组生成测试金字塔与命名规范 |
s10DesignTokens(s) | 10. Design Tokens | 主题、颜色、排版、间距、CSS 变量定义 |
s11Git(s) | 11. Git Workflow | 分支命名、Conventional Commits、PR 清单 |
s12CICD(s) | 12. CI/CD Pipeline | 按 cicd 生成 GitHub Actions 或 GitLab CI |
s13I18n(s) | 13. Internationalization | 按 i18n 类型生成配置(i18n='none' 返回 null) |
主入口 · generateDocument
export function generateDocument(s: WizardState, v: VersionMap = {}): string {
// 注入实时版本,使 mv()/pd()/标签辅助函数能取到最新版本
_v = { ...FALLBACK_VERSIONS, ...v }
const sections = [
s1Overview(s), s2TechStack(s), s3Directory(s),
s4Naming(s), s5Components(s), s6StateManagement(s),
s7Styles(s), s8Toolchain(s), s9Testing(s),
s10DesignTokens(s), s11Git(s), s12CICD(s),
s13I18n(s),
].filter((sec): sec is string => sec !== null) // s13I18n 对 i18n='none' 返回 null
_v = {} // 生成后重置
return sections.join('\n\n---\n\n')
}
generateDocument 统一注入版本、跑完 13 段、再重置 _v——既享受模块级变量「不用层层传参」的便利,又用「用后即清」保持纯函数的可重入性。条件化生成逻辑
分段函数不是静态模板——多个函数根据 WizardState 的值动态分叉。其中 s3Directory(目录结构)与 s10DesignTokens(设计令牌)是分叉最重的两个。
s3Directory · 按 framework + dirPattern 生成目录树
多项目 + 共享包
apps/
├── web/ # Next.js 主应用
├── admin/ # 管理后台
└── mobile/ # RN(可选)
packages/
├── ui/ # 共享组件库
├── config/ # ESLint/TS 配置
├── utils/ # 共享工具
└── types/ # 共享类型
feature-based
app/
├── (auth)/login/page.tsx
├── (dashboard)/users/page.tsx
└── api/users/route.ts
features/
├── auth/components/
└── users/components/
components/
├── ui/
└── common/
layer-based
src/
├── assets/
├── components/
├── hooks/
├── pages/
├── services/
├── store/
└── utils/
s10DesignTokens · 令牌分类与输出
该函数把设计令牌分成功能色 / 中性色 / 品牌色三类,分别处理:
// 功能颜色(必须符合用户心理预期)
const FUNCTIONAL_VARS = [
'--color-success', '--color-error',
'--color-warning', '--color-info', '--color-link'
]
// 中性颜色分三层:Text / Background / Border
const NEUTRAL_VARS = [
// Text: --color-text-primary/secondary/tertiary/disabled/inverse
// Bg: --color-neutral-bg/bg-subtle/bg-muted/elevated
// Border: --color-neutral-divider/border/border-strong
]
// 品牌颜色(通过 customTokens 自定义,排除已知功能/中性变量)
const brandLines = Object.entries(tokens)
.filter(([cssVar]) => !FUNCTIONAL_VARS.includes(cssVar) && !allNeutralVars.includes(cssVar))
.map(([cssVar, value]) => ` ${cssVar}: ${value};`)
.join('\n')
条件化分叉一览
| 函数 | 条件字段 | 分叉行为 |
|---|---|---|
s5Components | framework | Next.js 时追加 Server/Client 组件决策小节 |
s7Styles | cssSolution | 生成 Tailwind / CSS Modules / SCSS 特定内容 |
s8Toolchain | linter · formatter | ESLint / Biome / OXC 各自配置 |
s9Testing | testing[] | 数组为空 → 返回「手动测试清单」 |
s12CICD | cicd | 'none' → 返回手动部署检查清单 |
s13I18n | i18n | 'none' → 返回 null(整节跳过) |
skill-generator.ts 机器侧输出
源码:lib/skill-generator.ts。把同一份 WizardState 变成 agent 可读的 SKILL.md——标准 YAML frontmatter,兼容 Claude Code 的 skill 加载机制。
export function generateSkill(s: WizardState, v: VersionMap = {}): string {
_v = { ...FALLBACK_VERSIONS, ...v }
const pm = PM_RUN[s.pkgMgr] // e.g. "pnpm"
const px = PM_EXEC[s.pkgMgr] // e.g. "pnpm dlx"
const isTS = s.language === 'typescript'
// 构建技术栈描述
const stack = [
fwLabel(s.framework),
isTS ? 'TypeScript' : 'JavaScript',
cssLabel(s.cssSolution),
stateLabel(s.globalState),
s.serverState !== 'none' ? serverStateLabel(s.serverState) : '',
].filter(Boolean).join(', ')
// ... 生成 skill 内容
}
生成的 SKILL.md 结构
---
name: frontend-align-dev
description: >
Use whenever writing, modifying, or reviewing frontend code in this project.
Stack: Next.js 16, TypeScript, Tailwind CSS v4, Zustand, TanStack Query v5.
Triggers on any component, hook, store, style, or test file change.
---
## Dependency Bootstrap # 检查 ui-ux-pro-max-skill 是否存在
## Required Reading # 要求阅读 frontend-align.md
## Workflow # 1 理解需求 2 检查结构 3 实现 4 lint/typecheck/test 5 合规审查
## Compliance Checklist # 7–10 条,按 stack 动态定制
- Component naming follows the standard.
- Folder structure follows the standard.
- TypeScript types are explicit — no `any`.
- State management (Zustand) follows the standard.
- Styling (Tailwind CSS) follows the standard.
- All user-facing strings go through the i18n layer. # 若启用 i18n
- New logic has corresponding unit tests. # 若启用测试
## Final Response Format # 修改内容 / 遵循的规则 / 无法遵循的规则 / 运行的命令
PM_RUN / PM_EXEC 命令映射
| Package Manager | PM_RUN | PM_EXEC |
|---|---|---|
| npm | npm run | npx |
| yarn | yarn | yarn |
| pnpm | pnpm | pnpm dlx |
| bun | bun run | bunx |
检查命令生成
const lintCmd = s.linter === 'biome'
? `${px} @biomejs/biome check --apply .`
: `${pm} lint`
const typecheckCmd = isTS ? `${px} tsc --noEmit` : null
const testCmd = s.testing.length > 0 ? `${pm} test` : null
const checkCmds = [lintCmd, typecheckCmd, testCmd].filter(Boolean).join(' / ')
// 输出示例: "pnpm lint / npx tsc --noEmit / pnpm test"
frontend-align.md(人读,用于 code review)+ SKILL.md(机器读,放仓库根目录被 agent 自动加载)形成完整约定体系——这是 AlignDev 区别于纯文档工具的关键。pkg-versions.ts 实时版本
源码:lib/pkg-versions.ts。从 npm registry API 实时获取最新主版本号,让生成的文档始终引用当前最新版本(如 "next": "^16.x"),并提供 FALLBACK_VERSIONS 兜底。
export type VersionMap = Record<string, string>
// 例如: { next: '16', react: '19', vite: '6', ... }
FALLBACK_VERSIONS 回退版本表
| 类别 | 包名 | 回退主版本 |
|---|---|---|
| 框架 | next · react · vue · nuxt · svelte | 16 · 19 · 3 · 4 · 5 |
| 构建 | vite · rollup · webpack | 6 · 4 · 5 |
| 语言 | typescript · @types/node | 6 · 22 |
| CSS | tailwindcss · styled-components · scss · daisyui | 4 · 6 · 0.2 · 5 |
| 组件库 | antd · @mui/material · @chakra-ui/react · element-plus · ant-design-vue · naive-ui | 6 · 9 · 3 · 2 · 4 · 2 |
| 状态 | zustand · @reduxjs/toolkit · jotai · pinia | 5 · 2 · 2 · 2 |
| 数据获取 | @tanstack/react-query · @tanstack/vue-query · swr | 5 · 5 · 2 |
| 工具链 | eslint · prettier · @biomejs/biome | 9 · 3 · 1 |
| 国际化 | next-intl · i18next · vue-i18n · @nuxtjs/i18n | 4 · 26 · 11 · 10 |
fetchVersions · 实时获取
export async function fetchVersions(): Promise<VersionMap> {
try {
const res = await fetch('/api/versions', { cache: 'no-store' })
if (!res.ok) return FALLBACK_VERSIONS
const data = await res.json() as VersionMap
// 合并:API 结果优先,回退版本填补空缺
return { ...FALLBACK_VERSIONS, ...data }
} catch {
return FALLBACK_VERSIONS
}
}
该函数从 Next.js API 路由 /api/versions 获取最新版本,任何失败都回退到 FALLBACK_VERSIONS。合并逻辑 { ...FALLBACK_VERSIONS, ...v } 确保:所有已知包都有合理回退、API 实时版本能覆盖、未返回的包仍用回退。
_v[pkg] ?? FALLBACK_VERSIONS[pkg] ?? fb 三级回退——文档生成绝不因版本获取失败而中断。整体流程
从用户填写 WizardState 到产出两份契约文件的完整链路。
WizardState(用户配置) VersionMap(npm 版本)
├── framework: 'nextjs' ├── next: '16'
├── language: 'typescript' ├── react: '19'
├── pkgMgr: 'pnpm' ├── tailwindcss: '4'
├── cssSolution: 'tailwind' └── ...
├── globalState: 'zustand'
├── serverState: 'tanstack-query'
├── themeStyle: 'minimalism'
├── customTokens: { --color-primary: '#3b82f6', ... }
└── ...
│
▼
┌────────────────────────────────────────────┐
│ generateDocument(state, versions) │
│ s1Overview → s2TechStack → s3Directory │
│ → s4Naming → s5Components → s6State… │
│ → s7Styles → s8Toolchain → s9Testing │
│ → s10DesignTokens → s11Git → s12CICD │
│ → s13I18n(可选) │
└────────────────────────────────────────────┘
│ │
▼ ▼
frontend-align.md(人读) generateSkill(state, versions)
│
▼
SKILL.md(机器读)
配置 WizardState
7 步向导收集框架、CSS、状态管理等配置。
获取实时版本
fetchVersions() 从 /api/versions 拉最新版本。
生成规范文档
generateDocument() 产出 13 章 Markdown。
生成 Skill 文件
generateSkill() 产出 agent 可读 SKILL.md。
关键设计模式
AlignDev 的工程取舍,以及它在 coding agent 生态里的定位。
版本状态模块化
用模块级变量 _v 避免在每个分段函数间传递版本参数,generateDocument 统一注入、生成后重置。
条件化内容生成
各分段函数按 WizardState 字段值有条件返回内容(如 i18n='none' 时整节跳过)。
版本回退保护
所有版本查询走 ?? FALLBACK_VERSIONS[pkg] ?? fb 链式回退,确保生成不中断。
分段函数模板
13 个 s*N 函数各负责一章,最后 filter + join 组合成完整文档。