Install any skill in seconds. Free to start, no credit card required.
Get Started Free →AI-friendly architecture patterns for TypeScript projects including Domain-Driven Design, Clean Architecture, Hexagonal Architecture, and Page Object Model testing patterns
.claude/skills/aiskillstore-architecture-patterns/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 56% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 29% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 76% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 96% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 169% | 0% |
This skill is a pattern index that references comprehensive skills for details. Use this to understand which pattern to use, then reference the specific skill for implementation details.
→ See: nextjs-15-specialist skill
Quick Reference:
Decision Tree:
Need interactivity (onClick, onChange)?
├─ YES → Client Component
└─ NO → Server Component
Need React hooks (useState, useEffect)?
├─ YES → Client Component
└─ NO → Server Component
Need to fetch data?
└─ Prefer Server Component (better performance)Details: nextjs-patterns.md
→ See: typescript-strict-guard skill
Quick Reference:
any - Use explicit types or unknown with type guards@ts-ignore - Fix underlying type error! assertions - Use optional chaining or type guardsunknown typesDecision Tree:
Type is unknown at compile time?
├─ Use `unknown` with type guard
└─ Define explicit interface/type
Need optional property?
├─ Use `type?.property`
└─ Or `type ?? defaultValue`
Need to narrow union type?
└─ Use discriminated union or type guardDetails: typescript-conventions.md
→ See: drizzle-orm-patterns skill
Quick Reference:
.with() syntaxDecision Tree:
Need to query database?
├─ Simple query → db.select().from(table)
├─ Relations → .with() syntax
└─ Complex → Use joins explicitly
Need to modify data?
├─ Single record → db.insert/update/delete
└─ Multiple operations → Use transactionDetails: database-patterns.md
Quick Reference:
Decision Tree:
What kind of state?
├─ Server data (API, database) → React Query
├─ Local UI (toggle, input) → useState
├─ Shared across components → Context
├─ URL parameters → useSearchParams
└─ Form data → React Hook FormDetails: state-management-patterns.md
→ See: zod-validation-patterns skill
Quick Reference:
Decision Tree:
Implementing API route?
1. Define Zod schema for input validation
2. Check authentication (if protected)
3. Validate input with schema.parse()
4. Check authorization (resource ownership)
5. Execute business logic
6. Return appropriate status codeDetails: api-patterns.md
→ See: react-19-patterns skill
Quick Reference:
Details: react-19-patterns.md
Scenario: Need to display data from database
Options:
Decision:
Is data static or rarely changes?
└─ Use Server Component
Need real-time updates?
└─ Use SSE pattern
Need client-side caching/refetching?
└─ Use React QueryScenario: Need to handle form submission
Options:
Decision:
Simple form (create, update)?
└─ Use Server Action
Complex validation or multi-step?
└─ Use Client Component + API Route
Need optimistic UI updates?
└─ Use Client Component with useOptimisticScenario: Need to protect routes/resources
Pattern:
typescript// 1. Check authentication const user = await getAuthUser(request) if (!user) { return new Response('Unauthorized', { status: 401 }) } // 2. Check authorization (resource ownership) const resource = await db.resource.findUnique({ where: { id } }) if (!resource) { return new Response('Not found', { status: 404 }) } if (resource.userId !== user.id) { return new Response('Forbidden', { status: 403 }) } // 3. Proceed with operation
See: ../security-sentinel/SKILL.md
This skill uses progressive disclosure:
Example workflow:
Architecture patterns aggregate knowledge from:
typescript// app/projects/page.tsx (Server Component) export default async function ProjectsPage() { const projects = await db.select().from(projectsTable) return <ProjectList projects={projects} /> }
typescript// app/api/projects/route.ts import { z } from 'zod' const createSchema = z.object({ name: z.string().min(1).max(100), }) export async function POST(request: Request) { // 1. Validate input const body = await request.json() const validated = createSchema.parse(body) // 2. Check auth const user = await getAuthUser(request) if (!user) return new Response('Unauthorized', { status: 401 }) // 3. Execute const project = await db.insert(projectsTable).values({ ...validated, userId: user.id, }) return Response.json(project, { status: 201 }) }
typescript// components/ProjectCard.tsx (Client Component) 'use client' import { useState } from 'react' export function ProjectCard({ project }: Props) { const [loading, setLoading] = useState(false) const handleDelete = async () => { setLoading(true) await deleteProject(project.id) setLoading(false) } return ( <div> <h2>{project.name}</h2> <button onClick={handleDelete} disabled={loading}> Delete </button> </div> ) }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 15,697 | 13,651 | -13% | 1 | 1 | 0% | 3,344 | 5,221 | +56% | 0 | 0 | — |
case-02 | fail→pass | 23,998 | 16,704 | -30% | 1 | 1 | 0% | 4,771 | 6,132 | +29% | 0 | 0 | — |
case-03 | fail→pass | 16,473 | 16,976 | +3% | 1 | 1 | 0% | 3,428 | 6,042 | +76% | 0 | 0 | — |
case-04 | pass→pass | 12,492 | 11,821 | -5% | 1 | 1 | 0% | 2,407 | 4,711 | +96% | 0 | 0 | — |
case-05 | pass→pass | 8,100 | 8,494 | +5% | 1 | 1 | 0% | 1,490 | 4,013 | +169% | 0 | 0 | — |
case-06 | pass→pass | 14,196 | 11,215 | -21% | 1 | 1 | 0% | 2,171 | 4,096 | +89% | 0 | 0 | — |
case-07 | pass→pass | 12,171 | 9,010 | -26% | 1 | 1 | 0% | 2,405 | 4,030 | +68% | 0 | 0 | — |
case-08 | pass→pass | 10,783 | 10,129 | -6% | 1 | 1 | 0% | 2,032 | 4,181 | +106% | 0 | 0 | — |
case-09 | pass→pass | 8,802 | 7,069 | -20% | 1 | 1 | 0% | 1,737 | 3,745 | +116% | 0 | 0 | — |
case-10 | pass→pass | 11,915 | 8,940 | -25% | 1 | 1 | 0% | 2,031 | 3,991 | +97% | 0 | 0 | — |
case-11 | pass→pass | 13,446 | 7,231 | -46% | 1 | 1 | 0% | 2,520 | 3,877 | +54% | 0 | 0 | — |
case-12 | pass→pass | 10,784 | 11,577 | +7% | 1 | 1 | 0% | 2,068 | 4,254 | +106% | 0 | 0 | — |
case-13 | pass→pass | 17,985 | 14,134 | -21% | 1 | 1 | 0% | 3,214 | 5,020 | +56% | 0 | 0 | — |
case-14 | pass→pass | 17,558 | 9,735 | -45% | 1 | 1 | 0% | 3,168 | 4,340 | +37% | 0 | 0 | — |
case-15 | pass→pass | 5,769 | 5,356 | -7% | 1 | 1 | 0% | 1,012 | 3,357 | +232% | 0 | 0 | — |
case-16 | pass→pass | 4,710 | 4,489 | -5% | 1 | 1 | 0% | 786 | 3,217 | +309% | 0 | 0 | — |
case-17 | pass→pass | 4,579 | 2,861 | -38% | 1 | 1 | 0% | 704 | 2,885 | +310% | 0 | 0 | — |
case-18 | pass→pass | 11,617 | 9,109 | -22% | 1 | 1 | 0% | 1,999 | 4,072 | +104% | 0 | 0 | — |
case-19 | pass→pass | 7,131 | 4,531 | -36% | 1 | 1 | 0% | 1,263 | 3,238 | +156% | 0 | 0 | — |
case-20 | pass→pass | 9,003 | 6,201 | -31% | 1 | 1 | 0% | 1,472 | 3,449 | +134% | 0 | 0 | — |
case-21 | pass→pass | 10,971 | 8,227 | -25% | 1 | 1 | 0% | 2,028 | 4,018 | +98% | 0 | 0 | — |
case-22 | pass→pass | 12,829 | 5,360 | -58% | 1 | 1 | 0% | 2,270 | 3,426 | +51% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +14 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.