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/*"]
}