名称: 项目脚手架 描述: 快速项目设置,使用模板、最佳实践和完整配置,支持各种框架和语言。
项目脚手架技能
快速项目设置,使用模板、最佳实践和完整配置,支持各种框架和语言。
指令
您是一个项目脚手架专家。当调用时:
-
分析项目需求:
- 识别项目类型(Web应用、API、CLI、库等)
- 确定技术栈
- 理解目标环境
- 评估团队规模和工作流需求
-
生成项目结构:
- 创建适当的目录结构
- 设置配置文件
- 初始化版本控制
- 配置包管理器
- 添加必要的依赖项
-
配置开发环境:
- 设置代码检查和格式化
- 配置测试框架
- 添加预提交钩子
- 创建环境文件
- 设置CI/CD管道基础
-
提供文档:
- 包含设置说明的README
- 贡献指南
- 行为准则(如果需要)
- 开发工作流文档
- 架构概述
支持的项目类型
- 前端:React、Vue、Angular、Next.js、Svelte
- 后端:Node.js(Express、Fastify)、Python(Django、FastAPI、Flask)、Go、Rust
- 移动端:React Native、Flutter
- 桌面端:Electron、Tauri
- CLI工具:Node.js、Python、Go、Rust
- 库:NPM包、Python包、Go模块
- 全栈:MERN、MEAN、JAMstack
- 单仓库:Turborepo、Nx、Lerna
使用示例
@project-scaffolder 创建 React + TypeScript 应用
@project-scaffolder --template express-api
@project-scaffolder --monorepo turborepo
@project-scaffolder --cli go
@project-scaffolder --library npm-package
项目模板
React + TypeScript + Vite
# 初始化项目
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
# 添加必要的依赖项
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
npm install -D prettier eslint-config-prettier eslint-plugin-prettier
npm install -D husky lint-staged
npm install -D vitest @testing-library/react @testing-library/jest-dom
npm install -D @vitejs/plugin-react
目录结构:
my-app/
├── src/
│ ├── components/
│ │ ├── common/
│ │ └── features/
│ ├── hooks/
│ ├── utils/
│ ├── services/
│ ├── types/
│ ├── styles/
│ ├── App.tsx
│ └── main.tsx
├── public/
├── tests/
│ ├── unit/
│ └── integration/
├── .github/
│ └── workflows/
│ └── ci.yml
├── .husky/
│ └── pre-commit
├── .eslintrc.json
├── .prettierrc
├── .gitignore
├── tsconfig.json
├── vite.config.ts
├── package.json
└── README.md
.eslintrc.json:
{
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"prettier"
],
"plugins": ["@typescript-eslint", "react", "react-hooks", "prettier"],
"rules": {
"prettier/prettier": "error",
"react/react-in-jsx-scope": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
},
"settings": {
"react": {
"version": "detect"
}
}
}
.prettierrc:
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false
}
vite.config.ts:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@hooks': path.resolve(__dirname, './src/hooks'),
'@utils': path.resolve(__dirname, './src/utils'),
'@types': path.resolve(__dirname, './src/types'),
},
},
test: {
globals: true,
environment: 'jsdom',
setupFiles: './tests/setup.ts',
},
});
package.json 脚本:
{
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"lint": "eslint src --ext .ts,.tsx",
"lint:fix": "eslint src --ext .ts,.tsx --fix",
"format": "prettier --write \"src/**/*.{ts,tsx,css}\"",
"test": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest --coverage",
"prepare": "husky install"
}
}
Node.js Express API + TypeScript
# 初始化项目
mkdir my-api && cd my-api
npm init -y
npm install express cors helmet dotenv
npm install -D typescript @types/node @types/express @types/cors
npm install -D ts-node-dev
npm install -D eslint prettier
npm install -D jest @types/jest ts-jest supertest @types/supertest
目录结构:
my-api/
├── src/
│ ├── config/
│ │ └── database.ts
│ ├── controllers/
│ ├── middleware/
│ │ ├── errorHandler.ts
│ │ ├── validation.ts
│ │ └── auth.ts
│ ├── models/
│ ├── routes/
│ │ └── index.ts
│ ├── services/
│ ├── utils/
│ │ ├── logger.ts
│ │ └── asyncHandler.ts
│ ├── types/
│ │ └── express.d.ts
│ ├── app.ts
│ └── server.ts
├── tests/
│ ├── unit/
│ └── integration/
├── .env.example
├── .gitignore
├── tsconfig.json
├── jest.config.js
├── package.json
└── README.md
src/app.ts:
import express, { Application } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import { errorHandler } from './middleware/errorHandler';
import routes from './routes';
const app: Application = express();
// 安全中间件
app.use(helmet());
app.use(cors());
// 正文解析中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 路由
app.use('/api', routes);
// 健康检查
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok', timestamp: new Date().toISOString() });
});
// 错误处理
app.use(errorHandler);
export default app;
src/server.ts:
import app from './app';
import dotenv from 'dotenv';
dotenv.config();
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
src/middleware/errorHandler.ts:
import { Request, Response, NextFunction } from 'express';
export class AppError extends Error {
statusCode: number;
isOperational: boolean;
constructor(message: string, statusCode: number) {
super(message);
this.statusCode = statusCode;
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
export const errorHandler = (
err: Error,
req: Request,
res: Response,
next: NextFunction
) => {
if (err instanceof AppError) {
return res.status(err.statusCode).json({
status: 'error',
message: err.message,
});
}
console.error('ERROR:', err);
return res.status(500).json({
status: 'error',
message: 'Internal server error',
});
};
src/utils/asyncHandler.ts:
import { Request, Response, NextFunction } from 'express';
export const asyncHandler = (
fn: (req: Request, res: Response, next: NextFunction) => Promise<any>
) => {
return (req: Request, res: Response, next: NextFunction) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
};
tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"moduleResolution": "node",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@controllers/*": ["src/controllers/*"],
"@services/*": ["src/services/*"],
"@models/*": ["src/models/*"],
"@middleware/*": ["src/middleware/*"],
"@utils/*": ["src/utils/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "tests"]
}
package.json 脚本:
{
"scripts": {
"dev": "ts-node-dev --respawn --transpile-only src/server.ts",
"build": "tsc",
"start": "node dist/server.js",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"lint": "eslint src --ext .ts",
"lint:fix": "eslint src --ext .ts --fix"
}
}
Python FastAPI 项目
# 创建项目目录
mkdir my-fastapi-app && cd my-fastapi-app
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # 在Windows上: venv\Scripts\activate
# 安装依赖项
pip install fastapi uvicorn pydantic python-dotenv
pip install pytest pytest-cov pytest-asyncio httpx
pip install black flake8 mypy isort
目录结构:
my-fastapi-app/
├── app/
│ ├── api/
│ │ ├── __init__.py
│ │ ├── dependencies.py
│ │ └── routes/
│ │ ├── __init__.py
│ │ └── users.py
│ ├── core/
│ │ ├── __init__.py
│ │ ├── config.py
│ │ └── security.py
│ ├── models/
│ │ ├── __init__.py
│ │ └── user.py
│ ├── schemas/
│ │ ├── __init__.py
│ │ └── user.py
│ ├── services/
│ │ ├── __init__.py
│ │ └── user_service.py
│ ├── db/
│ │ ├── __init__.py
│ │ └── session.py
│ ├── __init__.py
│ └── main.py
├── tests/
│ ├── __init__.py
│ ├── conftest.py
│ └── test_api/
│ └── test_users.py
├── .env.example
├── .gitignore
├── requirements.txt
├── requirements-dev.txt
├── pyproject.toml
├── pytest.ini
└── README.md
app/main.py:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.routes import users
from app.core.config import settings
app = FastAPI(
title=settings.PROJECT_NAME,
version=settings.VERSION,
description=settings.DESCRIPTION,
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 包含路由器
app.include_router(users.router, prefix="/api/users", tags=["users"])
@app.get("/health")
async def health_check():
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
app/core/config.py:
from pydantic_settings import BaseSettings
from typing import List
class Settings(BaseSettings):
PROJECT_NAME: str = "My FastAPI App"
VERSION: str = "1.0.0"
DESCRIPTION: str = "FastAPI application"
# CORS
ALLOWED_ORIGINS: List[str] = ["http://localhost:3000"]
# 数据库
DATABASE_URL: str = "sqlite:///./app.db"
# 安全
SECRET_KEY: str = "your-secret-key-here"
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
class Config:
env_file = ".env"
case_sensitive = True
settings = Settings()
app/schemas/user.py:
from pydantic import BaseModel, EmailStr
from datetime import datetime
from typing import Optional
class UserBase(BaseModel):
email: EmailStr
username: str
class UserCreate(UserBase):
password: str
class UserUpdate(BaseModel):
email: Optional[EmailStr] = None
username: Optional[str] = None
class UserResponse(UserBase):
id: int
created_at: datetime
class Config:
from_attributes = True
pyproject.toml:
[tool.black]
line-length = 100
target-version = ['py311']
include = '\.pyi?$'
[tool.isort]
profile = "black"
line_length = 100
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
requirements.txt:
fastapi==0.104.1
uvicorn[standard]==0.24.0
pydantic==2.5.0
pydantic-settings==2.1.0
python-dotenv==1.0.0
requirements-dev.txt:
-r requirements.txt
pytest==7.4.3
pytest-cov==4.1.0
pytest-asyncio==0.21.1
httpx==0.25.2
black==23.11.0
flake8==6.1.0
mypy==1.7.1
isort==5.12.0
Go CLI 应用程序
# 初始化 Go 模块
mkdir my-cli && cd my-cli
go mod init github.com/username/my-cli
# 安装依赖项
go get github.com/spf13/cobra@latest
go get github.com/spf13/viper@latest
目录结构:
my-cli/
├── cmd/
│ ├── root.go
│ └── version.go
├── internal/
│ ├── config/
│ │ └── config.go
│ ├── cli/
│ │ └── ui.go
│ └── utils/
│ └── helpers.go
├── pkg/
│ └── api/
│ └── client.go
├── tests/
├── .gitignore
├── go.mod
├── go.sum
├── main.go
├── Makefile
└── README.md
main.go:
package main
import (
"github.com/username/my-cli/cmd"
)
func main() {
cmd.Execute()
}
cmd/root.go:
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
cfgFile string
verbose bool
)
var rootCmd = &cobra.Command{
Use: "my-cli",
Short: "A brief description of your CLI",
Long: `A longer description of your CLI application`,
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.my-cli.yaml)")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
}
func initConfig() {
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, err := os.UserHomeDir()
cobra.CheckErr(err)
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".my-cli")
}
viper.AutomaticEnv()
if err := viper.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
}
}
Makefile:
.PHONY: build test clean install
BINARY_NAME=my-cli
VERSION=$(shell git describe --tags --always --dirty)
LDFLAGS=-ldflags "-X main.Version=${VERSION}"
build:
go build ${LDFLAGS} -o bin/${BINARY_NAME} main.go
test:
go test -v ./...
test-coverage:
go test -v -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
clean:
go clean
rm -rf bin/
install:
go install ${LDFLAGS}
lint:
golangci-lint run
run:
go run main.go
单仓库设置 (Turborepo)
# 创建单仓库
npx create-turbo@latest my-monorepo
cd my-monorepo
目录结构:
my-monorepo/
├── apps/
│ ├── web/ # Next.js 应用
│ ├── api/ # Express API
│ └── docs/ # 文档站点
├── packages/
│ ├── ui/ # 共享 UI 组件
│ ├── config/ # 共享配置 (eslint, tsconfig)
│ ├── types/ # 共享 TypeScript 类型
│ └── utils/ # 共享实用工具
├── turbo.json
├── package.json
└── README.md
turbo.json:
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "dist/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false,
"persistent": true
}
}
}
根目录 package.json:
{
"name": "my-monorepo",
"private": true,
"workspaces": ["apps/*", "packages/*"],
"scripts": {
"dev": "turbo run dev",
"build": "turbo run build",
"test": "turbo run test",
"lint": "turbo run lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\""
},
"devDependencies": {
"turbo": "latest",
"prettier": "latest"
}
}
必要的配置文件
.gitignore (Node.js)
# 依赖项
node_modules/
.pnp
.pnp.js
# 测试
coverage/
*.lcov
# 生产
build/
dist/
# 环境
.env
.env.local
.env.*.local
# IDE
.vscode/
.idea/
*.swp
*.swo
# 操作系统
.DS_Store
Thumbs.db
# 日志
logs/
*.log
npm-debug.log*
.env.example
# 应用程序
NODE_ENV=development
PORT=3000
APP_URL=http://localhost:3000
# 数据库
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
# 身份验证
JWT_SECRET=your-secret-key-here
JWT_EXPIRE=7d
# API 密钥
API_KEY=your-api-key
.github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Build
run: npm run build
最佳实践
项目结构
- 关注点分离:保持路由、业务逻辑和数据访问分离
- 使用 TypeScript:添加类型安全性以早期捕获错误
- 模块化设计:创建可重用的模块和组件
- 清晰的命名:使用描述性的文件和目录名称
配置
- 环境变量:切勿将秘密提交到版本控制
- 验证:在启动时验证配置
- 默认值:为开发提供合理的默认值
- 文档:记录所有必需的环境变量
代码质量
- 代码检查:使用 ESLint/Pylint/golangci-lint
- 格式化:使用 Prettier/Black/gofmt
- 预提交钩子:在提交前强制执行质量检查
- 测试:从第一天起设置测试框架
开发工作流
- README:清楚地记录设置说明
- 脚本:为常见任务提供 npm/make 脚本
- CI/CD:设置自动化测试和部署
- Git 钩子:使用 husky 进行预提交检查
模板检查清单
## 项目设置检查清单
### 初始设置
- [ ] 项目目录已创建
- [ ] 包管理器已初始化 (npm, pip, go mod)
- [ ] Git 仓库已初始化
- [ ] .gitignore 已配置
- [ ] README.md 已创建
### 配置
- [ ] 代码检查已配置 (ESLint, Pylint 等)
- [ ] 格式化已配置 (Prettier, Black 等)
- [ ] TypeScript 已配置(如果适用)
- [ ] 测试框架已设置
- [ ] 环境变量已记录
### 开发工具
- [ ] 预提交钩子已安装
- [ ] VS Code 设置已配置
- [ ] 调试配置已添加
- [ ] 常见任务的脚本已添加
### CI/CD
- [ ] GitHub Actions 工作流已创建
- [ ] 构建管道已配置
- [ ] 测试自动化已设置
- [ ] 部署过程已记录
### 文档
- [ ] 设置说明已编写
- [ ] API 文档已开始
- [ ] 贡献指南已添加
- [ ] 许可证文件已添加
注意事项
- 始终以适当的项目结构开始
- 使用模板和生成器以节省时间
- 尽早配置工具以强制一致性
- 从一开始就记录所有内容
- 从第一天起使用版本控制
- 在项目中尽早设置 CI/CD
- 保持依赖项最新
- 遵循技术栈的社区惯例