project-scaffolder
About
The project-scaffolder skill automates project setup by generating complete directory structures, configuration files, and development environments based on your project type and stack. It handles best practices like linting, testing, and CI/CD pipeline configuration for you. Use this skill to quickly bootstrap new projects with production-ready foundations.
Documentation
Project Scaffolder Skill
Quick project setup with templates, best practices, and complete configuration for various frameworks and languages.
Instructions
You are a project scaffolding expert. When invoked:
-
Analyze Project Requirements:
- Identify project type (web app, API, CLI, library, etc.)
- Determine technology stack
- Understand target environment
- Assess team size and workflow needs
-
Generate Project Structure:
- Create appropriate directory structure
- Set up configuration files
- Initialize version control
- Configure package managers
- Add essential dependencies
-
Configure Development Environment:
- Set up linting and formatting
- Configure testing framework
- Add pre-commit hooks
- Create environment files
- Set up CI/CD pipeline basics
-
Provide Documentation:
- README with setup instructions
- Contributing guidelines
- Code of conduct (if needed)
- Development workflow documentation
- Architecture overview
Supported Project Types
- Frontend: React, Vue, Angular, Next.js, Svelte
- Backend: Node.js (Express, Fastify), Python (Django, FastAPI, Flask), Go, Rust
- Mobile: React Native, Flutter
- Desktop: Electron, Tauri
- CLI Tools: Node.js, Python, Go, Rust
- Libraries: NPM packages, Python packages, Go modules
- Full Stack: MERN, MEAN, JAMstack
- Monorepo: Turborepo, Nx, Lerna
Usage Examples
@project-scaffolder Create React + TypeScript app
@project-scaffolder --template express-api
@project-scaffolder --monorepo turborepo
@project-scaffolder --cli go
@project-scaffolder --library npm-package
Project Templates
React + TypeScript + Vite
# Initialize project
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
# Add essential dependencies
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
Directory Structure:
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:
{
"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
# Initialize project
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
Directory Structure:
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();
// Security middleware
app.use(helmet());
app.use(cors());
// Body parsing middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Routes
app.use('/api', routes);
// Health check
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Error handling
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:
{
"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 Project
# Create project directory
mkdir my-fastapi-app && cd my-fastapi-app
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install fastapi uvicorn pydantic python-dotenv
pip install pytest pytest-cov pytest-asyncio httpx
pip install black flake8 mypy isort
Directory Structure:
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=["*"],
)
# Include routers
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
DATABASE_URL: str = "sqlite:///./app.db"
# Security
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 Application
# Initialize Go module
mkdir my-cli && cd my-cli
go mod init github.com/username/my-cli
# Install dependencies
go get github.com/spf13/cobra@latest
go get github.com/spf13/viper@latest
Directory Structure:
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
Monorepo Setup (Turborepo)
# Create monorepo
npx create-turbo@latest my-monorepo
cd my-monorepo
Directory Structure:
my-monorepo/
├── apps/
│ ├── web/ # Next.js app
│ ├── api/ # Express API
│ └── docs/ # Documentation site
├── packages/
│ ├── ui/ # Shared UI components
│ ├── config/ # Shared configs (eslint, tsconfig)
│ ├── types/ # Shared TypeScript types
│ └── utils/ # Shared utilities
├── 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
}
}
}
Root 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"
}
}
Essential Configuration Files
.gitignore (Node.js)
# Dependencies
node_modules/
.pnp
.pnp.js
# Testing
coverage/
*.lcov
# Production
build/
dist/
# Environment
.env
.env.local
.env.*.local
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Logs
logs/
*.log
npm-debug.log*
.env.example
# Application
NODE_ENV=development
PORT=3000
APP_URL=http://localhost:3000
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
# Authentication
JWT_SECRET=your-secret-key-here
JWT_EXPIRE=7d
# API Keys
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
Best Practices
Project Structure
- Separate concerns: Keep routing, business logic, and data access separate
- Use TypeScript: Add type safety to catch errors early
- Modular design: Create reusable modules and components
- Clear naming: Use descriptive names for files and directories
Configuration
- Environment variables: Never commit secrets to version control
- Validation: Validate configuration on startup
- Defaults: Provide sensible defaults for development
- Documentation: Document all required environment variables
Code Quality
- Linting: Use ESLint/Pylint/golangci-lint
- Formatting: Use Prettier/Black/gofmt
- Pre-commit hooks: Enforce quality checks before commit
- Testing: Set up testing framework from day one
Development Workflow
- README: Document setup instructions clearly
- Scripts: Provide npm/make scripts for common tasks
- CI/CD: Set up automated testing and deployment
- Git hooks: Use husky for pre-commit checks
Template Checklist
## Project Setup Checklist
### Initial Setup
- [ ] Project directory created
- [ ] Package manager initialized (npm, pip, go mod)
- [ ] Git repository initialized
- [ ] .gitignore configured
- [ ] README.md created
### Configuration
- [ ] Linting configured (ESLint, Pylint, etc.)
- [ ] Formatting configured (Prettier, Black, etc.)
- [ ] TypeScript configured (if applicable)
- [ ] Testing framework set up
- [ ] Environment variables documented
### Development Tools
- [ ] Pre-commit hooks installed
- [ ] VS Code settings configured
- [ ] Debugging configuration added
- [ ] Scripts for common tasks added
### CI/CD
- [ ] GitHub Actions workflow created
- [ ] Build pipeline configured
- [ ] Test automation set up
- [ ] Deployment process documented
### Documentation
- [ ] Setup instructions written
- [ ] API documentation started
- [ ] Contributing guidelines added
- [ ] License file added
Notes
- Always start with a proper project structure
- Use templates and generators to save time
- Configure tooling early to enforce consistency
- Document everything from the beginning
- Use version control from day one
- Set up CI/CD early in the project
- Keep dependencies up to date
- Follow community conventions for the stack
Quick Install
/plugin add https://github.com/CuriousLearner/devkit/tree/main/project-scaffolderCopy and paste this command in Claude Code to install this skill
GitHub 仓库
Related Skills
langchain
MetaLangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.
Algorithmic Art Generation
MetaThis skill helps developers create algorithmic art using p5.js, focusing on generative art, computational aesthetics, and interactive visualizations. It automatically activates for topics like "generative art" or "p5.js visualization" and guides you through creating unique algorithms with features like seeded randomness, flow fields, and particle systems. Use it when you need to build reproducible, code-driven artistic patterns.
webapp-testing
TestingThis Claude Skill provides a Playwright-based toolkit for testing local web applications through Python scripts. It enables frontend verification, UI debugging, screenshot capture, and log viewing while managing server lifecycles. Use it for browser automation tasks but run scripts directly rather than reading their source code to avoid context pollution.
requesting-code-review
DesignThis skill dispatches a code-reviewer subagent to analyze code changes against requirements before proceeding. It should be used after completing tasks, implementing major features, or before merging to main. The review helps catch issues early by comparing the current implementation with the original plan.
