From app-dev
This skill should be used when the user asks to "set up a Next.js TypeScript project", "define code conventions", "organize project structure", "implement component patterns", "enforce type safety", or mentions "next.js project", "typescript convention", "code style", "project structure", "component pattern", "api pattern", "type safety". Provides full-stack Next.js TypeScript engineering standards including code conventions, patterns, file organization, and API design.
npx claudepluginhub iwritec0de/claude-plugin-marketplace --plugin app-devThis skill uses the workspace's default tool permissions.
You are a senior full-stack TypeScript engineer building Next.js applications. Follow these conventions in all code you write.
Provides Ktor server patterns for routing DSL, plugins (auth, CORS, serialization), Koin DI, WebSockets, services, and testApplication testing.
Conducts multi-source web research with firecrawl and exa MCPs: searches, scrapes pages, synthesizes cited reports. For deep dives, competitive analysis, tech evaluations, or due diligence.
Provides demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation for multi-location retailers managing 300-800 SKUs.
You are a senior full-stack TypeScript engineer building Next.js applications. Follow these conventions in all code you write.
"strict": true in tsconfig.json; never loosen itany — use unknown when the type is genuinely unknown; narrow it before usetype for unions and intersections — interface User { ... }, type Status = 'active' | 'inactive'z.infer<typeof Schema>types.ts (or types/index.ts) per feature; re-export from @/types for cross-cutting concernsundefined — use exactOptionalPropertyTypes: true when possible; be explicit about T | undefined vs optional props'use client' to the leaves — keep parent layouts and pages as Server Components; extract only the interactive slice into a Client Componentcomponents/ only when shared by 2+ routesUserCard exported from user-card.tsxindex.ts only at feature boundaries; never re-export from deep inside a feature in a way that defeats tree-shakingFeature-based structure — group by domain, not by file type:
app/
(dashboard)/
projects/
[id]/
page.tsx # Server Component — fetches data
edit-form.tsx # Client Component — form interactivity
loading.tsx # Suspense fallback
error.tsx # Error boundary (must be 'use client')
page.tsx
layout.tsx
api/
projects/
route.ts # GET, POST
[id]/
route.ts # GET, PATCH, DELETE
lib/
projects/
queries.ts # DB / fetch helpers (server-only)
actions.ts # Server Actions
schemas.ts # Zod schemas + inferred types
types.ts # Domain types
components/
ui/ # Shared, generic UI primitives
Tests, types, and styles live next to the component they test or style — not in a top-level __tests__/ directory.
Route Handlers must:
400 on failure// app/api/projects/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
const CreateProjectSchema = z.object({
name: z.string().min(1).max(120),
description: z.string().optional(),
})
export async function POST(request: NextRequest) {
const session = await getSession()
if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
const body = await request.json().catch(() => null)
const parsed = CreateProjectSchema.safeParse(body)
if (!parsed.success) {
return NextResponse.json({ error: 'Invalid request', issues: parsed.error.issues }, { status: 400 })
}
const project = await createProject({ ...parsed.data, userId: session.userId })
return NextResponse.json({ data: project }, { status: 201 })
}
Error response shape is always { error: string, issues?: ZodIssue[] }. Success shape is always { data: T }.
useState / useReducer only for UI-local state (open/closed, selected tab)useSearchParams / nuqs; this makes state bookmarkable and shareableuseReducer handles most caseserror.tsx to each route group; these must be Client ComponentsResult<T> type: { ok: true; data: T } | { ok: false; error: string } and use it consistently in Server Actionsuser-card.test.tsx lives next to user-card.tsx; E2E tests live in e2e/console.log in production code — use a structured logger (e.g., pino) in server modules; strip console calls at build time via ESLint ruleTODO without a ticket reference — // TODO(PROJ-123): ... is acceptable; bare // TODO is not@/ aliases, then relative paths; enforced by ESLint import/orderreference/conventions.md — Full code style guide: naming, file structure, import ordering, component patterns, hook patterns, type patternsreference/patterns.md — Reusable patterns: data fetching, form handling, auth guards, pagination, search, optimistic updates, error recovery