Awesome-omni-skill scaffolder
Generates boilerplate code following loaded rules. Creates new components, modules, APIs, and features that automatically comply with your coding standards. Extracts patterns from rules and applies them consistently.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/scaffolder" ~/.claude/skills/diegosouzapw-awesome-omni-skill-scaffolder-f39d9e && rm -rf "$T"
skills/development/scaffolder/SKILL.mdStep 1: Load Rule Index
Load the rule index to discover relevant rules dynamically:
- @.claude/context/rule-index.json
Step 2: Identify Target Framework and Query Index
Determine which technologies apply based on what you're scaffolding:
Component scaffolding:
- Detect: React, Next.js, TypeScript
- Query:
,index.technology_map['react']
,index.technology_map['nextjs']index.technology_map['typescript']
API Route scaffolding:
- Detect: Next.js App Router or FastAPI
- Query:
orindex.technology_map['nextjs']index.technology_map['fastapi']
Test File scaffolding:
- Detect: Jest, Cypress, Playwright, Vitest, pytest
- Query:
,index.technology_map['jest']
, etc.index.technology_map['cypress']
Database Model scaffolding:
- Detect: Prisma, SQL, database patterns
- Query:
or database-related rulesindex.technology_map['prisma']
Step 3: Load Relevant Rules
Load only the relevant rule files from the index (progressive disclosure):
- Master rules first (from
).claude/rules-master/ - Archive rules supplement (from
).claude/archive/ - Load 3-5 most relevant rules, not all 1,081
Step 4: Extract Patterns from Rules
Parse the loaded rule files to extract scaffolding patterns:
From Next.js rules (TECH_STACK_NEXTJS.md or nextjs.mdc):
- Server Components by default
- 'use client' only when needed
- Place in
for routes,app/
for sharedcomponents/ - Use lowercase-with-dashes for directories
From TypeScript rules:
- Interfaces for object shapes
- Proper return type annotations
- Avoid
, useanyunknown - PascalCase for types/interfaces
From React rules:
- Functional components only
- Custom hooks for reusable logic
- Props interface for each component
- Error boundaries for critical sections
Step 5: Generate Compliant Code
Apply extracted patterns to generate code that passes rule-auditor. </execution_process>
<best_practices>
- Always Audit After: Run
after scaffolding to catch any edge cases/audit - Customize Templates: Add project-specific patterns to rules for consistent generation
- Use for Consistency: Scaffold even simple files to maintain team conventions
- Review Generated Code: Scaffolded code is a starting point, not final implementation
- Keep Rules Updated: As patterns evolve, update rules so scaffolder stays current </best_practices>
1. User: /scaffold component UserDashboard 2. Scaffolder reads: nextjs.mdc, typescript.mdc, react.mdc 3. Extracts patterns: Server Component, Suspense, interfaces 4. Generates compliant code structure 5. Writes files to correct locations 6. Runs rule-auditor to verify compliance 7. Reports any manual adjustments needed
Feature Module Generation
For larger features, scaffold generates a complete module:
</integration> </instructions> <examples> <code_example> **Next.js Server Component**/scaffold feature user-management Generates: app/ └── (dashboard)/ └── users/ ├── page.tsx # List page ├── [id]/ │ └── page.tsx # Detail page ├── new/ │ └── page.tsx # Create page └── components/ ├── user-list.tsx ├── user-card.tsx └── user-form.tsx components/ └── users/ └── ... (shared components) lib/ └── users/ ├── api.ts # API functions ├── types.ts # Type definitions └── validations.ts # Zod schemas
Command:
/scaffold component UserProfile
Generated:
components/user-profile/index.tsx
// Server Component (default per nextjs.mdc) // Location: components/user-profile/ (lowercase-with-dashes per nextjs.mdc) import { Suspense } from 'react' import { UserProfileSkeleton } from './skeleton' import { UserProfileContent } from './content' // Interface defined (per typescript.mdc) interface UserProfileProps { userId: string showDetails?: boolean } // Async Server Component for data fetching (per nextjs.mdc > Data Fetching) export async function UserProfile({ userId, showDetails = false }: UserProfileProps) { return ( // Suspense boundary (per nextjs.mdc > Components) <Suspense fallback={<UserProfileSkeleton />}> <UserProfileContent userId={userId} showDetails={showDetails} /> </Suspense> ) } // Default export for dynamic imports (per nextjs.mdc) export default UserProfile
Also generates:
- Async content componentcomponents/user-profile/content.tsx
- Loading skeletoncomponents/user-profile/skeleton.tsx
- Shared typescomponents/user-profile/types.ts
- Barrel export </code_example>components/user-profile/index.ts
<code_example> Next.js Client Component
Command:
/scaffold client-component SearchBar
Generated:
components/search-bar/index.tsx
'use client' // Required for useState (per nextjs.mdc > Components) import { useState, useCallback } from 'react' import { useDebounce } from '@/hooks/use-debounce' // Props interface (per typescript.mdc) interface SearchBarProps { onSearch: (query: string) => void placeholder?: string debounceMs?: number } // Functional component (per react.mdc) export function SearchBar({ onSearch, placeholder = 'Search...', debounceMs = 300, }: SearchBarProps) { // Minimal client state (per nextjs.mdc > State Management) const [query, setQuery] = useState('') // Debounced callback (per nextjs.mdc > Performance) const debouncedSearch = useDebounce(onSearch, debounceMs) const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { const value = e.target.value setQuery(value) debouncedSearch(value) }, [debouncedSearch]) return ( <input type="search" value={query} onChange={handleChange} placeholder={placeholder} className="w-full px-4 py-2 border rounded-lg" // Tailwind (per tailwind.mdc) aria-label={placeholder} // Accessibility /> ) } export default SearchBar
</code_example>
<code_example> Next.js API Route (App Router)
Command:
/scaffold api users
Generated:
app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server' import { z } from 'zod' // Zod for validation (per nextjs.mdc > Forms and Validation) // Request schema (per typescript.mdc > Type System) const CreateUserSchema = z.object({ email: z.string().email(), name: z.string().min(2), }) // Response type (per typescript.mdc) interface UserResponse { id: string email: string name: string createdAt: string } // GET handler (per nextjs.mdc > Routing) export async function GET(request: NextRequest) { try { const { searchParams } = new URL(request.url) const page = parseInt(searchParams.get('page') ?? '1') const limit = parseInt(searchParams.get('limit') ?? '10') // TODO: Replace with actual database query const users: UserResponse[] = [] return NextResponse.json({ data: users, pagination: { page, limit, total: 0 }, }) } catch (error) { // Proper error handling (per nextjs.mdc > Data Fetching) console.error('Failed to fetch users:', error) return NextResponse.json( { error: 'Failed to fetch users' }, { status: 500 } ) } } // POST handler with validation export async function POST(request: NextRequest) { try { const body = await request.json() // Server-side validation (per nextjs.mdc > Forms and Validation) const validated = CreateUserSchema.parse(body) // TODO: Replace with actual database insert const user: UserResponse = { id: crypto.randomUUID(), ...validated, createdAt: new Date().toISOString(), } return NextResponse.json({ data: user }, { status: 201 }) } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( { error: 'Validation failed', details: error.errors }, { status: 400 } ) } console.error('Failed to create user:', error) return NextResponse.json( { error: 'Failed to create user' }, { status: 500 } ) } }
</code_example>
<code_example> FastAPI Endpoint
Command:
/scaffold fastapi-route users
Generated:
app/routers/users.py
"""User management endpoints.""" # Type hints required (per python.mdc) from typing import Annotated from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, Query, status from pydantic import BaseModel, EmailStr, Field # Router with tags (per fastapi.mdc > API Design) router = APIRouter(prefix="/users", tags=["users"]) # Pydantic models (per fastapi.mdc > Components and Validation) class UserCreate(BaseModel): """Schema for creating a user.""" email: EmailStr name: str = Field(..., min_length=2, max_length=100) class UserResponse(BaseModel): """Schema for user response.""" id: UUID email: EmailStr name: str created_at: str class Config: from_attributes = True class PaginatedResponse(BaseModel): """Paginated response wrapper.""" data: list[UserResponse] total: int page: int limit: int # Dependency injection (per fastapi.mdc > Dependency Injection) async def get_db(): """Database session dependency.""" # TODO: Replace with actual database session yield None # GET endpoint with pagination (per fastapi.mdc > Performance) @router.get("", response_model=PaginatedResponse) async def list_users( db: Annotated[None, Depends(get_db)], page: Annotated[int, Query(ge=1)] = 1, limit: Annotated[int, Query(ge=1, le=100)] = 10, ) -> PaginatedResponse: """ List all users with pagination. - **page**: Page number (starting from 1) - **limit**: Items per page (max 100) """ # TODO: Replace with actual database query users: list[UserResponse] = [] total = 0 return PaginatedResponse(data=users, total=total, page=page, limit=limit) # POST endpoint with validation @router.post("", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def create_user( user_data: UserCreate, db: Annotated[None, Depends(get_db)], ) -> UserResponse: """ Create a new user. - **email**: Valid email address - **name**: User's display name (2-100 chars) """ # TODO: Replace with actual database insert # Check for existing user, create, return raise HTTPException( status_code=status.HTTP_501_NOT_IMPLEMENTED, detail="Database integration pending", ) # GET by ID endpoint @router.get("/{user_id}", response_model=UserResponse) async def get_user( user_id: UUID, db: Annotated[None, Depends(get_db)], ) -> UserResponse: """Get a specific user by ID.""" # TODO: Replace with actual database query raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"User {user_id} not found", )
</code_example>
<code_example> Test File (Vitest/Jest)
Command:
/scaffold test components/user-profile
Generated:
components/user-profile/__tests__/index.test.tsx
// Test file (per jest-*.mdc / vitest-*.mdc patterns) import { render, screen, waitFor } from '@testing-library/react' import { describe, it, expect, vi, beforeEach } from 'vitest' import { UserProfile } from '../index' // Mock external dependencies (per testing best practices) vi.mock('@/lib/api', () => ({ fetchUser: vi.fn(), })) describe('UserProfile', () => { // Clear mocks before each test (per clean-code.mdc) beforeEach(() => { vi.clearAllMocks() }) // Descriptive test names (per testing guidelines) it('renders loading skeleton initially', () => { render(<UserProfile userId="123" />) expect(screen.getByTestId('user-profile-skeleton')).toBeInTheDocument() }) it('displays user information after loading', async () => { const mockUser = { id: '123', name: 'John Doe', email: 'john@example.com', } const { fetchUser } = await import('@/lib/api') vi.mocked(fetchUser).mockResolvedValue(mockUser) render(<UserProfile userId="123" />) await waitFor(() => { expect(screen.getByText('John Doe')).toBeInTheDocument() expect(screen.getByText('john@example.com')).toBeInTheDocument() }) }) it('handles error state gracefully', async () => { const { fetchUser } = await import('@/lib/api') vi.mocked(fetchUser).mockRejectedValue(new Error('Network error')) render(<UserProfile userId="123" />) await waitFor(() => { expect(screen.getByText(/failed to load/i)).toBeInTheDocument() }) }) // Edge cases (per qa best practices) it('shows details when showDetails prop is true', async () => { render(<UserProfile userId="123" showDetails />) await waitFor(() => { expect(screen.getByTestId('user-details-section')).toBeInTheDocument() }) }) })
</code_example>
<code_example> Cypress E2E Test
Command:
/scaffold e2e-test user-flow
Generated:
cypress/e2e/user-flow.cy.ts
// E2E test (per cypress-e2e-testing-*.mdc) describe('User Flow', () => { // Setup before tests (per cypress best practices) beforeEach(() => { // Reset state and seed data cy.task('db:seed') cy.visit('/') }) // Critical user flow (per cypress-e2e-testing guidelines) it('allows user to sign up, login, and view profile', () => { // Use data-testid selectors (per cypress best practices) cy.get('[data-testid="signup-link"]').click() // Fill signup form cy.get('[data-testid="email-input"]').type('test@example.com') cy.get('[data-testid="password-input"]').type('SecurePass123!') cy.get('[data-testid="name-input"]').type('Test User') cy.get('[data-testid="signup-submit"]').click() // Verify redirect to dashboard cy.url().should('include', '/dashboard') // Navigate to profile cy.get('[data-testid="profile-link"]').click() // Verify profile data cy.get('[data-testid="profile-name"]').should('contain', 'Test User') cy.get('[data-testid="profile-email"]').should('contain', 'test@example.com') }) // API mocking example (per cypress-api-testing guidelines) it('handles API errors gracefully', () => { // Mock API failure cy.intercept('GET', '/api/users/*', { statusCode: 500, body: { error: 'Internal server error' }, }).as('getUserError') cy.visit('/profile') // Wait for mocked request cy.wait('@getUserError') // Verify error handling cy.get('[data-testid="error-message"]') .should('be.visible') .and('contain', 'Failed to load profile') // Verify retry option cy.get('[data-testid="retry-button"]').should('be.visible') }) })
</code_example>
<usage_example> Quick Commands:
# Generate a Server Component /scaffold component MyComponent # Generate a Client Component /scaffold client-component MyInteractiveWidget # Generate an API route /scaffold api resource-name # Generate a FastAPI router /scaffold fastapi-route resource-name # Generate test for existing file /scaffold test path/to/component # Generate E2E test /scaffold e2e-test flow-name # Generate with specific rules /scaffold component MyComponent --rules nextjs,typescript # Generate in specific location /scaffold component MyComponent --path src/features/auth # List available scaffold templates /scaffold --list
Available Templates:
| Template | Framework | Files Generated |
|---|---|---|
| Next.js/React | index.tsx, types.ts, skeleton.tsx |
| Next.js | index.tsx with 'use client' |
| Next.js App Router | page.tsx, loading.tsx, error.tsx |
| Next.js App Router | route.ts with handlers |
| FastAPI | router file with endpoints |
| React | Custom hook with types |
| React | Context provider + hook |
| Jest/Vitest | Test file for component |
| Cypress/Playwright | E2E test spec |
| Prisma | Schema model |
| Database | Migration file |
| </usage_example> |