frontend-development
Frontend Development
Next.js App Router with TypeScript. Server-first architecture. Covers everything from adding a page to building complex interactive features — including vague tasks where you need to figure out the right approach from context.
Related Skills:
kavak-documentation— for Kavak-specific patterns, GitLab CI, Docker templatesvercel-react-best-practices— for performance (bundle size, waterfalls, caching, re-renders)- Check
.claude/CLAUDE.mdor.cursor/rules/*for project-specific conventionsMCP: Use
kavak-platform/platform_docs_searchfor Kavak internal docs andkavak-platform/search_resourcefor workload info.
Quick Start
| Task | Pattern |
|---|---|
| New page | Server Component by default |
| Data fetching | Server Component async fetch |
| Mutations | Server Actions + Zod + revalidatePath |
| Styling | MUI sx prop, inline if <100 lines |
| State | Server = fetch, Client = useState only when needed |
Core Principles
- Server by Default — components are Server Components unless they need
useState/useEffect/events - Server Actions for Mutations — replace API routes for internal app logic
- Opt-in Caching — use
'use cache'directive for explicit caching - Minimal Client JS — keep
'use client'components small and leaf-level - Type Everything — strict TypeScript, Zod for runtime validation
Performance: For bundle optimization, waterfalls, memoization, see
vercel-react-best-practices
Server vs Client Decision
Need useState/useEffect/onClick? → 'use client'
Need browser APIs (localStorage)? → 'use client'
Just rendering data? → Server Component (default)
Keep Client Components small. Most of the tree stays server-rendered.
Data Fetching Pattern
// app/users/page.tsx - Server Component (default)
export default async function UsersPage() {
const users = await db.user.findMany(); // Runs on server
return <UserList users={users} />;
}
No TanStack Query needed — Server Components handle data fetching natively. Only use TanStack Query for real-time polling or complex optimistic updates.
Server Actions Pattern
// app/actions.ts
'use server';
import { z } from 'zod';
import { revalidatePath } from 'next/cache';
const schema = z.object({ title: z.string().min(1) });
export async function createPost(formData: FormData) {
const parsed = schema.safeParse({ title: formData.get('title') });
if (!parsed.success) return { error: parsed.error.flatten() };
await db.post.create({ data: parsed.data });
revalidatePath('/posts');
return { success: true };
}
- Server Actions → internal mutations, form submissions
- Route Handlers → public APIs, webhooks, large uploads, streaming
Design Quality
When building UI, avoid generic-looking interfaces. Every interface should feel intentional:
- Typography — pick fonts that match the context. Avoid defaulting to Inter/Roboto/Arial for everything
- Color — commit to a cohesive palette with CSS variables. Dominant colors with sharp accents beat timid, evenly-distributed palettes
- Spacing — generous negative space or controlled density, not cramped defaults
- Motion — meaningful animations for state transitions, not gratuitous effects. Use CSS transitions first, Motion library for complex sequences
Match complexity to the design vision. A dashboard needs clarity and information density. A marketing page needs bold visual impact. A form needs clean usability.
Critical Rules
// ❌ Large 'use client' at top of tree — marks entire subtree as client
// ❌ Expose secrets in client: process.env.SECRET_KEY
// ❌ Old MUI Grid syntax: <Grid xs={12} md={6}>
// ✅ Small leaf-level client components
// ✅ Validate Server Action inputs with Zod
// ✅ MUI Grid size prop: <Grid size={{ xs: 12, md: 6 }}>
File Conventions
app/
├── layout.tsx # Root layout (Server)
├── page.tsx # Home page
├── loading.tsx # Loading UI (Suspense fallback)
├── error.tsx # Error boundary ('use client')
├── not-found.tsx # 404 page
├── users/
│ ├── page.tsx # /users
│ ├── [id]/page.tsx # /users/:id
│ └── actions.ts # Server Actions
└── api/webhook/
└── route.ts # Route Handler (public API)
Common Workflows
New Feature
- Create
app/{route}/page.tsx(Server Component) - Add
loading.tsxfor Suspense boundary - Create Server Actions in
actions.ts - Add Client Components only where needed
Styling Component
- MUI
sxprop withSxProps<Theme> - Inline styles if <100 lines, separate
.styles.tsif >100 - Grid:
size={{ xs: 12, md: 6 }}
Performance Issue
→ Run vercel-react-best-practices skill for optimization rules
References
| Reference | When to Use |
|---|---|
references/nextjs.md |
App Router, RSC, Server Actions, caching |
references/component-patterns.md |
React.FC, hooks order, dialogs, forms |
references/styling.md |
MUI sx prop, Grid, theming |
references/typescript.md |
Types, generics, Zod validation |
references/project-structure.md |
features/ vs components/, organization |
Next.js DevTools MCP (Next.js 16+)
When working on a Next.js 16+ project, use these MCP tools for runtime diagnostics and documentation. They provide better information than reading files or guessing — always prefer them when available.
| Tool | When to Use |
|---|---|
next-devtools/init |
Call FIRST at session start to establish documentation-first approach |
next-devtools/nextjs_docs |
Look up ANY Next.js API, pattern, or feature. Read nextjs-docs://llms-index resource first to get the correct path, then query |
next-devtools/nextjs_index |
Discover running dev servers and their available MCP tools. Call before any runtime inspection |
next-devtools/nextjs_call |
Execute runtime tools on a running dev server — get errors, list routes, check build status, clear cache. Use nextjs_index first to discover available tools |
next-devtools/browser_eval |
Browser automation — navigate, click, fill forms, take screenshots, get console messages. For Next.js, prefer nextjs_index/nextjs_call over console log forwarding |
next-devtools/enable_cache_components |
Migrate to Cache Components mode (Next.js 16+). Handles config, error detection, Suspense boundaries, 'use cache' directives |
next-devtools/upgrade_nextjs_16 |
Upgrade to Next.js 16 — runs official codemod first (needs clean git), then handles remaining issues |
Workflow: Before implementing changes, call nextjs_index to understand current routes and state. Before looking up Next.js APIs, call nextjs_docs with the correct path from the docs index. Use nextjs_call for runtime diagnostics (errors, build status) instead of reading logs manually.
Technology Stack
| Layer | Technology |
|---|---|
| Framework | Next.js (App Router, latest) |
| Type Safety | TypeScript (strict) + Zod |
| Data Fetching | Server Components (async) |
| Mutations | Server Actions + revalidatePath |
| Client State | useState (minimal) |
| Styling | MUI (latest) |
| Forms | Server Actions + useActionState |
More from carvalab/k-skills
code-review
Use this skill as the FINAL step after writing or modifying code — reviews for logic bugs, architecture violations, security issues, and performance problems. Trigger after completing a feature, fixing a bug, before merging, or when asked to "review this code", "check my changes", or "is this ready to merge". Fixes issues directly and runs quality gates (lint, typecheck, build, tests). Delegates style to automation, focuses on what matters.
38refactor-cleaner
Use this skill to find and remove dead code, unused dependencies, duplicate logic, and unused exports using detection tools (knip, depcheck, ts-prune, deadcode, staticcheck). Trigger on "clean up dead code", "remove unused", "find dead code", "reduce bundle size", "dependency audit", or when the codebase feels bloated. For simplifying living code (readability, naming, complexity reduction) without detection tools, use code-simplifier instead. Use this skill during maintenance windows or before major refactors.
36code-simplifier
Use this skill after writing or modifying code to simplify it — reduces complexity, eliminates redundancy, and improves naming while preserving exact behavior. Trigger after implementing a feature, after a refactor, or when asked to "clean up this code", "simplify this", "make this more readable", or "reduce complexity". Also use when code feels too nested, verbose, or hard to follow. For removing dead code and unused dependencies with detection tools (knip, ts-prune, deadcode), use refactor-cleaner instead.
24backend-development
Use this skill for ANY task in a Node.js/TypeScript or Go backend codebase — adding features, fixing bugs, refactoring, adding flows, modifying handlers, changing business logic, or writing new code. Trigger even when the task is vague like "add the flow to this", "implement this feature", "fix this", or "add X like Y" — if the project has go.mod, nest-cli.json, express routes, or server-side TypeScript, this skill applies. Covers REST APIs, PostgreSQL, Redis, authentication, job queues, events, microservices, Docker, CI/CD, Clean Architecture, SOLID, DRY, and code reuse patterns. When in doubt whether this is backend work, use this skill.
24doc-updater
Use this skill when documentation needs updating — after adding features, changing APIs, modifying architecture, or updating dependencies. Trigger on "update the docs", "generate codemap", "refresh the README", "document this", "update architecture docs", or when code changes make existing documentation stale. Generates codemaps from actual code, updates READMEs, architecture diagrams, and guides.
22test-driven-development
Use this skill when writing new features, fixing bugs, or adding test coverage. Enforces Red-Green-Refactor — write the test first, then the code. Trigger on "add tests", "write tests first", "TDD", "test this feature", "fix this bug" (reproduce with a failing test first), or when starting any new implementation. Prevents testing anti-patterns like over-mocking, test-per-method, and tests that pass but verify nothing.
19