boilerplate
npx machina-cli add skill manastalukdar/claude-devstudio/boilerplate --openclawFramework Boilerplate Generator
I'll generate framework-specific boilerplate code following best practices and conventions for React, Vue, Next.js, Express, FastAPI, Django, and more.
Arguments: $ARGUMENTS - component/route/model name and type
Supported Frameworks:
- Frontend: React, Vue, Next.js, Angular, Svelte
- Backend: Express, Fastify, NestJS, FastAPI, Django
- Full-stack: Next.js, Remix, SvelteKit
Token Optimization
This skill uses multiple optimization strategies to minimize token usage while maintaining comprehensive boilerplate generation:
1. Framework Detection Caching (400 token savings)
Pattern: Cache framework detection results to avoid repeated file system checks
# Cache file: .boilerplate-framework.cache
# Format: framework_name
# TTL: 24 hours (framework rarely changes)
if [ -f ".boilerplate-framework.cache" ] && [ $(($(date +%s) - $(stat -c %Y .boilerplate-framework.cache))) -lt 86400 ]; then
FRAMEWORK=$(cat .boilerplate-framework.cache)
# 20 tokens vs 420 tokens for full detection
else
FRAMEWORK=$(detect_framework) # Full detection (420 tokens)
echo "$FRAMEWORK" > .boilerplate-framework.cache
fi
Savings:
- Cached: ~20 tokens (read cache file)
- Uncached: ~420 tokens (package.json/requirements.txt checks, multiple Grep operations)
- 400 token savings (95%) for subsequent runs
2. Template Library Approach (2,500 token savings)
Pattern: Use comprehensive pre-defined templates instead of LLM-generated code
# Instead of: LLM-generated boilerplate (3,000+ tokens)
# Use: Template library (500 tokens)
# Template files stored in skill
TEMPLATE_DIR="templates/$FRAMEWORK"
generate_component() {
local component_name="$1"
local template_file="$TEMPLATE_DIR/component.template.tsx"
# Simple variable substitution (100 tokens)
sed "s/\${COMPONENT_NAME}/$component_name/g" "$template_file"
}
Savings:
- Template-based: ~500 tokens (file read + substitution)
- LLM-generated: ~3,000 tokens (full code generation with analysis)
- 2,500 token savings (83%) per component
3. Grep-Based Configuration Detection (300 token savings)
Pattern: Use Grep to detect project configuration instead of reading files
# Instead of: Read package.json/requirements.txt fully (500 tokens)
# Use: Grep for specific patterns (200 tokens)
# Detect React
HAS_REACT=$(grep -q "\"react\":" package.json && echo "true" || echo "false")
# Detect TypeScript
HAS_TS=$(grep -q "\"typescript\":" package.json && echo "true" || echo "false")
# Detect testing framework
HAS_JEST=$(grep -q "\"jest\":" package.json && echo "true" || echo "false")
Savings:
- Grep approach: ~200 tokens (pattern matching)
- Full file read: ~500 tokens (read and parse JSON)
- 300 token savings (60%)
4. Incremental Scaffolding (1,200 token savings)
Pattern: Generate only requested component type, not entire feature
# Instead of: Full feature scaffolding (4,000+ tokens)
# - Component + styles + tests + stories + types
# Generate: Only component (800 tokens)
case $COMPONENT_TYPE in
component)
generate_component "$COMPONENT_NAME" # 800 tokens
;;
route)
generate_route "$COMPONENT_NAME" # 900 tokens
;;
full)
generate_component "$COMPONENT_NAME"
generate_styles "$COMPONENT_NAME"
generate_tests "$COMPONENT_NAME"
generate_types "$COMPONENT_NAME" # 4,000 tokens
;;
esac
Savings:
- Component only: ~800 tokens
- Full feature: ~4,000 tokens
- 1,200 token savings (75%) when generating single component
5. Early Exit for Existing Components (90% savings)
Pattern: Check if component already exists before generating
# Quick check: Does component exist?
case $FRAMEWORK in
react)
component_path="src/components/${COMPONENT_NAME}/${COMPONENT_NAME}.tsx"
;;
nextjs)
component_path="app/${COMPONENT_NAME}/page.tsx"
;;
esac
if [ -f "$component_path" ]; then
echo "⚠️ Component $COMPONENT_NAME already exists at $component_path"
read -p "Overwrite? (y/n): " confirm
if [ "$confirm" != "y" ]; then
echo "✓ Keeping existing component"
exit 0 # 200 tokens total
fi
fi
# Otherwise: Full generation (3,500+ tokens)
Savings:
- Existing component: ~200 tokens (early exit)
- Full generation: ~3,500+ tokens
- 3,300+ token savings (94%) when component exists
6. Framework-Specific Template Caching (800 token savings)
Pattern: Cache loaded templates per framework
# Cache file: .boilerplate-templates-${FRAMEWORK}.cache
# Contains pre-loaded templates for the framework
# TTL: 24 hours
load_templates() {
local cache_file=".boilerplate-templates-${FRAMEWORK}.cache"
if [ -f "$cache_file" ]; then
source "$cache_file" # 150 tokens
return
fi
# Load all templates for framework (950 tokens)
case $FRAMEWORK in
react)
TEMPLATE_COMPONENT=$(cat templates/react/component.tsx)
TEMPLATE_TEST=$(cat templates/react/test.tsx)
TEMPLATE_STYLES=$(cat templates/react/styles.css)
;;
nextjs)
TEMPLATE_PAGE=$(cat templates/nextjs/page.tsx)
TEMPLATE_API=$(cat templates/nextjs/api-route.ts)
;;
esac
declare -p TEMPLATE_* > "$cache_file"
}
Savings:
- Cached templates: ~150 tokens
- Load templates: ~950 tokens (multiple file reads)
- 800 token savings (84%) for subsequent runs
7. Component Inventory Tracking (400 token savings)
Pattern: Track generated components to avoid duplicates
# Cache file: .boilerplate-generated.cache
# Format: framework:component_type:component_name:file_path
# TTL: Session-based (cleared manually)
is_component_generated() {
local component_name="$1"
local component_type="$2"
grep -q "^$FRAMEWORK:$component_type:$component_name:" .boilerplate-generated.cache 2>/dev/null
}
# Track generated components
if ! is_component_generated "$COMPONENT_NAME" "$COMPONENT_TYPE"; then
generate_boilerplate
echo "$FRAMEWORK:$COMPONENT_TYPE:$COMPONENT_NAME:$component_path" >> .boilerplate-generated.cache
else
echo " ✓ $COMPONENT_NAME already generated"
fi
Savings:
- Skip duplicate: ~50 tokens (cache check)
- Generate new: ~450 tokens (template processing)
- 400 token savings (89%) for duplicate prevention
8. Test File Generation Optimization (600 token savings)
Pattern: Generate minimal test boilerplate with placeholders
# Instead of: Comprehensive test suite (1,200 tokens)
# Use: Minimal test template with TODOs (600 tokens)
generate_minimal_test() {
local component_name="$1"
cat <<EOF
import { render, screen } from '@testing-library/react';
import { ${component_name} } from './${component_name}';
describe('${component_name}', () => {
it('renders without crashing', () => {
render(<${component_name} />);
});
// TODO: Add more tests
});
EOF
}
Savings:
- Minimal test: ~200 tokens (basic structure)
- Comprehensive test: ~800 tokens (multiple test cases)
- 600 token savings (75%)
- Users can expand tests as needed
9. Real-World Token Usage Distribution
Typical Scenarios:
-
First Run - Single Component (2,000-3,000 tokens)
- Framework detection: 420 tokens
- Load templates: 950 tokens
- Generate component: 800 tokens
- Generate test: 200 tokens
- Generate styles: 150 tokens
- Total: ~2,520 tokens
-
Subsequent Run - Same Framework (800-1,500 tokens)
- Framework detection (cached): 20 tokens
- Load templates (cached): 150 tokens
- Generate component: 800 tokens
- Generate test: 200 tokens
- Total: ~1,170 tokens
-
Component Exists (150-250 tokens)
- Framework detection (cached): 20 tokens
- Check existing: 100 tokens
- Early exit: 50 tokens
- Total: ~170 tokens
-
Full Feature Scaffold (4,000-6,000 tokens)
- Framework detection: 420 tokens
- Load templates: 950 tokens
- Generate component: 800 tokens
- Generate test: 800 tokens
- Generate styles: 150 tokens
- Generate types: 400 tokens
- Generate story: 300 tokens
- Total: ~3,820 tokens
-
API Route Only (600-1,000 tokens)
- Framework detection (cached): 20 tokens
- Load API template: 150 tokens
- Generate route: 600 tokens
- Total: ~770 tokens
Expected Token Savings:
- Average 53% reduction from baseline (3,000 → 1,400 tokens)
- 94% reduction when component already exists
- Aggregate savings: 1,500-2,000 tokens per boilerplate generation
Optimization Summary
| Strategy | Savings | When Applied |
|---|---|---|
| Framework detection caching | 400 tokens (95%) | Subsequent runs |
| Template library approach | 2,500 tokens (83%) | Always |
| Grep-based config detection | 300 tokens (60%) | Always |
| Incremental scaffolding | 1,200 tokens (75%) | Component-only generation |
| Early exit for existing | 3,300 tokens (94%) | Component exists |
| Template caching | 800 tokens (84%) | Subsequent runs |
| Component inventory | 400 tokens (89%) | Duplicate prevention |
| Minimal test generation | 600 tokens (75%) | Test files |
Key Insight: The template library approach combined with framework caching provides 50-60% token reduction while maintaining production-ready boilerplate quality. Early exit patterns provide 94% savings when components already exist.
Phase 1: Framework Detection
#!/bin/bash
# Detect project framework
echo "=== Detecting Framework ==="
echo ""
detect_framework() {
if [ -f "package.json" ]; then
if grep -q "\"react\"" package.json; then
if grep -q "\"next\"" package.json; then
echo "nextjs"
else
echo "react"
fi
elif grep -q "\"vue\"" package.json; then
echo "vue"
elif grep -q "\"@angular/core\"" package.json; then
echo "angular"
elif grep -q "\"svelte\"" package.json; then
echo "svelte"
elif grep -q "\"express\"" package.json; then
echo "express"
elif grep -q "\"fastify\"" package.json; then
echo "fastify"
elif grep -q "\"@nestjs/core\"" package.json; then
echo "nestjs"
fi
elif [ -f "requirements.txt" ]; then
if grep -q "fastapi" requirements.txt; then
echo "fastapi"
elif grep -q "django" requirements.txt; then
echo "django"
elif grep -q "flask" requirements.txt; then
echo "flask"
fi
fi
}
FRAMEWORK=$(detect_framework)
if [ -z "$FRAMEWORK" ]; then
echo "❌ No supported framework detected"
echo ""
echo "Supported frameworks:"
echo " Frontend: React, Vue, Next.js, Angular, Svelte"
echo " Backend: Express, Fastify, NestJS, FastAPI, Django, Flask"
exit 1
fi
echo "✓ Detected framework: $FRAMEWORK"
# Parse arguments
COMPONENT_NAME="${1:-MyComponent}"
COMPONENT_TYPE="${2:-component}"
echo " Name: $COMPONENT_NAME"
echo " Type: $COMPONENT_TYPE"
Phase 2: React Component Boilerplate
// React component with TypeScript
import React, { useState, useEffect } from 'react';
import styles from './${COMPONENT_NAME}.module.css';
/**
* Props for ${COMPONENT_NAME} component
*/
interface ${COMPONENT_NAME}Props {
/**
* Component title
*/
title?: string;
/**
* Additional CSS classes
*/
className?: string;
/**
* Event handler when component is clicked
*/
onClick?: () => void;
}
/**
* ${COMPONENT_NAME} component
*
* @example
* ```tsx
* <${COMPONENT_NAME} title="Hello" onClick={() => console.log('clicked')} />
* ```
*/
export const ${COMPONENT_NAME}: React.FC<${COMPONENT_NAME}Props> = ({
title = 'Default Title',
className,
onClick,
}) => {
const [count, setCount] = useState(0);
useEffect(() => {
// Component mounted
console.log('${COMPONENT_NAME} mounted');
return () => {
// Component unmounted
console.log('${COMPONENT_NAME} unmounted');
};
}, []);
const handleClick = () => {
setCount((prev) => prev + 1);
onClick?.();
};
return (
<div className={`${styles.container} ${className || ''}`}>
<h2>{title}</h2>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
};
export default ${COMPONENT_NAME};
/* ${COMPONENT_NAME}.module.css */
.container {
padding: 1rem;
border: 1px solid #ddd;
border-radius: 8px;
}
.container h2 {
margin: 0 0 1rem 0;
font-size: 1.5rem;
}
.container button {
padding: 0.5rem 1rem;
background-color: #0070f3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.container button:hover {
background-color: #0051cc;
}
// ${COMPONENT_NAME}.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { ${COMPONENT_NAME} } from './${COMPONENT_NAME}';
describe('${COMPONENT_NAME}', () => {
it('renders with default props', () => {
render(<${COMPONENT_NAME} />);
expect(screen.getByText('Default Title')).toBeInTheDocument();
});
it('renders with custom title', () => {
render(<${COMPONENT_NAME} title="Custom Title" />);
expect(screen.getByText('Custom Title')).toBeInTheDocument();
});
it('increments count on button click', () => {
render(<${COMPONENT_NAME} />);
const button = screen.getByRole('button', { name: /increment/i });
expect(screen.getByText('Count: 0')).toBeInTheDocument();
fireEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
it('calls onClick handler when clicked', () => {
const handleClick = jest.fn();
render(<${COMPONENT_NAME} onClick={handleClick} />);
const button = screen.getByRole('button', { name: /increment/i });
fireEvent.click(button);
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
Phase 3: Next.js Page/Route Boilerplate
// Next.js App Router page
import { Metadata } from 'next';
import { ${COMPONENT_NAME} } from '@/components/${COMPONENT_NAME}';
/**
* Page metadata
*/
export const metadata: Metadata = {
title: '${COMPONENT_NAME}',
description: '${COMPONENT_NAME} page description',
};
/**
* ${COMPONENT_NAME} page component
*/
export default async function ${COMPONENT_NAME}Page() {
// Server-side data fetching
const data = await fetchData();
return (
<div>
<h1>${COMPONENT_NAME}</h1>
<${COMPONENT_NAME} data={data} />
</div>
);
}
/**
* Fetch data on the server
*/
async function fetchData() {
// Fetch data from API or database
const res = await fetch('https://api.example.com/data', {
next: { revalidate: 3600 }, // Revalidate every hour
});
if (!res.ok) {
throw new Error('Failed to fetch data');
}
return res.json();
}
// Next.js API Route
import { NextRequest, NextResponse } from 'next/server';
/**
* GET /api/${COMPONENT_NAME}
*/
export async function GET(request: NextRequest) {
try {
// Get query parameters
const searchParams = request.nextUrl.searchParams;
const id = searchParams.get('id');
// Fetch data
const data = await fetchData(id);
return NextResponse.json({
success: true,
data,
});
} catch (error) {
console.error('${COMPONENT_NAME} GET error:', error);
return NextResponse.json(
{ success: false, error: 'Internal server error' },
{ status: 500 }
);
}
}
/**
* POST /api/${COMPONENT_NAME}
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json();
// Validate request body
if (!body.name) {
return NextResponse.json(
{ success: false, error: 'Name is required' },
{ status: 400 }
);
}
// Process data
const result = await createData(body);
return NextResponse.json({
success: true,
data: result,
}, { status: 201 });
} catch (error) {
console.error('${COMPONENT_NAME} POST error:', error);
return NextResponse.json(
{ success: false, error: 'Internal server error' },
{ status: 500 }
);
}
}
Phase 4: Express Route Boilerplate
// Express route handler
import { Router, Request, Response, NextFunction } from 'express';
import { body, param, validationResult } from 'express-validator';
const router = Router();
/**
* ${COMPONENT_NAME} interface
*/
interface ${COMPONENT_NAME} {
id: string;
name: string;
createdAt: Date;
}
/**
* GET /api/${COMPONENT_NAME}
* List all ${COMPONENT_NAME}s
*/
router.get(
'/',
async (req: Request, res: Response, next: NextFunction) => {
try {
const { page = 1, limit = 10, search } = req.query;
// Fetch data from database
const items = await db.${COMPONENT_NAME}.findMany({
where: search ? { name: { contains: search as string } } : {},
skip: (Number(page) - 1) * Number(limit),
take: Number(limit),
});
const total = await db.${COMPONENT_NAME}.count();
res.json({
data: items,
pagination: {
page: Number(page),
limit: Number(limit),
total,
totalPages: Math.ceil(total / Number(limit)),
},
});
} catch (error) {
next(error);
}
}
);
/**
* GET /api/${COMPONENT_NAME}/:id
* Get ${COMPONENT_NAME} by ID
*/
router.get(
'/:id',
param('id').isUUID(),
async (req: Request, res: Response, next: NextFunction) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const item = await db.${COMPONENT_NAME}.findUnique({
where: { id: req.params.id },
});
if (!item) {
return res.status(404).json({ error: '${COMPONENT_NAME} not found' });
}
res.json({ data: item });
} catch (error) {
next(error);
}
}
);
/**
* POST /api/${COMPONENT_NAME}
* Create new ${COMPONENT_NAME}
*/
router.post(
'/',
body('name').isString().trim().isLength({ min: 1, max: 255 }),
async (req: Request, res: Response, next: NextFunction) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const item = await db.${COMPONENT_NAME}.create({
data: {
name: req.body.name,
},
});
res.status(201).json({ data: item });
} catch (error) {
next(error);
}
}
);
/**
* PUT /api/${COMPONENT_NAME}/:id
* Update ${COMPONENT_NAME}
*/
router.put(
'/:id',
param('id').isUUID(),
body('name').isString().trim().isLength({ min: 1, max: 255 }),
async (req: Request, res: Response, next: NextFunction) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const item = await db.${COMPONENT_NAME}.update({
where: { id: req.params.id },
data: { name: req.body.name },
});
res.json({ data: item });
} catch (error) {
next(error);
}
}
);
/**
* DELETE /api/${COMPONENT_NAME}/:id
* Delete ${COMPONENT_NAME}
*/
router.delete(
'/:id',
param('id').isUUID(),
async (req: Request, res: Response, next: NextFunction) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
await db.${COMPONENT_NAME}.delete({
where: { id: req.params.id },
});
res.status(204).send();
} catch (error) {
next(error);
}
}
);
export default router;
Phase 5: FastAPI Route Boilerplate
# FastAPI route handler
from fastapi import APIRouter, HTTPException, Query, Path
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
import uuid
router = APIRouter(
prefix="/api/${COMPONENT_NAME}",
tags=["${COMPONENT_NAME}"],
)
class ${COMPONENT_NAME}Base(BaseModel):
"""Base ${COMPONENT_NAME} schema"""
name: str = Field(..., min_length=1, max_length=255)
class ${COMPONENT_NAME}Create(${COMPONENT_NAME}Base):
"""Schema for creating ${COMPONENT_NAME}"""
pass
class ${COMPONENT_NAME}Update(${COMPONENT_NAME}Base):
"""Schema for updating ${COMPONENT_NAME}"""
name: Optional[str] = Field(None, min_length=1, max_length=255)
class ${COMPONENT_NAME}InDB(${COMPONENT_NAME}Base):
"""Schema for ${COMPONENT_NAME} in database"""
id: str
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class PaginatedResponse(BaseModel):
"""Paginated response schema"""
data: List[${COMPONENT_NAME}InDB]
total: int
page: int
page_size: int
total_pages: int
@router.get("/", response_model=PaginatedResponse)
async def list_${COMPONENT_NAME}s(
page: int = Query(1, ge=1),
page_size: int = Query(10, ge=1, le=100),
search: Optional[str] = None,
):
"""
List all ${COMPONENT_NAME}s with pagination
Args:
page: Page number (default: 1)
page_size: Items per page (default: 10, max: 100)
search: Optional search query
Returns:
Paginated list of ${COMPONENT_NAME}s
"""
try:
# Query database
skip = (page - 1) * page_size
query = db.query(${COMPONENT_NAME})
if search:
query = query.filter(${COMPONENT_NAME}.name.contains(search))
total = query.count()
items = query.offset(skip).limit(page_size).all()
return PaginatedResponse(
data=items,
total=total,
page=page,
page_size=page_size,
total_pages=(total + page_size - 1) // page_size,
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/{id}", response_model=${COMPONENT_NAME}InDB)
async def get_${COMPONENT_NAME}(
id: str = Path(..., description="${COMPONENT_NAME} ID"),
):
"""
Get ${COMPONENT_NAME} by ID
Args:
id: ${COMPONENT_NAME} unique identifier
Returns:
${COMPONENT_NAME} object
Raises:
HTTPException: 404 if ${COMPONENT_NAME} not found
"""
item = db.query(${COMPONENT_NAME}).filter(${COMPONENT_NAME}.id == id).first()
if not item:
raise HTTPException(status_code=404, detail="${COMPONENT_NAME} not found")
return item
@router.post("/", response_model=${COMPONENT_NAME}InDB, status_code=201)
async def create_${COMPONENT_NAME}(
data: ${COMPONENT_NAME}Create,
):
"""
Create new ${COMPONENT_NAME}
Args:
data: ${COMPONENT_NAME} creation data
Returns:
Created ${COMPONENT_NAME} object
"""
try:
item = ${COMPONENT_NAME}(
id=str(uuid.uuid4()),
name=data.name,
created_at=datetime.utcnow(),
updated_at=datetime.utcnow(),
)
db.add(item)
db.commit()
db.refresh(item)
return item
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=str(e))
@router.put("/{id}", response_model=${COMPONENT_NAME}InDB)
async def update_${COMPONENT_NAME}(
id: str = Path(..., description="${COMPONENT_NAME} ID"),
data: ${COMPONENT_NAME}Update = None,
):
"""
Update ${COMPONENT_NAME}
Args:
id: ${COMPONENT_NAME} unique identifier
data: Update data
Returns:
Updated ${COMPONENT_NAME} object
Raises:
HTTPException: 404 if ${COMPONENT_NAME} not found
"""
item = db.query(${COMPONENT_NAME}).filter(${COMPONENT_NAME}.id == id).first()
if not item:
raise HTTPException(status_code=404, detail="${COMPONENT_NAME} not found")
update_data = data.dict(exclude_unset=True)
for key, value in update_data.items():
setattr(item, key, value)
item.updated_at = datetime.utcnow()
db.commit()
db.refresh(item)
return item
@router.delete("/{id}", status_code=204)
async def delete_${COMPONENT_NAME}(
id: str = Path(..., description="${COMPONENT_NAME} ID"),
):
"""
Delete ${COMPONENT_NAME}
Args:
id: ${COMPONENT_NAME} unique identifier
Raises:
HTTPException: 404 if ${COMPONENT_NAME} not found
"""
item = db.query(${COMPONENT_NAME}).filter(${COMPONENT_NAME}.id == id).first()
if not item:
raise HTTPException(status_code=404, detail="${COMPONENT_NAME} not found")
db.delete(item)
db.commit()
return None
Summary
echo ""
echo "=== ✓ Boilerplate Generation Complete ==="
echo ""
echo "📁 Generated files for $FRAMEWORK:"
case $FRAMEWORK in
react)
echo " - src/components/${COMPONENT_NAME}/${COMPONENT_NAME}.tsx"
echo " - src/components/${COMPONENT_NAME}/${COMPONENT_NAME}.module.css"
echo " - src/components/${COMPONENT_NAME}/${COMPONENT_NAME}.test.tsx"
;;
nextjs)
echo " - app/${COMPONENT_NAME}/page.tsx"
echo " - app/api/${COMPONENT_NAME}/route.ts"
;;
express)
echo " - src/routes/${COMPONENT_NAME}.routes.ts"
echo " - src/controllers/${COMPONENT_NAME}.controller.ts"
;;
fastapi)
echo " - app/routes/${COMPONENT_NAME}.py"
echo " - app/schemas/${COMPONENT_NAME}.py"
;;
esac
echo ""
echo "✓ Includes:"
echo " - TypeScript/type definitions"
echo " - Input validation"
echo " - Error handling"
echo " - JSDoc/docstrings"
echo " - Unit tests"
echo ""
echo "🚀 Next steps:"
echo " 1. Review and customize generated code"
echo " 2. Update business logic"
echo " 3. Add database integration"
echo " 4. Run tests: npm test"
Best Practices
Code Quality:
- Follow framework conventions
- Include comprehensive types
- Add proper error handling
- Write meaningful documentation
Integration Points:
/test- Generate tests for boilerplate/scaffold- Complete feature scaffolding/inline-docs- Add documentation
What I'll Actually Do
- Detect framework - Identify project type
- Parse arguments - Component name and type
- Generate boilerplate - Framework-specific code
- Include tests - Unit/integration tests
- Add documentation - JSDoc/docstrings
- Follow conventions - Framework best practices
Important: I will NEVER add AI attribution.
Credits: Boilerplate patterns based on Create React App, Next.js, Express.js, FastAPI, and framework documentation best practices.
Source
git clone https://github.com/manastalukdar/claude-devstudio/blob/main/skills/boilerplate/SKILL.mdView on GitHub Overview
Generates framework-specific boilerplate code for frontend, backend, and full-stack projects. Supports React, Vue, Next.js, Angular, Svelte, Express, FastAPI, Django, and more, using optimized templates and caching to speed up scaffolding.
How This Skill Works
On invocation, the tool detects the target framework (with a caching mechanism to avoid repeated filesystem checks), selects a pre-defined template from a library, and substitutes the component/route/model name provided in ARGUMENTS. It also supports incremental scaffolding to generate only the requested piece and uses lightweight grep-based configuration detection to minimize token usage.
When to Use It
- Bootstrapping a new frontend component or page (React, Vue, Next.js, Angular, Svelte).
- Scaffolding a backend API route or service (Express, FastAPI, Django, Fastify, NestJS).
- Generating a full-stack feature in Next.js, Remix, or SvelteKit.
- Adding a model, route, or controller in a Django, FastAPI, or NestJS project.
- Starting a template-driven project and aligning with project conventions.
Quick Start
- Step 1: Provide ARGUMENTS with the component/route/model name and type.
- Step 2: Run the boilerplate generator for your target framework.
- Step 3: Integrate the generated boilerplate into your project and run tests.
Best Practices
- Always pass the exact name and type via ARGUMENTS to ensure correct scaffolding.
- Prefer the Template Library approach to minimize token usage and ensure consistency.
- Enable framework detection caching to speed up subsequent runs.
- Use incremental scaffolding to generate only the requested component rather than a full feature.
- Run basic linting and type checks on the generated boilerplate before integration.
Example Use Cases
- Generate a React 'Header' component with a TSX scaffold.
- Create an Express 'users' API route with CRUD setup.
- Bootstrap a Next.js 'dashboard' page with routing and basic styles.
- Scaffold a FastAPI 'items' router with Pydantic models.
- Set up a Django 'Blog' app with models and admin configuration.