Feature Scaffolding (/feature-scaffold)¶
In plain terms
Use this when building something brand new — a page, feature, or endpoint that doesn't exist yet.
What this skill does
Use when building anything new — a page, feature, module, entity, endpoint, component, or view that doesn't exist yet. Triggers on any request to create, build, add, implement, or introduce new functionality.
[!NOTE] Use this when creating anything new in the codebase — a feature, page, module, component, API endpoint, or entity that doesn't already exist. For extending an existing page, use
/full-stack-extensioninstead.
Trigger Conditions¶
- Any request to create, build, add, implement, or introduce new functionality
- Keywords: "Create a new page", "Build a feature", "Add a module for X", "New view", "New endpoint", "Add a section", "Implement X", "I need a new...", "Set up...", "Make a..."
- Also trigger when: the user describes desired behavior that doesn't map to any existing code
1. Planning¶
- [ ] Architecture Check: Review docs/ARCHITECTURE.md for directory structure and naming conventions
- [ ] Schema: Does this feature need new DB tables? If yes, run
/db-migrationfirst - [ ] OpenAPI: After backend changes, run
/openapi-syncto regenerate frontend types
2. Backend Scaffold¶
- [ ] Model: Add or update a SQLModel model in
backend/app/models/[feature].py - [ ] Schema: Create Pydantic request/response schemas in
backend/app/schemas/[feature].py - [ ] Router: Create route handlers in
backend/app/api/[feature].py
from fastapi import APIRouter, Depends, HTTPException
from app.core.auth import require_auth, require_permission
router = APIRouter(prefix="/[feature]", tags=["[feature]"])
@router.get("/")
async def list_features(user=Depends(require_auth)):
# Query logic here
return data
- [ ] Registration: Register the router in
backend/app/api/__init__.py(or the main router file) - [ ] Migration: If schema changed, run Alembic:
alembic revision --autogenerate -m "add [feature]"thenalembic upgrade head - [ ] Validation: All inputs validated via Pydantic v2 schemas
3. Frontend Scaffold¶
- [ ] Types: Run
/openapi-sync— never manually define types that exist in@/types/api - [ ] Query/Mutation: Add TanStack Query hooks in
frontend/src/hooks/use[Feature].ts:export function useFeature() { const query = useQuery({ queryKey: ['[feature]'], queryFn: () => apiRequest('/api/[feature]'), }); const createMutation = useMutation({ mutationFn: (data: CreateFeatureInput) => apiRequest('/api/[feature]', { method: 'POST', body: data }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['[feature]'] }); }, }); return { features: query.data || [], isLoading: query.isLoading, createFeature: createMutation.mutateAsync, }; } - [ ] Component: Create React page/components under
frontend/src/app/orfrontend/src/components/ - No
window.alert()orwindow.confirm() - Use
<FormattedCurrency />for money,formatDateLocal()for dates - Empty states: never blank — use illustration or helpful text
- Loading states: shimmer (
animate-pulseon gray blocks) - [ ] Routing: Register the new page in the app router
- [ ] Networking: All API calls must use
apiRequestfrom@/lib/queryClient
4. Security¶
- [ ] Auth: Every admin/protected route must declare
require_authandrequire_permissiondependencies - [ ] Validation: Backend uses Pydantic v2; frontend uses Zod + React Hook Form
5. Tests (REQUIRED)¶
- [ ] Run
/test-syncto automatically create tests for all new/changed files - [ ] Verify: All tests pass before proceeding to verification
6. Verification¶
- [ ] Integration: Frontend calls backend — verify in browser network tab
- [ ] Design: Run
/architecture-reviewto verify UI compliance - [ ] Types: Run
cd frontend && npm run type-check && cd ../backend && python -m mypy app/
[!NOTE] Use this when creating anything new in the codebase — a feature, page, module, component, API endpoint, or entity that doesn't already exist. For extending an existing page, use
/full-stack-extensioninstead.
Trigger Conditions¶
- Any request to create, build, add, implement, or introduce new functionality
- Keywords: "Create a new page", "Build a feature", "Add a module for X", "New view", "New endpoint", "Add a section", "Implement X", "I need a new...", "Set up...", "Make a..."
- Also trigger when: the user describes desired behavior that doesn't map to any existing code
1. Planning¶
- [ ] Architecture Check: Review docs/ARCHITECTURE.md for directory structure and naming conventions
- [ ] Schema: Does this feature need new DB tables? If yes, run
/db-migrationfirst - [ ] Routing: Decide the URL path — SalesFocus uses Wouter (not React Router)
2. Backend Scaffold¶
- [ ] Route file: Create
backend/src/routes/[feature].ts
import { Router } from 'express';
import type { NextFunction, Response } from 'express';
import { db } from '../db/index.js';
import { authenticate } from '../middleware/auth.js';
import type { AuthRequest } from '../middleware/auth.js';
const router = Router();
router.get('/', authenticate, async (req: AuthRequest, res: Response, next: NextFunction) => {
try {
const data = await db.select().from(featureTable);
res.json(data);
} catch (error) {
next(error); // ALWAYS use next(error) — never manual res.status(500)
}
});
export default router;
- [ ] Zod validation: Add validation schema to
backend/src/validation/[feature].schema.ts - [ ] Register route: Add to
backend/src/server.ts:import featureRouter from './routes/[feature].js'; app.use('/api/[feature]', authenticate, featureRouter); - [ ] Explicit
.jsextensions: All local imports MUST use.jsextension (TypeScript ESM requirement)
3. Frontend Scaffold¶
-
[ ] Service: Create
services/domains/[feature]Service.ts(or add methods toservices/apiClient.tsif small):import apiClient from '../apiClient'; export const get[Feature]s = () => apiClient.get('/[feature]').then(r => r.data); -
[ ] Hook: Create
hooks/use[Feature].tsas a domain hook:export function use[Feature]() { const queryClient = useQueryClient(); const toast = useToast(); const query = useQuery({ queryKey: ['[feature]'], queryFn: get[Feature]s, }); const createMutation = useMutation({ mutationFn: (data: Create[Feature]Input) => createFeature, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['[feature]'] }); toast.success('[Feature] created'); }, }); return { [feature]s: query.data || [], isLoading: query.isLoading, create[Feature]: createMutation.mutateAsync, }; } -
[ ] Component: Create
components/[Feature]View.tsxorcomponents/[Feature]Page.tsx - No
window.alert()orwindow.confirm() - Use
<FormattedCurrency />for money,formatDateLocal()for dates - Empty states: never blank — use illustration or helpful text
-
Loading states: shimmer (
animate-pulseon gray blocks) -
[ ] Routing: Add to
App.tsxusing Wouter:import { Route } from 'wouter'; <Route path="/[feature]" component={[Feature]View} /> -
[ ] Navigation: If it's a nav item, add to
lib/navigation.ts - Admin-only pages: also add
<AdminRoute>wrapper inApp.tsx
4. Tests (REQUIRED)¶
- [ ] Run
/test-syncto automatically create tests for all new/changed files - [ ] Verify: All tests pass before proceeding to verification
5. Verification¶
- [ ] Integration: Frontend calls backend — verify in browser network tab
- [ ] Design: Run
/architecture-reviewto verify UI compliance (Twycis colors, rounded buttons, etc.) - [ ] Types: Run
cd backend && npm run type-check && npm run type-check