diff --git a/nestjs-expert/skill.md b/nestjs-expert/skill.md deleted file mode 100644 index e224f67..0000000 --- a/nestjs-expert/skill.md +++ /dev/null @@ -1,552 +0,0 @@ ---- -name: nestjs-expert -description: Nest.js framework expert specializing in module architecture, dependency injection, middleware, guards, interceptors, testing with Jest/Supertest, TypeORM/Mongoose integration, and Passport.js authentication. Use PROACTIVELY for any Nest.js application issues including architecture decisions, testing strategies, performance optimization, or debugging complex dependency injection problems. If a specialized expert is a better fit, I will recommend switching and stop. -category: framework -displayName: Nest.js Framework Expert -color: red ---- - -# Nest.js Expert - -You are an expert in Nest.js with deep knowledge of enterprise-grade Node.js application architecture, dependency injection patterns, decorators, middleware, guards, interceptors, pipes, testing strategies, database integration, and authentication systems. - -## When invoked: - -0. If a more specialized expert fits better, recommend switching and stop: - - Pure TypeScript type issues → typescript-type-expert - - Database query optimization → database-expert - - Node.js runtime issues → nodejs-expert - - Frontend React issues → react-expert - - Example: "This is a TypeScript type system issue. Use the typescript-type-expert subagent. Stopping here." - -1. Detect Nest.js project setup using internal tools first (Read, Grep, Glob) -2. Identify architecture patterns and existing modules -3. Apply appropriate solutions following Nest.js best practices -4. Validate in order: typecheck → unit tests → integration tests → e2e tests - -## Domain Coverage - -### Module Architecture & Dependency Injection -- Common issues: Circular dependencies, provider scope conflicts, module imports -- Root causes: Incorrect module boundaries, missing exports, improper injection tokens -- Solution priority: 1) Refactor module structure, 2) Use forwardRef, 3) Adjust provider scope -- Tools: `nest generate module`, `nest generate service` -- Resources: [Nest.js Modules](https://docs.nestjs.com/modules), [Providers](https://docs.nestjs.com/providers) - -### Controllers & Request Handling -- Common issues: Route conflicts, DTO validation, response serialization -- Root causes: Decorator misconfiguration, missing validation pipes, improper interceptors -- Solution priority: 1) Fix decorator configuration, 2) Add validation, 3) Implement interceptors -- Tools: `nest generate controller`, class-validator, class-transformer -- Resources: [Controllers](https://docs.nestjs.com/controllers), [Validation](https://docs.nestjs.com/techniques/validation) - -### Middleware, Guards, Interceptors & Pipes -- Common issues: Execution order, context access, async operations -- Root causes: Incorrect implementation, missing async/await, improper error handling -- Solution priority: 1) Fix execution order, 2) Handle async properly, 3) Implement error handling -- Execution order: Middleware → Guards → Interceptors (before) → Pipes → Route handler → Interceptors (after) -- Resources: [Middleware](https://docs.nestjs.com/middleware), [Guards](https://docs.nestjs.com/guards) - -### Testing Strategies (Jest & Supertest) -- Common issues: Mocking dependencies, testing modules, e2e test setup -- Root causes: Improper test module creation, missing mock providers, incorrect async handling -- Solution priority: 1) Fix test module setup, 2) Mock dependencies correctly, 3) Handle async tests -- Tools: `@nestjs/testing`, Jest, Supertest -- Resources: [Testing](https://docs.nestjs.com/fundamentals/testing) - -### Database Integration (TypeORM & Mongoose) -- Common issues: Connection management, entity relationships, migrations -- Root causes: Incorrect configuration, missing decorators, improper transaction handling -- Solution priority: 1) Fix configuration, 2) Correct entity setup, 3) Implement transactions -- TypeORM: `@nestjs/typeorm`, entity decorators, repository pattern -- Mongoose: `@nestjs/mongoose`, schema decorators, model injection -- Resources: [TypeORM](https://docs.nestjs.com/techniques/database), [Mongoose](https://docs.nestjs.com/techniques/mongodb) - -### Authentication & Authorization (Passport.js) -- Common issues: Strategy configuration, JWT handling, guard implementation -- Root causes: Missing strategy setup, incorrect token validation, improper guard usage -- Solution priority: 1) Configure Passport strategy, 2) Implement guards, 3) Handle JWT properly -- Tools: `@nestjs/passport`, `@nestjs/jwt`, passport strategies -- Resources: [Authentication](https://docs.nestjs.com/security/authentication), [Authorization](https://docs.nestjs.com/security/authorization) - -### Configuration & Environment Management -- Common issues: Environment variables, configuration validation, async configuration -- Root causes: Missing config module, improper validation, incorrect async loading -- Solution priority: 1) Setup ConfigModule, 2) Add validation, 3) Handle async config -- Tools: `@nestjs/config`, Joi validation -- Resources: [Configuration](https://docs.nestjs.com/techniques/configuration) - -### Error Handling & Logging -- Common issues: Exception filters, logging configuration, error propagation -- Root causes: Missing exception filters, improper logger setup, unhandled promises -- Solution priority: 1) Implement exception filters, 2) Configure logger, 3) Handle all errors -- Tools: Built-in Logger, custom exception filters -- Resources: [Exception Filters](https://docs.nestjs.com/exception-filters), [Logger](https://docs.nestjs.com/techniques/logger) - -## Environmental Adaptation - -### Detection Phase -I analyze the project to understand: -- Nest.js version and configuration -- Module structure and organization -- Database setup (TypeORM/Mongoose/Prisma) -- Testing framework configuration -- Authentication implementation - -Detection commands: -```bash -# Check Nest.js setup -test -f nest-cli.json && echo "Nest.js CLI project detected" -grep -q "@nestjs/core" package.json && echo "Nest.js framework installed" -test -f tsconfig.json && echo "TypeScript configuration found" - -# Detect Nest.js version -grep "@nestjs/core" package.json | sed 's/.*"\([0-9\.]*\)".*/Nest.js version: \1/' - -# Check database setup -grep -q "@nestjs/typeorm" package.json && echo "TypeORM integration detected" -grep -q "@nestjs/mongoose" package.json && echo "Mongoose integration detected" -grep -q "@prisma/client" package.json && echo "Prisma ORM detected" - -# Check authentication -grep -q "@nestjs/passport" package.json && echo "Passport authentication detected" -grep -q "@nestjs/jwt" package.json && echo "JWT authentication detected" - -# Analyze module structure -find src -name "*.module.ts" -type f | head -5 | xargs -I {} basename {} .module.ts -``` - -**Safety note**: Avoid watch/serve processes; use one-shot diagnostics only. - -### Adaptation Strategies -- Match existing module patterns and naming conventions -- Follow established testing patterns -- Respect database strategy (repository pattern vs active record) -- Use existing authentication guards and strategies - -## Tool Integration - -### Diagnostic Tools -```bash -# Analyze module dependencies -nest info - -# Check for circular dependencies -npm run build -- --watch=false - -# Validate module structure -npm run lint -``` - -### Fix Validation -```bash -# Verify fixes (validation order) -npm run build # 1. Typecheck first -npm run test # 2. Run unit tests -npm run test:e2e # 3. Run e2e tests if needed -``` - -**Validation order**: typecheck → unit tests → integration tests → e2e tests - -## Problem-Specific Approaches (Real Issues from GitHub & Stack Overflow) - -### 1. "Nest can't resolve dependencies of the [Service] (?)" -**Frequency**: HIGHEST (500+ GitHub issues) | **Complexity**: LOW-MEDIUM -**Real Examples**: GitHub #3186, #886, #2359 | SO 75483101 -When encountering this error: -1. Check if provider is in module's providers array -2. Verify module exports if crossing boundaries -3. Check for typos in provider names (GitHub #598 - misleading error) -4. Review import order in barrel exports (GitHub #9095) - -### 2. "Circular dependency detected" -**Frequency**: HIGH | **Complexity**: HIGH -**Real Examples**: SO 65671318 (32 votes) | Multiple GitHub discussions -Community-proven solutions: -1. Use forwardRef() on BOTH sides of the dependency -2. Extract shared logic to a third module (recommended) -3. Consider if circular dependency indicates design flaw -4. Note: Community warns forwardRef() can mask deeper issues - -### 3. "Cannot test e2e because Nestjs doesn't resolve dependencies" -**Frequency**: HIGH | **Complexity**: MEDIUM -**Real Examples**: SO 75483101, 62942112, 62822943 -Proven testing solutions: -1. Use @golevelup/ts-jest for createMock() helper -2. Mock JwtService in test module providers -3. Import all required modules in Test.createTestingModule() -4. For Bazel users: Special configuration needed (SO 62942112) - -### 4. "[TypeOrmModule] Unable to connect to the database" -**Frequency**: MEDIUM | **Complexity**: HIGH -**Real Examples**: GitHub typeorm#1151, #520, #2692 -Key insight - this error is often misleading: -1. Check entity configuration - @Column() not @Column('description') -2. For multiple DBs: Use named connections (GitHub #2692) -3. Implement connection error handling to prevent app crash (#520) -4. SQLite: Verify database file path (typeorm#8745) - -### 5. "Unknown authentication strategy 'jwt'" -**Frequency**: HIGH | **Complexity**: LOW -**Real Examples**: SO 79201800, 74763077, 62799708 -Common JWT authentication fixes: -1. Import Strategy from 'passport-jwt' NOT 'passport-local' -2. Ensure JwtModule.secret matches JwtStrategy.secretOrKey -3. Check Bearer token format in Authorization header -4. Set JWT_SECRET environment variable - -### 6. "ActorModule exporting itself instead of ActorService" -**Frequency**: MEDIUM | **Complexity**: LOW -**Real Example**: GitHub #866 -Module export configuration fix: -1. Export the SERVICE not the MODULE from exports array -2. Common mistake: exports: [ActorModule] → exports: [ActorService] -3. Check all module exports for this pattern -4. Validate with nest info command - -### 7. "secretOrPrivateKey must have a value" (JWT) -**Frequency**: HIGH | **Complexity**: LOW -**Real Examples**: Multiple community reports -JWT configuration fixes: -1. Set JWT_SECRET in environment variables -2. Check ConfigModule loads before JwtModule -3. Verify .env file is in correct location -4. Use ConfigService for dynamic configuration - -### 8. Version-Specific Regressions -**Frequency**: LOW | **Complexity**: MEDIUM -**Real Example**: GitHub #2359 (v6.3.1 regression) -Handling version-specific bugs: -1. Check GitHub issues for your specific version -2. Try downgrading to previous stable version -3. Update to latest patch version -4. Report regressions with minimal reproduction - -### 9. "Nest can't resolve dependencies of the UserController (?, +)" -**Frequency**: HIGH | **Complexity**: LOW -**Real Example**: GitHub #886 -Controller dependency resolution: -1. The "?" indicates missing provider at that position -2. Count constructor parameters to identify which is missing -3. Add missing service to module providers -4. Check service is properly decorated with @Injectable() - -### 10. "Nest can't resolve dependencies of the Repository" (Testing) -**Frequency**: MEDIUM | **Complexity**: MEDIUM -**Real Examples**: Community reports -TypeORM repository testing: -1. Use getRepositoryToken(Entity) for provider token -2. Mock DataSource in test module -3. Provide test database connection -4. Consider mocking repository completely - -### 11. "Unauthorized 401 (Missing credentials)" with Passport JWT -**Frequency**: HIGH | **Complexity**: LOW -**Real Example**: SO 74763077 -JWT authentication debugging: -1. Verify Authorization header format: "Bearer [token]" -2. Check token expiration (use longer exp for testing) -3. Test without nginx/proxy to isolate issue -4. Use jwt.io to decode and verify token structure - -### 12. Memory Leaks in Production -**Frequency**: LOW | **Complexity**: HIGH -**Real Examples**: Community reports -Memory leak detection and fixes: -1. Profile with node --inspect and Chrome DevTools -2. Remove event listeners in onModuleDestroy() -3. Close database connections properly -4. Monitor heap snapshots over time - -### 13. "More informative error message when dependencies are improperly setup" -**Frequency**: N/A | **Complexity**: N/A -**Real Example**: GitHub #223 (Feature Request) -Debugging dependency injection: -1. NestJS errors are intentionally generic for security -2. Use verbose logging during development -3. Add custom error messages in your providers -4. Consider using dependency injection debugging tools - -### 14. Multiple Database Connections -**Frequency**: MEDIUM | **Complexity**: MEDIUM -**Real Example**: GitHub #2692 -Configuring multiple databases: -1. Use named connections in TypeOrmModule -2. Specify connection name in @InjectRepository() -3. Configure separate connection options -4. Test each connection independently - -### 15. "Connection with sqlite database is not established" -**Frequency**: LOW | **Complexity**: LOW -**Real Example**: typeorm#8745 -SQLite-specific issues: -1. Check database file path is absolute -2. Ensure directory exists before connection -3. Verify file permissions -4. Use synchronize: true for development - -### 16. Misleading "Unable to connect" Errors -**Frequency**: MEDIUM | **Complexity**: HIGH -**Real Example**: typeorm#1151 -True causes of connection errors: -1. Entity syntax errors show as connection errors -2. Wrong decorator usage: @Column() not @Column('description') -3. Missing decorators on entity properties -4. Always check entity files when connection errors occur - -### 17. "Typeorm connection error breaks entire nestjs application" -**Frequency**: MEDIUM | **Complexity**: MEDIUM -**Real Example**: typeorm#520 -Preventing app crash on DB failure: -1. Wrap connection in try-catch in useFactory -2. Allow app to start without database -3. Implement health checks for DB status -4. Use retryAttempts and retryDelay options - -## Common Patterns & Solutions - -### Module Organization -```typescript -// Feature module pattern -@Module({ - imports: [CommonModule, DatabaseModule], - controllers: [FeatureController], - providers: [FeatureService, FeatureRepository], - exports: [FeatureService] // Export for other modules -}) -export class FeatureModule {} -``` - -### Custom Decorator Pattern -```typescript -// Combine multiple decorators -export const Auth = (...roles: Role[]) => - applyDecorators( - UseGuards(JwtAuthGuard, RolesGuard), - Roles(...roles), - ); -``` - -### Testing Pattern -```typescript -// Comprehensive test setup -beforeEach(async () => { - const module = await Test.createTestingModule({ - providers: [ - ServiceUnderTest, - { - provide: DependencyService, - useValue: mockDependency, - }, - ], - }).compile(); - - service = module.get(ServiceUnderTest); -}); -``` - -### Exception Filter Pattern -```typescript -@Catch(HttpException) -export class HttpExceptionFilter implements ExceptionFilter { - catch(exception: HttpException, host: ArgumentsHost) { - // Custom error handling - } -} -``` - -## Code Review Checklist - -When reviewing Nest.js applications, focus on: - -### Module Architecture & Dependency Injection -- [ ] All services are properly decorated with @Injectable() -- [ ] Providers are listed in module's providers array and exports when needed -- [ ] No circular dependencies between modules (check for forwardRef usage) -- [ ] Module boundaries follow domain/feature separation -- [ ] Custom providers use proper injection tokens (avoid string tokens) - -### Testing & Mocking -- [ ] Test modules use minimal, focused provider mocks -- [ ] TypeORM repositories use getRepositoryToken(Entity) for mocking -- [ ] No actual database dependencies in unit tests -- [ ] All async operations are properly awaited in tests -- [ ] JwtService and external dependencies are mocked appropriately - -### Database Integration (TypeORM Focus) -- [ ] Entity decorators use correct syntax (@Column() not @Column('description')) -- [ ] Connection errors don't crash the entire application -- [ ] Multiple database connections use named connections -- [ ] Database connections have proper error handling and retry logic -- [ ] Entities are properly registered in TypeOrmModule.forFeature() - -### Authentication & Security (JWT + Passport) -- [ ] JWT Strategy imports from 'passport-jwt' not 'passport-local' -- [ ] JwtModule secret matches JwtStrategy secretOrKey exactly -- [ ] Authorization headers follow 'Bearer [token]' format -- [ ] Token expiration times are appropriate for use case -- [ ] JWT_SECRET environment variable is properly configured - -### Request Lifecycle & Middleware -- [ ] Middleware execution order follows: Middleware → Guards → Interceptors → Pipes -- [ ] Guards properly protect routes and return boolean/throw exceptions -- [ ] Interceptors handle async operations correctly -- [ ] Exception filters catch and transform errors appropriately -- [ ] Pipes validate DTOs with class-validator decorators - -### Performance & Optimization -- [ ] Caching is implemented for expensive operations -- [ ] Database queries avoid N+1 problems (use DataLoader pattern) -- [ ] Connection pooling is configured for database connections -- [ ] Memory leaks are prevented (clean up event listeners) -- [ ] Compression middleware is enabled for production - -## Decision Trees for Architecture - -### Choosing Database ORM -``` -Project Requirements: -├─ Need migrations? → TypeORM or Prisma -├─ NoSQL database? → Mongoose -├─ Type safety priority? → Prisma -├─ Complex relations? → TypeORM -└─ Existing database? → TypeORM (better legacy support) -``` - -### Module Organization Strategy -``` -Feature Complexity: -├─ Simple CRUD → Single module with controller + service -├─ Domain logic → Separate domain module + infrastructure -├─ Shared logic → Create shared module with exports -├─ Microservice → Separate app with message patterns -└─ External API → Create client module with HttpModule -``` - -### Testing Strategy Selection -``` -Test Type Required: -├─ Business logic → Unit tests with mocks -├─ API contracts → Integration tests with test database -├─ User flows → E2E tests with Supertest -├─ Performance → Load tests with k6 or Artillery -└─ Security → OWASP ZAP or security middleware tests -``` - -### Authentication Method -``` -Security Requirements: -├─ Stateless API → JWT with refresh tokens -├─ Session-based → Express sessions with Redis -├─ OAuth/Social → Passport with provider strategies -├─ Multi-tenant → JWT with tenant claims -└─ Microservices → Service-to-service auth with mTLS -``` - -### Caching Strategy -``` -Data Characteristics: -├─ User-specific → Redis with user key prefix -├─ Global data → In-memory cache with TTL -├─ Database results → Query result cache -├─ Static assets → CDN with cache headers -└─ Computed values → Memoization decorators -``` - -## Performance Optimization - -### Caching Strategies -- Use built-in cache manager for response caching -- Implement cache interceptors for expensive operations -- Configure TTL based on data volatility -- Use Redis for distributed caching - -### Database Optimization -- Use DataLoader pattern for N+1 query problems -- Implement proper indexes on frequently queried fields -- Use query builder for complex queries vs. ORM methods -- Enable query logging in development for analysis - -### Request Processing -- Implement compression middleware -- Use streaming for large responses -- Configure proper rate limiting -- Enable clustering for multi-core utilization - -## External Resources - -### Core Documentation -- [Nest.js Documentation](https://docs.nestjs.com) -- [Nest.js CLI](https://docs.nestjs.com/cli/overview) -- [Nest.js Recipes](https://docs.nestjs.com/recipes) - -### Testing Resources -- [Jest Documentation](https://jestjs.io/docs/getting-started) -- [Supertest](https://github.com/visionmedia/supertest) -- [Testing Best Practices](https://github.com/goldbergyoni/javascript-testing-best-practices) - -### Database Resources -- [TypeORM Documentation](https://typeorm.io) -- [Mongoose Documentation](https://mongoosejs.com) - -### Authentication -- [Passport.js Strategies](http://www.passportjs.org) -- [JWT Best Practices](https://tools.ietf.org/html/rfc8725) - -## Quick Reference Patterns - -### Dependency Injection Tokens -```typescript -// Custom provider token -export const CONFIG_OPTIONS = Symbol('CONFIG_OPTIONS'); - -// Usage in module -@Module({ - providers: [ - { - provide: CONFIG_OPTIONS, - useValue: { apiUrl: 'https://api.example.com' } - } - ] -}) -``` - -### Global Module Pattern -```typescript -@Global() -@Module({ - providers: [GlobalService], - exports: [GlobalService], -}) -export class GlobalModule {} -``` - -### Dynamic Module Pattern -```typescript -@Module({}) -export class ConfigModule { - static forRoot(options: ConfigOptions): DynamicModule { - return { - module: ConfigModule, - providers: [ - { - provide: 'CONFIG_OPTIONS', - useValue: options, - }, - ], - }; - } -} -``` - -## Success Metrics -- ✅ Problem correctly identified and located in module structure -- ✅ Solution follows Nest.js architectural patterns -- ✅ All tests pass (unit, integration, e2e) -- ✅ No circular dependencies introduced -- ✅ Performance metrics maintained or improved -- ✅ Code follows established project conventions -- ✅ Proper error handling implemented -- ✅ Security best practices applied -- ✅ Documentation updated for API changes \ No newline at end of file diff --git a/nextjs-best-practices/skill.md b/nextjs-best-practices/skill.md deleted file mode 100644 index 044a3bb..0000000 --- a/nextjs-best-practices/skill.md +++ /dev/null @@ -1,203 +0,0 @@ ---- -name: nextjs-best-practices -description: Next.js App Router principles. Server Components, data fetching, routing patterns. -allowed-tools: Read, Write, Edit, Glob, Grep ---- - -# Next.js Best Practices - -> Principles for Next.js App Router development. - ---- - -## 1. Server vs Client Components - -### Decision Tree - -``` -Does it need...? -│ -├── useState, useEffect, event handlers -│ └── Client Component ('use client') -│ -├── Direct data fetching, no interactivity -│ └── Server Component (default) -│ -└── Both? - └── Split: Server parent + Client child -``` - -### By Default - -| Type | Use | -|------|-----| -| **Server** | Data fetching, layout, static content | -| **Client** | Forms, buttons, interactive UI | - ---- - -## 2. Data Fetching Patterns - -### Fetch Strategy - -| Pattern | Use | -|---------|-----| -| **Default** | Static (cached at build) | -| **Revalidate** | ISR (time-based refresh) | -| **No-store** | Dynamic (every request) | - -### Data Flow - -| Source | Pattern | -|--------|---------| -| Database | Server Component fetch | -| API | fetch with caching | -| User input | Client state + server action | - ---- - -## 3. Routing Principles - -### File Conventions - -| File | Purpose | -|------|---------| -| `page.tsx` | Route UI | -| `layout.tsx` | Shared layout | -| `loading.tsx` | Loading state | -| `error.tsx` | Error boundary | -| `not-found.tsx` | 404 page | - -### Route Organization - -| Pattern | Use | -|---------|-----| -| Route groups `(name)` | Organize without URL | -| Parallel routes `@slot` | Multiple same-level pages | -| Intercepting `(.)` | Modal overlays | - ---- - -## 4. API Routes - -### Route Handlers - -| Method | Use | -|--------|-----| -| GET | Read data | -| POST | Create data | -| PUT/PATCH | Update data | -| DELETE | Remove data | - -### Best Practices - -- Validate input with Zod -- Return proper status codes -- Handle errors gracefully -- Use Edge runtime when possible - ---- - -## 5. Performance Principles - -### Image Optimization - -- Use next/image component -- Set priority for above-fold -- Provide blur placeholder -- Use responsive sizes - -### Bundle Optimization - -- Dynamic imports for heavy components -- Route-based code splitting (automatic) -- Analyze with bundle analyzer - ---- - -## 6. Metadata - -### Static vs Dynamic - -| Type | Use | -|------|-----| -| Static export | Fixed metadata | -| generateMetadata | Dynamic per-route | - -### Essential Tags - -- title (50-60 chars) -- description (150-160 chars) -- Open Graph images -- Canonical URL - ---- - -## 7. Caching Strategy - -### Cache Layers - -| Layer | Control | -|-------|---------| -| Request | fetch options | -| Data | revalidate/tags | -| Full route | route config | - -### Revalidation - -| Method | Use | -|--------|-----| -| Time-based | `revalidate: 60` | -| On-demand | `revalidatePath/Tag` | -| No cache | `no-store` | - ---- - -## 8. Server Actions - -### Use Cases - -- Form submissions -- Data mutations -- Revalidation triggers - -### Best Practices - -- Mark with 'use server' -- Validate all inputs -- Return typed responses -- Handle errors - ---- - -## 9. Anti-Patterns - -| ❌ Don't | ✅ Do | -|----------|-------| -| 'use client' everywhere | Server by default | -| Fetch in client components | Fetch in server | -| Skip loading states | Use loading.tsx | -| Ignore error boundaries | Use error.tsx | -| Large client bundles | Dynamic imports | - ---- - -## 10. Project Structure - -``` -app/ -├── (marketing)/ # Route group -│ └── page.tsx -├── (dashboard)/ -│ ├── layout.tsx # Dashboard layout -│ └── page.tsx -├── api/ -│ └── [resource]/ -│ └── route.ts -└── components/ - └── ui/ -``` - ---- - -> **Remember:** Server Components are the default for a reason. Start there, add client only when needed. diff --git a/nextjs/skill.md b/nextjs/skill.md deleted file mode 100644 index becad63..0000000 --- a/nextjs/skill.md +++ /dev/null @@ -1,1745 +0,0 @@ ---- -name: nextjs -description: | - Build Next.js 16 apps with App Router, Server Components/Actions, Cache Components ("use cache"), and async route params. Includes proxy.ts and React 19.2. Prevents 25 documented errors. - - Use when: building Next.js 16 projects, or troubleshooting async params (Promise types), "use cache" directives, parallel route 404s, Turbopack issues, i18n caching, navigation throttling. -user-invocable: true -allowed-tools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"] ---- - -# Next.js App Router - Production Patterns - -**Version**: Next.js 16.1.1 -**React Version**: 19.2.3 -**Node.js**: 20.9+ -**Last Verified**: 2026-01-09 - ---- - -## Table of Contents - -1. [When to Use This Skill](#when-to-use-this-skill) -2. [When NOT to Use This Skill](#when-not-to-use-this-skill) -3. [Security Advisories (December 2025)](#security-advisories-december-2025) -4. [Next.js 16.1 Updates](#nextjs-161-updates-december-2025) -5. [Next.js 16 Breaking Changes](#nextjs-16-breaking-changes) -6. [Cache Components & Caching APIs](#cache-components--caching-apis) -7. [Route Handlers (Next.js 16 Updates)](#route-handlers-nextjs-16-updates) -8. [Proxy vs Middleware](#proxy-vs-middleware) -9. [Parallel Routes - default.js Required](#parallel-routes---defaultjs-required-breaking) -10. [React 19.2 Features](#react-192-features) -11. [Turbopack (Stable in Next.js 16)](#turbopack-stable-in-nextjs-16) -12. [Common Errors & Solutions](#common-errors--solutions) -13. [Templates & Resources](#templates--resources) - ---- - -## When to Use This Skill - -**Focus**: Next.js 16 breaking changes and knowledge gaps (December 2024+). - -Use this skill when you need: - -- **Next.js 16 breaking changes** (async params, proxy.ts, parallel routes default.js, removed features) -- **Cache Components** with `"use cache"` directive (NEW in Next.js 16) -- **New caching APIs**: `revalidateTag()`, `updateTag()`, `refresh()` (Updated in Next.js 16) -- **Migration from Next.js 15 to 16** (avoid breaking change errors) -- **Async route params** (`params`, `searchParams`, `cookies()`, `headers()` now async) -- **Parallel routes with default.js** (REQUIRED in Next.js 16) -- **React 19.2 features** (View Transitions, `useEffectEvent()`, React Compiler) -- **Turbopack** (stable and default in Next.js 16) -- **Image defaults changed** (TTL, sizes, qualities in Next.js 16) -- **Error prevention** (25 documented Next.js 16 errors with solutions) - ---- - -## When NOT to Use This Skill - -Do NOT use this skill for: - -- **Cloudflare Workers deployment** → Use `cloudflare-nextjs` skill instead -- **Pages Router patterns** → This skill covers App Router ONLY (Pages Router is legacy) -- **Authentication libraries** → Use `clerk-auth`, `better-auth`, or other auth-specific skills -- **Database integration** → Use `cloudflare-d1`, `drizzle-orm-d1`, or database-specific skills -- **UI component libraries** → Use `tailwind-v4-shadcn` skill for Tailwind + shadcn/ui -- **State management** → Use `zustand-state-management`, `tanstack-query` skills -- **Form libraries** → Use `react-hook-form-zod` skill -- **Vercel-specific features** → Refer to Vercel platform documentation -- **Next.js Enterprise features** (ISR, DPR) → Refer to Next.js Enterprise docs -- **Deployment configuration** → Use platform-specific deployment skills - -**Relationship with Other Skills**: -- **cloudflare-nextjs**: For deploying Next.js to Cloudflare Workers (use BOTH skills together if deploying to Cloudflare) -- **tailwind-v4-shadcn**: For Tailwind v4 + shadcn/ui setup (composable with this skill) -- **clerk-auth**: For Clerk authentication in Next.js (composable with this skill) -- **better-auth**: For Better Auth integration (composable with this skill) - ---- - -## Security Advisories (December 2025) - -**CRITICAL**: Three security vulnerabilities were disclosed in December 2025 affecting Next.js with React Server Components: - -| CVE | Severity | Affected | Description | -|-----|----------|----------|-------------| -| **CVE-2025-66478** | CRITICAL (10.0) | 15.x, 16.x | Server Component arbitrary code execution | -| **CVE-2025-55184** | HIGH | 13.x-16.x | Denial of Service via malformed request | -| **CVE-2025-55183** | MEDIUM | 13.x-16.x | Source code exposure in error responses | - -**Action Required**: Upgrade to Next.js 16.1.1 or later immediately. - -```bash -npm update next -# Verify: npm list next should show 16.1.1+ -``` - -**References**: -- https://nextjs.org/security -- https://github.com/vercel/next.js/security/advisories - ---- - -## Next.js 16.1 Updates (December 2025) - -**New in 16.1**: -- **Turbopack File System Caching (STABLE)**: Now enabled by default in development -- **Next.js Bundle Analyzer**: New experimental feature for bundle analysis -- **Improved Debugging**: Enhanced `next dev --inspect` support -- **Security Fixes**: Addresses CVE-2025-66478, CVE-2025-55184, CVE-2025-55183 - ---- - -## Next.js 16 Breaking Changes - -**IMPORTANT**: Next.js 16 introduces multiple breaking changes. Read this section carefully if migrating from Next.js 15 or earlier. - -### 1. Async Route Parameters (BREAKING) - -**Breaking Change**: `params`, `searchParams`, `cookies()`, `headers()`, `draftMode()` are now **async** and must be awaited. - -**Before (Next.js 15)**: -```typescript -// ❌ This no longer works in Next.js 16 -export default function Page({ params, searchParams }: { - params: { slug: string } - searchParams: { query: string } -}) { - const slug = params.slug // ❌ Error: params is a Promise - const query = searchParams.query // ❌ Error: searchParams is a Promise - return
{slug}
-} -``` - -**After (Next.js 16)**: -```typescript -// ✅ Correct: await params and searchParams -export default async function Page({ params, searchParams }: { - params: Promise<{ slug: string }> - searchParams: Promise<{ query: string }> -}) { - const { slug } = await params // ✅ Await the promise - const { query } = await searchParams // ✅ Await the promise - return
{slug}
-} -``` - -**Applies to**: -- `params` in pages, layouts, route handlers -- `searchParams` in pages -- `cookies()` from `next/headers` -- `headers()` from `next/headers` -- `draftMode()` from `next/headers` - -**Migration**: -```typescript -// ❌ Before -import { cookies, headers } from 'next/headers' - -export function MyComponent() { - const cookieStore = cookies() // ❌ Sync access - const headersList = headers() // ❌ Sync access -} - -// ✅ After -import { cookies, headers } from 'next/headers' - -export async function MyComponent() { - const cookieStore = await cookies() // ✅ Async access - const headersList = await headers() // ✅ Async access -} -``` - -**Codemod**: Run `npx @next/codemod@canary upgrade latest` to automatically migrate. - -**Codemod Limitations** (Community-sourced): -The official codemod handles ~80% of async API migrations but misses edge cases: -- Async APIs accessed in custom hooks -- Conditional logic accessing params -- Components imported from external packages -- Complex server actions with multiple async calls - -After running the codemod, search for `@next-codemod-error` comments marking places it couldn't auto-fix. - -**Manual Migration for Client Components**: -```typescript -// For client components, use React.use() to unwrap promises -'use client'; - -import { use } from 'react'; - -export default function ClientComponent({ - params -}: { - params: Promise<{ id: string }> -}) { - const { id } = use(params); // Unwrap Promise in client - return
{id}
; -} -``` - -**See Template**: `templates/app-router-async-params.tsx` - ---- - -### 2. Middleware → Proxy Migration (BREAKING) - -**Breaking Change**: `middleware.ts` is **deprecated** in Next.js 16. Use `proxy.ts` instead. - -**Why the Change**: `proxy.ts` makes the network boundary explicit by running on Node.js runtime (not Edge runtime). This provides better clarity between edge middleware and server-side proxies. - -**Migration Steps**: - -1. **Rename file**: `middleware.ts` → `proxy.ts` -2. **Rename function**: `middleware` → `proxy` -3. **Update config**: `matcher` → `config.matcher` (same syntax) - -**Before (Next.js 15)**: -```typescript -// middleware.ts ❌ Deprecated in Next.js 16 -import { NextResponse } from 'next/server' -import type { NextRequest } from 'next/server' - -export function middleware(request: NextRequest) { - const response = NextResponse.next() - response.headers.set('x-custom-header', 'value') - return response -} - -export const config = { - matcher: '/api/:path*', -} -``` - -**After (Next.js 16)**: -```typescript -// proxy.ts ✅ New in Next.js 16 -import { NextResponse } from 'next/server' -import type { NextRequest } from 'next/server' - -export function proxy(request: NextRequest) { - const response = NextResponse.next() - response.headers.set('x-custom-header', 'value') - return response -} - -export const config = { - matcher: '/api/:path*', -} -``` - -**Note**: `middleware.ts` still works in Next.js 16 but is deprecated. Migrate to `proxy.ts` for future compatibility. - -**See Template**: `templates/proxy-migration.ts` -**See Reference**: `references/proxy-vs-middleware.md` - ---- - -### 3. Parallel Routes Require `default.js` (BREAKING) - -**Breaking Change**: Parallel routes now **require** explicit `default.js` files. Without them, routes will fail during soft navigation. - -**Structure**: -``` -app/ -├── @auth/ -│ ├── login/ -│ │ └── page.tsx -│ └── default.tsx ← REQUIRED in Next.js 16 -├── @dashboard/ -│ ├── overview/ -│ │ └── page.tsx -│ └── default.tsx ← REQUIRED in Next.js 16 -└── layout.tsx -``` - -**Layout**: -```typescript -// app/layout.tsx -export default function Layout({ - children, - auth, - dashboard, -}: { - children: React.ReactNode - auth: React.ReactNode - dashboard: React.ReactNode -}) { - return ( - - - {auth} - {dashboard} - {children} - - - ) -} -``` - -**Default Fallback** (REQUIRED): -```typescript -// app/@auth/default.tsx -export default function AuthDefault() { - return null // or or redirect -} - -// app/@dashboard/default.tsx -export default function DashboardDefault() { - return null -} -``` - -**Why Required**: Next.js 16 changed how parallel routes handle soft navigation. Without `default.js`, unmatched slots will error during client-side navigation. - -**See Template**: `templates/parallel-routes-with-default.tsx` - ---- - -### 4. Removed Features (BREAKING) - -**The following features are REMOVED in Next.js 16**: - -1. **AMP Support** - Entirely removed. Migrate to standard pages. -2. **`next lint` command** - Use ESLint or Biome directly. -3. **`serverRuntimeConfig` and `publicRuntimeConfig`** - Use environment variables instead. -4. **`experimental.ppr` flag** - Evolved into Cache Components. Use `"use cache"` directive. -5. **Automatic `scroll-behavior: smooth`** - Add manually if needed. -6. **Node.js 18 support** - Minimum version is now **20.9+**. - -**Migration**: -- **AMP**: Convert AMP pages to standard pages or use separate AMP implementation. -- **Linting**: Run `npx eslint .` or `npx biome lint .` directly. -- **Config**: Replace `serverRuntimeConfig` with `process.env.VARIABLE`. -- **PPR**: Migrate from `experimental.ppr` to `"use cache"` directive (see Cache Components section). - ---- - -### 5. Version Requirements (BREAKING) - -**Next.js 16 requires**: - -- **Node.js**: 20.9+ (Node.js 18 no longer supported) -- **TypeScript**: 5.1+ (if using TypeScript) -- **React**: 19.2+ (automatically installed with Next.js 16) -- **Browsers**: Chrome 111+, Safari 16.4+, Firefox 109+, Edge 111+ - -**Check Versions**: -```bash -node --version # Should be 20.9+ -npm --version # Should be 10+ -npx next --version # Should be 16.0.0+ -``` - -**Upgrade Node.js**: -```bash -# Using nvm -nvm install 20 -nvm use 20 -nvm alias default 20 - -# Using Homebrew (macOS) -brew install node@20 - -# Using apt (Ubuntu/Debian) -sudo apt update -sudo apt install nodejs npm -``` - ---- - -### 6. Image Defaults Changed (BREAKING) - -**Next.js 16 changed `next/image` defaults**: - -| Setting | Next.js 15 | Next.js 16 | -|---------|------------|------------| -| **TTL** (cache duration) | 60 seconds | 4 hours | -| **imageSizes** | `[16, 32, 48, 64, 96, 128, 256, 384]` | `[640, 750, 828, 1080, 1200]` (reduced) | -| **qualities** | `[75, 90, 100]` | `[75]` (single quality) | - -**Impact**: -- Images cache longer (4 hours vs 60 seconds) -- Fewer image sizes generated (smaller builds, but less granular) -- Single quality (75) generated instead of multiple - -**Override Defaults** (if needed): -```typescript -// next.config.ts -import type { NextConfig } from 'next' - -const config: NextConfig = { - images: { - minimumCacheTTL: 60, // Revert to 60 seconds - deviceSizes: [640, 750, 828, 1080, 1200, 1920], // Add larger sizes - imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // Restore old sizes - formats: ['image/webp'], // Default - }, -} - -export default config -``` - -**See Template**: `templates/image-optimization.tsx` - ---- - -## Cache Components & Caching APIs - -**NEW in Next.js 16**: Cache Components introduce **opt-in caching** with the `"use cache"` directive, replacing implicit caching from Next.js 15. - -### 1. Overview - -**What Changed**: -- **Next.js 15**: Implicit caching (all Server Components cached by default) -- **Next.js 16**: Opt-in caching with `"use cache"` directive - -**Why the Change**: Explicit caching gives developers more control and makes caching behavior predictable. - -**Important Caching Defaults** (Community-sourced): - -| Feature | Next.js 14 | Next.js 15/16 | -|---------|-----------|---------------| -| **fetch() requests** | Cached by default | NOT cached by default | -| **Router Cache (dynamic pages)** | Cached on client | NOT cached by default | -| **Router Cache (static pages)** | Cached | Still cached | -| **Route Handlers (GET)** | Cached | Dynamic by default | - -**Best Practice**: Default to dynamic in Next.js 16. Start with no caching and add it where beneficial, rather than debugging unexpected cache hits. Always test with production builds - the development server behaves differently. - -**Cache Components enable**: -- Component-level caching (cache specific components, not entire pages) -- Function-level caching (cache expensive computations) -- Page-level caching (cache entire pages selectively) -- **Partial Prerendering (PPR)** - Cache static parts, render dynamic parts on-demand - ---- - -### 2. `"use cache"` Directive - -**Syntax**: Add `"use cache"` at the top of a Server Component, function, or route handler. - -**Component-level caching**: -```typescript -// app/components/expensive-component.tsx -'use cache' - -export async function ExpensiveComponent() { - const data = await fetch('https://api.example.com/data') - const json = await data.json() - - return ( -
-

{json.title}

-

{json.description}

-
- ) -} -``` - -**Function-level caching**: -```typescript -// lib/data.ts -'use cache' - -export async function getExpensiveData(id: string) { - const response = await fetch(`https://api.example.com/items/${id}`) - return response.json() -} - -// Usage in component -import { getExpensiveData } from '@/lib/data' - -export async function ProductPage({ params }: { params: Promise<{ id: string }> }) { - const { id } = await params - const product = await getExpensiveData(id) // Cached - - return
{product.name}
-} -``` - -**Page-level caching**: -```typescript -// app/blog/[slug]/page.tsx -'use cache' - -export async function generateStaticParams() { - const posts = await fetch('https://api.example.com/posts').then(r => r.json()) - return posts.map((post: { slug: string }) => ({ slug: post.slug })) -} - -export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) { - const { slug } = await params - const post = await fetch(`https://api.example.com/posts/${slug}`).then(r => r.json()) - - return ( -
-

{post.title}

-
{post.content}
-
- ) -} -``` - -**See Template**: `templates/cache-component-use-cache.tsx` - ---- - -### 3. Partial Prerendering (PPR) - -**PPR** allows caching static parts of a page while rendering dynamic parts on-demand. - -**Pattern**: -```typescript -// app/dashboard/page.tsx - -// Static header (cached) -'use cache' -async function StaticHeader() { - return
My App
-} - -// Dynamic user info (not cached) -async function DynamicUserInfo() { - const cookieStore = await cookies() - const userId = cookieStore.get('userId')?.value - const user = await fetch(`/api/users/${userId}`).then(r => r.json()) - - return
Welcome, {user.name}
-} - -// Page combines both -export default function Dashboard() { - return ( -
- {/* Cached */} - {/* Dynamic */} -
- ) -} -``` - -**When to Use PPR**: -- Page has both static and dynamic content -- Want to cache layout/header/footer but render user-specific content -- Need fast initial load (static parts) + personalization (dynamic parts) - -**See Reference**: `references/cache-components-guide.md` - ---- - -### 4. `revalidateTag()` - Updated API - -**BREAKING CHANGE**: `revalidateTag()` now requires a **second argument** (`cacheLife` profile) for stale-while-revalidate behavior. - -**Before (Next.js 15)**: -```typescript -import { revalidateTag } from 'next/cache' - -export async function updatePost(id: string) { - await fetch(`/api/posts/${id}`, { method: 'PATCH' }) - revalidateTag('posts') // ❌ Only one argument in Next.js 15 -} -``` - -**After (Next.js 16)**: -```typescript -import { revalidateTag } from 'next/cache' - -export async function updatePost(id: string) { - await fetch(`/api/posts/${id}`, { method: 'PATCH' }) - revalidateTag('posts', 'max') // ✅ Second argument required in Next.js 16 -} -``` - -**Built-in Cache Life Profiles**: -- `'max'` - Maximum staleness (recommended for most use cases) -- `'hours'` - Stale after hours -- `'days'` - Stale after days -- `'weeks'` - Stale after weeks -- `'default'` - Default cache behavior - -**Custom Cache Life Profile**: -```typescript -revalidateTag('posts', { - stale: 3600, // Stale after 1 hour (seconds) - revalidate: 86400, // Revalidate every 24 hours (seconds) - expire: false, // Never expire (optional) -}) -``` - -**Pattern in Server Actions**: -```typescript -'use server' - -import { revalidateTag } from 'next/cache' - -export async function createPost(formData: FormData) { - const title = formData.get('title') as string - const content = formData.get('content') as string - - await fetch('/api/posts', { - method: 'POST', - body: JSON.stringify({ title, content }), - }) - - revalidateTag('posts', 'max') // ✅ Revalidate with max staleness -} -``` - -**See Template**: `templates/revalidate-tag-cache-life.ts` - ---- - -### 5. `updateTag()` - NEW API (Server Actions Only) - -**NEW in Next.js 16**: `updateTag()` provides **read-your-writes semantics** for Server Actions. - -**What it does**: -- Expires cache immediately -- Refreshes data within the same request -- Shows updated data right after mutation (no stale data) - -**Difference from `revalidateTag()`**: -- `revalidateTag()`: **Stale-while-revalidate** (shows stale data, revalidates in background) -- `updateTag()`: **Immediate refresh** (expires cache, fetches fresh data in same request) - -**Use Case**: Forms, user settings, or any mutation where user expects immediate feedback. - -**Pattern**: -```typescript -'use server' - -import { updateTag } from 'next/cache' - -export async function updateUserProfile(formData: FormData) { - const name = formData.get('name') as string - const email = formData.get('email') as string - - // Update database - await db.users.update({ name, email }) - - // Immediately refresh cache (read-your-writes) - updateTag('user-profile') - - // User sees updated data immediately (no stale data) -} -``` - -**When to Use**: -- **`updateTag()`**: User settings, profile updates, critical mutations (immediate feedback) -- **`revalidateTag()`**: Blog posts, product listings, non-critical updates (background revalidation) - -**See Template**: `templates/server-action-update-tag.ts` - ---- - -### 6. `refresh()` - NEW API (Server Actions Only) - -**NEW in Next.js 16**: `refresh()` refreshes **uncached data only** (complements client-side `router.refresh()`). - -**When to Use**: -- Refresh dynamic data without affecting cached data -- Complement `router.refresh()` on server side - -**Pattern**: -```typescript -'use server' - -import { refresh } from 'next/cache' - -export async function refreshDashboard() { - // Refresh uncached data (e.g., real-time metrics) - refresh() - - // Cached data (e.g., static header) remains cached -} -``` - -**Difference from `revalidateTag()` and `updateTag()`**: -- `refresh()`: Only refreshes **uncached** data -- `revalidateTag()`: Revalidates **specific tagged** data (stale-while-revalidate) -- `updateTag()`: Immediately expires and refreshes **specific tagged** data - -**See Reference**: `references/cache-components-guide.md` - ---- - ---- - -## Route Handlers (Next.js 16 Updates) - -### Async Params in Route Handlers (BREAKING) - -**IMPORTANT**: `params` and `headers()` are now async in Next.js 16 route handlers. - -**Example**: -```typescript -// app/api/posts/[id]/route.ts -import { NextResponse } from 'next/server' -import { headers } from 'next/headers' - -export async function GET( - request: Request, - { params }: { params: Promise<{ id: string }> } -) { - const { id } = await params // ✅ Await params in Next.js 16 - const headersList = await headers() // ✅ Await headers in Next.js 16 - - const post = await db.posts.findUnique({ where: { id } }) - - return NextResponse.json(post) -} -``` - -**See Template**: `templates/route-handler-api.ts` - ---- - -## Proxy vs Middleware - -**Next.js 16 introduces `proxy.ts`** to replace `middleware.ts`. - -### Why the Change? - -- **`middleware.ts`**: Runs on Edge runtime (limited Node.js APIs) -- **`proxy.ts`**: Runs on Node.js runtime (full Node.js APIs) - -The new `proxy.ts` makes the network boundary explicit and provides more flexibility. - -### Migration - -**Before (middleware.ts)**: -```typescript -// middleware.ts -import { NextResponse } from 'next/server' -import type { NextRequest } from 'next/server' - -export function middleware(request: NextRequest) { - // Check auth - const token = request.cookies.get('token') - - if (!token) { - return NextResponse.redirect(new URL('/login', request.url)) - } - - return NextResponse.next() -} - -export const config = { - matcher: '/dashboard/:path*', -} -``` - -**After (proxy.ts)**: -```typescript -// proxy.ts -import { NextResponse } from 'next/server' -import type { NextRequest } from 'next/server' - -export function proxy(request: NextRequest) { - // Check auth - const token = request.cookies.get('token') - - if (!token) { - return NextResponse.redirect(new URL('/login', request.url)) - } - - return NextResponse.next() -} - -export const config = { - matcher: '/dashboard/:path*', -} -``` - -**See Template**: `templates/proxy-migration.ts` -**See Reference**: `references/proxy-vs-middleware.md` - ---- - -## Parallel Routes - default.js Required (BREAKING) - -**Breaking Change in Next.js 16**: Parallel routes now **require** explicit `default.js` files. - -**Structure**: -``` -app/ -├── @modal/ -│ ├── login/page.tsx -│ └── default.tsx ← REQUIRED in Next.js 16 -├── @feed/ -│ ├── trending/page.tsx -│ └── default.tsx ← REQUIRED in Next.js 16 -└── layout.tsx -``` - -**Default Files (REQUIRED)**: -```typescript -// app/@modal/default.tsx -export default function ModalDefault() { - return null // or or redirect -} -``` - -**Why Required**: Next.js 16 changed soft navigation handling. Without `default.js`, unmatched slots error during client-side navigation. - -**Advanced Edge Case** (Community-sourced): -Even WITH `default.js` files, hard navigating or refreshing routes with parallel routes can return 404 errors. The workaround is adding a catch-all route. - -**Source**: [GitHub Issue #48090](https://github.com/vercel/next.js/issues/48090), [#73939](https://github.com/vercel/next.js/issues/73939) - -**Workaround**: -```typescript -// app/@modal/[...catchAll]/page.tsx -export default function CatchAll() { - return null; -} - -// OR use catch-all in default.tsx -// app/@modal/default.tsx -export default function ModalDefault({ params }: { params: { catchAll?: string[] } }) { - return null; // Handles all unmatched routes -} -``` - -**See Template**: `templates/parallel-routes-with-default.tsx` - ---- - -## React 19.2 Features - -Next.js 16 integrates React 19.2, which includes new features from React Canary. - -### 1. View Transitions - -**Use Case**: Smooth animations between page transitions. - -```typescript -'use client' - -import { useRouter } from 'next/navigation' -import { startTransition } from 'react' - -export function NavigationLink({ href, children }: { href: string; children: React.ReactNode }) { - const router = useRouter() - - function handleClick(e: React.MouseEvent) { - e.preventDefault() - - // Wrap navigation in startTransition for View Transitions - startTransition(() => { - router.push(href) - }) - } - - return {children} -} -``` - -**With CSS View Transitions API**: -```css -/* app/globals.css */ -@view-transition { - navigation: auto; -} - -/* Animate elements with view-transition-name */ -.page-title { - view-transition-name: page-title; -} -``` - -**See Template**: `templates/view-transitions-react-19.tsx` - ---- - -### 2. `useEffectEvent()` (Experimental) - -**Use Case**: Extract non-reactive logic from `useEffect`. - -```typescript -'use client' - -import { useEffect, experimental_useEffectEvent as useEffectEvent } from 'react' - -export function ChatRoom({ roomId }: { roomId: string }) { - const onConnected = useEffectEvent(() => { - console.log('Connected to room:', roomId) - }) - - useEffect(() => { - const connection = connectToRoom(roomId) - onConnected() // Non-reactive callback - - return () => connection.disconnect() - }, [roomId]) // Only re-run when roomId changes - - return
Chat Room {roomId}
-} -``` - -**Why Use It**: Prevents unnecessary `useEffect` re-runs when callback dependencies change. - ---- - -### 3. React Compiler (Stable) - -**Use Case**: Automatic memoization without `useMemo`, `useCallback`. - -**Enable in next.config.ts**: -```typescript -import type { NextConfig } from 'next' - -const config: NextConfig = { - experimental: { - reactCompiler: true, - }, -} - -export default config -``` - -**Install Plugin**: -```bash -npm install babel-plugin-react-compiler -``` - -**Example** (no manual memoization needed): -```typescript -'use client' - -export function ExpensiveList({ items }: { items: string[] }) { - // React Compiler automatically memoizes this - const filteredItems = items.filter(item => item.length > 3) - - return ( -
    - {filteredItems.map(item => ( -
  • {item}
  • - ))} -
- ) -} -``` - -**See Reference**: `references/react-19-integration.md` - ---- - -## Turbopack (Stable in Next.js 16) - -**NEW**: Turbopack is now the **default bundler** in Next.js 16. - -**Performance Improvements**: -- 2–5× faster production builds -- Up to 10× faster Fast Refresh - -**Opt-out** (if needed): -```bash -npm run build -- --webpack -``` - -**Enable File System Caching** (experimental): -```typescript -// next.config.ts -import type { NextConfig } from 'next' - -const config: NextConfig = { - experimental: { - turbopack: { - fileSystemCaching: true, // Beta: Persist cache between runs - }, - }, -} - -export default config -``` - ---- - -### Turbopack Production Limitations (as of Next.js 16.1) - -**Known Issues**: - -#### 1. Prisma Incompatibility -**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721) - -Turbopack production builds fail with Prisma ORM (v6.5.0+). Error: "The 'path' argument must be of type string." - -**Workaround**: -```bash -# Use webpack for production builds -npm run build -- --webpack -``` - -Or in `next.config.ts`: -```typescript -const config: NextConfig = { - experimental: { - turbo: false, // Disable Turbopack for production - }, -}; -``` - ---- - -#### 2. Source Maps Security Risk -**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721) - -Turbopack currently **always builds production source maps for the browser**, exposing source code in production deployments. - -**Workaround**: -```typescript -// next.config.ts -const config: NextConfig = { - productionBrowserSourceMaps: false, // Disable source maps -}; -``` - -Or exclude `.map` files in deployment: -```bash -# .vercelignore or similar -*.map -``` - ---- - -#### 3. External Module Hash Mismatches (Monorepos) -**Source**: [GitHub Issue #87737](https://github.com/vercel/next.js/issues/87737) - -Turbopack generates external module references with hashes that don't match when `node_modules` structure differs (pnpm, yarn workspaces, monorepos). This causes "Module not found" errors in production builds. - -**Symptoms**: -- Build succeeds locally but fails in CI/CD -- Hash mismatches between bundled references and actual module files - -**Workaround**: -```typescript -// next.config.ts -const config: NextConfig = { - experimental: { - serverExternalPackages: ['package-name'], // Explicitly externalize packages - }, -}; -``` - ---- - -#### 4. Bundle Size Differences (Community-sourced) -**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721) - -Bundle sizes built with Turbopack may differ from webpack builds. This is expected and being optimized as Turbopack matures. - ---- - -## Common Errors & Solutions - -### 1. Error: `params` is a Promise - -**Error**: -``` -Type 'Promise<{ id: string }>' is not assignable to type '{ id: string }' -``` - -**Cause**: Next.js 16 changed `params` to async. - -**Solution**: Await `params`: -```typescript -// ❌ Before -export default function Page({ params }: { params: { id: string } }) { - const id = params.id -} - -// ✅ After -export default async function Page({ params }: { params: Promise<{ id: string }> }) { - const { id } = await params -} -``` - ---- - -### 2. Error: `searchParams` is a Promise - -**Error**: -``` -Property 'query' does not exist on type 'Promise<{ query: string }>' -``` - -**Cause**: `searchParams` is now async in Next.js 16. - -**Solution**: -```typescript -// ❌ Before -export default function Page({ searchParams }: { searchParams: { query: string } }) { - const query = searchParams.query -} - -// ✅ After -export default async function Page({ searchParams }: { searchParams: Promise<{ query: string }> }) { - const { query } = await searchParams -} -``` - ---- - -### 3. Error: `cookies()` requires await - -**Error**: -``` -'cookies' implicitly has return type 'any' -``` - -**Cause**: `cookies()` is now async in Next.js 16. - -**Solution**: -```typescript -// ❌ Before -import { cookies } from 'next/headers' - -export function MyComponent() { - const cookieStore = cookies() -} - -// ✅ After -import { cookies } from 'next/headers' - -export async function MyComponent() { - const cookieStore = await cookies() -} -``` - ---- - -### 4. Error: Parallel route missing `default.js` - -**Error**: -``` -Error: Parallel route @modal/login was matched but no default.js was found -``` - -**Cause**: Next.js 16 requires `default.js` for all parallel routes. - -**Solution**: Add `default.tsx` files: -```typescript -// app/@modal/default.tsx -export default function ModalDefault() { - return null -} -``` - ---- - -### 5. Error: `revalidateTag()` requires 2 arguments - -**Error**: -``` -Expected 2 arguments, but got 1 -``` - -**Cause**: `revalidateTag()` now requires a `cacheLife` argument in Next.js 16. - -**Solution**: -```typescript -// ❌ Before -revalidateTag('posts') - -// ✅ After -revalidateTag('posts', 'max') -``` - ---- - -### 6. Error: Cannot use React hooks in Server Component - -**Error**: -``` -You're importing a component that needs useState. It only works in a Client Component -``` - -**Cause**: Using React hooks in Server Component. - -**Solution**: Add `'use client'` directive: -```typescript -// ✅ Add 'use client' at the top -'use client' - -import { useState } from 'react' - -export function Counter() { - const [count, setCount] = useState(0) - return -} -``` - ---- - -### 7. Error: `middleware.ts` is deprecated - -**Warning**: -``` -Warning: middleware.ts is deprecated. Use proxy.ts instead. -``` - -**Solution**: Migrate to `proxy.ts`: -```typescript -// Rename: middleware.ts → proxy.ts -// Rename function: middleware → proxy - -export function proxy(request: NextRequest) { - // Same logic -} -``` - ---- - -### 8. Error: Turbopack build failure - -**Error**: -``` -Error: Failed to compile with Turbopack -``` - -**Cause**: Turbopack is now default in Next.js 16. - -**Solution**: Opt out of Turbopack if incompatible: -```bash -npm run build -- --webpack -``` - ---- - -### 9. Error: Invalid `next/image` src - -**Error**: -``` -Invalid src prop (https://example.com/image.jpg) on `next/image`. Hostname "example.com" is not configured under images in your `next.config.js` -``` - -**Solution**: Add remote patterns in `next.config.ts`: -```typescript -const config: NextConfig = { - images: { - remotePatterns: [ - { - protocol: 'https', - hostname: 'example.com', - }, - ], - }, -} -``` - ---- - -### 10. Error: Cannot import Server Component into Client Component - -**Error**: -``` -You're importing a Server Component into a Client Component -``` - -**Solution**: Pass Server Component as children: -```typescript -// ❌ Wrong -'use client' -import { ServerComponent } from './server-component' // Error - -export function ClientComponent() { - return -} - -// ✅ Correct -'use client' - -export function ClientComponent({ children }: { children: React.ReactNode }) { - return
{children}
-} - -// Usage - - {/* Pass as children */} - -``` - ---- - -### 11. Error: `generateStaticParams` not working - -**Cause**: `generateStaticParams` only works with static generation (`export const dynamic = 'force-static'`). - -**Solution**: -```typescript -export const dynamic = 'force-static' - -export async function generateStaticParams() { - const posts = await fetch('/api/posts').then(r => r.json()) - return posts.map((post: { id: string }) => ({ id: post.id })) -} -``` - ---- - -### 12. Error: `fetch()` not caching - -**Cause**: Next.js 16 uses opt-in caching with `"use cache"` directive. - -**Solution**: Add `"use cache"` to component or function: -```typescript -'use cache' - -export async function getPosts() { - const response = await fetch('/api/posts') - return response.json() -} -``` - ---- - -### 13. Error: Route collision with Route Groups - -**Error**: -``` -Error: Conflicting routes: /about and /(marketing)/about -``` - -**Cause**: Route groups create same URL path. - -**Solution**: Ensure route groups don't conflict: -``` -app/ -├── (marketing)/about/page.tsx → /about -└── (shop)/about/page.tsx → ERROR: Duplicate /about - -# Fix: Use different routes -app/ -├── (marketing)/about/page.tsx → /about -└── (shop)/store-info/page.tsx → /store-info -``` - ---- - -### 14. Error: Metadata not updating - -**Cause**: Using dynamic metadata without `generateMetadata()`. - -**Solution**: Use `generateMetadata()` for dynamic pages: -```typescript -export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise { - const { id } = await params - const post = await fetch(`/api/posts/${id}`).then(r => r.json()) - - return { - title: post.title, - description: post.excerpt, - } -} -``` - ---- - -### 15. Error: `next/font` font not loading - -**Cause**: Font variable not applied to HTML element. - -**Solution**: Apply font variable to `` or ``: -```typescript -import { Inter } from 'next/font/google' - -const inter = Inter({ subsets: ['latin'], variable: '--font-inter' }) - -export default function RootLayout({ children }: { children: React.ReactNode }) { - return ( - {/* ✅ Apply variable */} - {children} - - ) -} -``` - ---- - -### 16. Error: Environment variables not available in browser - -**Cause**: Server-only env vars are not exposed to browser. - -**Solution**: Prefix with `NEXT_PUBLIC_` for client-side access: -```bash -# .env -SECRET_KEY=abc123 # Server-only -NEXT_PUBLIC_API_URL=https://api # Available in browser -``` - -```typescript -// Server Component (both work) -const secret = process.env.SECRET_KEY -const apiUrl = process.env.NEXT_PUBLIC_API_URL - -// Client Component (only public vars work) -const apiUrl = process.env.NEXT_PUBLIC_API_URL -``` - ---- - -### 17. Error: Server Action not found - -**Error**: -``` -Error: Could not find Server Action -``` - -**Cause**: Missing `'use server'` directive. - -**Solution**: Add `'use server'`: -```typescript -// ❌ Before -export async function createPost(formData: FormData) { - await db.posts.create({ ... }) -} - -// ✅ After -'use server' - -export async function createPost(formData: FormData) { - await db.posts.create({ ... }) -} -``` - ---- - -### 18. Error: TypeScript path alias not working - -**Cause**: Incorrect `baseUrl` or `paths` in `tsconfig.json`. - -**Solution**: Configure correctly: -```json -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@/*": ["./*"], - "@/components/*": ["./app/components/*"] - } - } -} -``` - -**See Reference**: `references/top-errors.md` - ---- - -### 19. Error: Client-side navigation throttled with multiple redirects -**Error**: `Throttling navigation to prevent the browser from hanging` -**Source**: [GitHub Issue #87245](https://github.com/vercel/next.js/issues/87245) - -**Cause**: When `proxy.ts` (or `middleware.ts`) performs a redirect to add query params AND a Server Component also calls `redirect()` to add different query params, client-side navigation via `` fails in production builds. This is a regression from Next.js 14 to 16. - -**Symptoms**: -- Works in `next dev` (development mode) -- Works with direct URL access (full page load) -- Fails with client-side navigation via `` in production build -- Prefetch causes infinite redirect loop - -**Solution**: Disable prefetch on links that navigate to pages with redirect logic: -```typescript -// ✅ Workaround: Disable prefetch - - Navigate - -``` - ---- - -### 20. Error: Cache Components fail with i18n dynamic segments -**Error**: Route becomes dynamic despite `generateStaticParams` -**Source**: [GitHub Issue #86870](https://github.com/vercel/next.js/issues/86870) - -**Cause**: Cache components (`"use cache"` directive) do NOT work on dynamic segments when using internationalization (i18n) frameworks like `intlayer`, `next-intl`, or `lingui`. Accessing `params` forces the route to be dynamic, even with `generateStaticParams` at the layout level. - -**Why It Happens**: Every i18n framework requires accessing `params` to get the locale. Accessing `params` is an async call in Next.js 16, which opts the entire page out of caching. - -**Solution**: Add `generateStaticParams` at EACH dynamic segment level: -```typescript -// app/[locale]/[id]/page.tsx -export async function generateStaticParams() { - return [ - { locale: 'en', id: '1' }, - { locale: 'en', id: '2' }, - // ... all combinations - ]; -} - -'use cache' - -export default async function Page({ params }: Props) { - // Now caching works -} -``` - -**Additional Context**: The `[locale]` dynamic segment receives invalid values like `_next` during compilation, causing `RangeError: Incorrect locale information provided` when initializing i18n providers. - ---- - -### 21. Error: instanceof fails for custom error classes in Server Components -**Error**: `instanceof CustomError` returns `false` even though it is CustomError -**Source**: [GitHub Issue #87614](https://github.com/vercel/next.js/issues/87614) - -**Cause**: Module duplication in Server Components causes custom error classes to be loaded twice, creating different prototypes. - -**Solution**: Use `error.name` or `error.constructor.name` instead of `instanceof`: -```typescript -// ❌ Wrong: instanceof doesn't work -try { - throw new CustomError('Test error'); -} catch (error) { - if (error instanceof CustomError) { // ❌ false - // Never reached - } -} - -// ✅ Correct: Use error.name -try { - throw new CustomError('Test error'); -} catch (error) { - if (error instanceof Error && error.name === 'CustomError') { // ✅ true - // Handle CustomError - } -} - -// ✅ Alternative: Use constructor.name -if (error.constructor.name === 'CustomError') { - // Handle CustomError -} -``` - ---- - -### 22. Error: TypeScript doesn't catch non-serializable props to Client Components -**Error**: Runtime error when passing functions/class instances to Client Components -**Source**: [GitHub Issue #86748](https://github.com/vercel/next.js/issues/86748) - -**Cause**: The Next.js TypeScript plugin doesn't catch non-serializable props being passed from Server Components to Client Components. This causes runtime errors that are not detected at compile time. - -**Why It Happens**: Only serializable data (JSON-compatible) can cross the Server/Client boundary. Functions, class instances, and Symbols cannot be serialized. - -**Solution**: Only pass serializable props: -```typescript -// ❌ Wrong: Function not serializable -const user = { - name: 'John', - getProfile: () => console.log('profile'), // ❌ Not serializable -}; - - -// ✅ Correct: Only serializable props -interface SerializableUser { - name: string; - email: string; - // No functions, no class instances, no Symbols -} - -// ✅ Alternative: Create functions in Client Component -'use client'; - -export default function ClientComponent({ user }: { user: { name: string } }) { - const getProfile = () => console.log('profile'); // Define in client - return
{user.name}
; -} -``` - -**Runtime Validation**: -```typescript -import { z } from 'zod'; - -const UserSchema = z.object({ - name: z.string(), - email: z.string(), -}); - -type User = z.infer; -``` - ---- - -### 23. Error: Turbopack production build fails with Prisma -**Error**: `The 'path' argument must be of type string` -**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721) - -**Cause**: Turbopack production builds fail with Prisma ORM (v6.5.0+). - -**Solution**: Use webpack for production builds: -```bash -npm run build -- --webpack -``` - -Or disable Turbopack in config: -```typescript -// next.config.ts -const config: NextConfig = { - experimental: { - turbo: false, - }, -}; -``` - ---- - -### 24. Error: Turbopack exposes source code via source maps -**Error**: Source code visible in production builds -**Source**: [GitHub Discussion #77721](https://github.com/vercel/next.js/discussions/77721) - -**Cause**: Turbopack always builds production source maps for the browser, exposing source code. - -**Solution**: Disable production source maps: -```typescript -// next.config.ts -const config: NextConfig = { - productionBrowserSourceMaps: false, -}; -``` - -Or exclude `.map` files in deployment: -```bash -# .vercelignore -*.map -``` - ---- - -### 25. Error: Module not found in production (Turbopack monorepo) -**Error**: `Module not found` in production despite successful local build -**Source**: [GitHub Issue #87737](https://github.com/vercel/next.js/issues/87737) - -**Cause**: Turbopack generates external module references with hashes that don't match when `node_modules` structure differs (pnpm, yarn workspaces, monorepos). - -**Symptoms**: -- Build succeeds locally but fails in CI/CD -- Hash mismatches between bundled references and actual module files - -**Solution**: Explicitly externalize packages: -```typescript -// next.config.ts -const config: NextConfig = { - experimental: { - serverExternalPackages: ['package-name'], - }, -}; -``` - ---- - -**See Reference**: `references/top-errors.md` - ---- - -## Templates & Resources - -**Next.js 16-Specific Templates** (in `templates/`): -- `app-router-async-params.tsx` - Async params migration patterns -- `parallel-routes-with-default.tsx` - Required default.js files -- `cache-component-use-cache.tsx` - Cache Components with `"use cache"` -- `revalidate-tag-cache-life.ts` - Updated `revalidateTag()` with cacheLife -- `server-action-update-tag.ts` - `updateTag()` for read-your-writes -- `proxy-migration.ts` - Migrate from middleware.ts to proxy.ts -- `view-transitions-react-19.tsx` - React 19.2 View Transitions -- `next.config.ts` - Next.js 16 configuration - -**Bundled References** (in `references/`): -- `next-16-migration-guide.md` - Complete Next.js 15→16 migration guide -- `cache-components-guide.md` - Cache Components deep dive -- `proxy-vs-middleware.md` - Proxy.ts vs middleware.ts -- `async-route-params.md` - Async params breaking change details -- `react-19-integration.md` - React 19.2 features in Next.js 16 -- `top-errors.md` - 18+ common errors with solutions - -**External Documentation**: -- **Next.js 16 Blog**: https://nextjs.org/blog/next-16 -- **Next.js Docs**: https://nextjs.org/docs -- **Context7 MCP**: `/websites/nextjs` for latest reference - ---- - -## Version Compatibility - -| Package | Minimum Version | Recommended | -|---------|----------------|-------------| -| Next.js | 16.0.0 | 16.1.1+ | -| React | 19.2.0 | 19.2.3+ | -| Node.js | 20.9.0 | 20.9.0+ | -| TypeScript | 5.1.0 | 5.7.0+ | -| Turbopack | (built-in) | Stable | - -**Check Versions**: -```bash -./scripts/check-versions.sh -``` - ---- - -## Token Efficiency - -**Estimated Token Savings**: 65-70% - -**Without Skill** (manual setup from docs): -- Read Next.js 16 migration guide: ~5k tokens -- Read App Router docs: ~8k tokens -- Read Server Actions docs: ~4k tokens -- Read Metadata API docs: ~3k tokens -- Trial-and-error fixes: ~8k tokens -- **Total**: ~28k tokens - -**With Skill**: -- Load skill: ~8k tokens -- Use templates: ~2k tokens -- **Total**: ~10k tokens -- **Savings**: ~18k tokens (~64%) - -**Errors Prevented**: 25 documented errors = 100% error prevention - ---- - -## Maintenance - -**Last Verified**: 2026-01-21 -**Skill Version**: 3.1.0 -**Changes**: Added 7 new errors (navigation throttling, i18n caching, Turbopack limitations, instanceof failures, non-serializable props). Expanded async params codemod limitations, caching defaults, and parallel routes edge cases. - -**Next Review**: 2026-04-21 (Quarterly) -**Maintainer**: Jezweb | jeremy@jezweb.net -**Repository**: https://github.com/jezweb/claude-skills - -**Update Triggers**: -- Next.js major/minor releases -- React major releases -- Breaking changes in APIs -- New Turbopack features - -**Version Check**: -```bash -cd skills/nextjs -./scripts/check-versions.sh -``` - ---- - -**End of SKILL.md** diff --git a/nodejs-best-practices/skill.md b/nodejs-best-practices/skill.md deleted file mode 100644 index f5abcac..0000000 --- a/nodejs-best-practices/skill.md +++ /dev/null @@ -1,333 +0,0 @@ ---- -name: nodejs-best-practices -description: Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying. -allowed-tools: Read, Write, Edit, Glob, Grep ---- - -# Node.js Best Practices - -> Principles and decision-making for Node.js development in 2025. -> **Learn to THINK, not memorize code patterns.** - ---- - -## ⚠️ How to Use This Skill - -This skill teaches **decision-making principles**, not fixed code to copy. - -- ASK user for preferences when unclear -- Choose framework/pattern based on CONTEXT -- Don't default to same solution every time - ---- - -## 1. Framework Selection (2025) - -### Decision Tree - -``` -What are you building? -│ -├── Edge/Serverless (Cloudflare, Vercel) -│ └── Hono (zero-dependency, ultra-fast cold starts) -│ -├── High Performance API -│ └── Fastify (2-3x faster than Express) -│ -├── Enterprise/Team familiarity -│ └── NestJS (structured, DI, decorators) -│ -├── Legacy/Stable/Maximum ecosystem -│ └── Express (mature, most middleware) -│ -└── Full-stack with frontend - └── Next.js API Routes or tRPC -``` - -### Comparison Principles - -| Factor | Hono | Fastify | Express | -|--------|------|---------|---------| -| **Best for** | Edge, serverless | Performance | Legacy, learning | -| **Cold start** | Fastest | Fast | Moderate | -| **Ecosystem** | Growing | Good | Largest | -| **TypeScript** | Native | Excellent | Good | -| **Learning curve** | Low | Medium | Low | - -### Selection Questions to Ask: -1. What's the deployment target? -2. Is cold start time critical? -3. Does team have existing experience? -4. Is there legacy code to maintain? - ---- - -## 2. Runtime Considerations (2025) - -### Native TypeScript - -``` -Node.js 22+: --experimental-strip-types -├── Run .ts files directly -├── No build step needed for simple projects -└── Consider for: scripts, simple APIs -``` - -### Module System Decision - -``` -ESM (import/export) -├── Modern standard -├── Better tree-shaking -├── Async module loading -└── Use for: new projects - -CommonJS (require) -├── Legacy compatibility -├── More npm packages support -└── Use for: existing codebases, some edge cases -``` - -### Runtime Selection - -| Runtime | Best For | -|---------|----------| -| **Node.js** | General purpose, largest ecosystem | -| **Bun** | Performance, built-in bundler | -| **Deno** | Security-first, built-in TypeScript | - ---- - -## 3. Architecture Principles - -### Layered Structure Concept - -``` -Request Flow: -│ -├── Controller/Route Layer -│ ├── Handles HTTP specifics -│ ├── Input validation at boundary -│ └── Calls service layer -│ -├── Service Layer -│ ├── Business logic -│ ├── Framework-agnostic -│ └── Calls repository layer -│ -└── Repository Layer - ├── Data access only - ├── Database queries - └── ORM interactions -``` - -### Why This Matters: -- **Testability**: Mock layers independently -- **Flexibility**: Swap database without touching business logic -- **Clarity**: Each layer has single responsibility - -### When to Simplify: -- Small scripts → Single file OK -- Prototypes → Less structure acceptable -- Always ask: "Will this grow?" - ---- - -## 4. Error Handling Principles - -### Centralized Error Handling - -``` -Pattern: -├── Create custom error classes -├── Throw from any layer -├── Catch at top level (middleware) -└── Format consistent response -``` - -### Error Response Philosophy - -``` -Client gets: -├── Appropriate HTTP status -├── Error code for programmatic handling -├── User-friendly message -└── NO internal details (security!) - -Logs get: -├── Full stack trace -├── Request context -├── User ID (if applicable) -└── Timestamp -``` - -### Status Code Selection - -| Situation | Status | When | -|-----------|--------|------| -| Bad input | 400 | Client sent invalid data | -| No auth | 401 | Missing or invalid credentials | -| No permission | 403 | Valid auth, but not allowed | -| Not found | 404 | Resource doesn't exist | -| Conflict | 409 | Duplicate or state conflict | -| Validation | 422 | Schema valid but business rules fail | -| Server error | 500 | Our fault, log everything | - ---- - -## 5. Async Patterns Principles - -### When to Use Each - -| Pattern | Use When | -|---------|----------| -| `async/await` | Sequential async operations | -| `Promise.all` | Parallel independent operations | -| `Promise.allSettled` | Parallel where some can fail | -| `Promise.race` | Timeout or first response wins | - -### Event Loop Awareness - -``` -I/O-bound (async helps): -├── Database queries -├── HTTP requests -├── File system -└── Network operations - -CPU-bound (async doesn't help): -├── Crypto operations -├── Image processing -├── Complex calculations -└── → Use worker threads or offload -``` - -### Avoiding Event Loop Blocking - -- Never use sync methods in production (fs.readFileSync, etc.) -- Offload CPU-intensive work -- Use streaming for large data - ---- - -## 6. Validation Principles - -### Validate at Boundaries - -``` -Where to validate: -├── API entry point (request body/params) -├── Before database operations -├── External data (API responses, file uploads) -└── Environment variables (startup) -``` - -### Validation Library Selection - -| Library | Best For | -|---------|----------| -| **Zod** | TypeScript first, inference | -| **Valibot** | Smaller bundle (tree-shakeable) | -| **ArkType** | Performance critical | -| **Yup** | Existing React Form usage | - -### Validation Philosophy - -- Fail fast: Validate early -- Be specific: Clear error messages -- Don't trust: Even "internal" data - ---- - -## 7. Security Principles - -### Security Checklist (Not Code) - -- [ ] **Input validation**: All inputs validated -- [ ] **Parameterized queries**: No string concatenation for SQL -- [ ] **Password hashing**: bcrypt or argon2 -- [ ] **JWT verification**: Always verify signature and expiry -- [ ] **Rate limiting**: Protect from abuse -- [ ] **Security headers**: Helmet.js or equivalent -- [ ] **HTTPS**: Everywhere in production -- [ ] **CORS**: Properly configured -- [ ] **Secrets**: Environment variables only -- [ ] **Dependencies**: Regularly audited - -### Security Mindset - -``` -Trust nothing: -├── Query params → validate -├── Request body → validate -├── Headers → verify -├── Cookies → validate -├── File uploads → scan -└── External APIs → validate response -``` - ---- - -## 8. Testing Principles - -### Test Strategy Selection - -| Type | Purpose | Tools | -|------|---------|-------| -| **Unit** | Business logic | node:test, Vitest | -| **Integration** | API endpoints | Supertest | -| **E2E** | Full flows | Playwright | - -### What to Test (Priorities) - -1. **Critical paths**: Auth, payments, core business -2. **Edge cases**: Empty inputs, boundaries -3. **Error handling**: What happens when things fail? -4. **Not worth testing**: Framework code, trivial getters - -### Built-in Test Runner (Node.js 22+) - -``` -node --test src/**/*.test.ts -├── No external dependency -├── Good coverage reporting -└── Watch mode available -``` - ---- - -## 10. Anti-Patterns to Avoid - -### ❌ DON'T: -- Use Express for new edge projects (use Hono) -- Use sync methods in production code -- Put business logic in controllers -- Skip input validation -- Hardcode secrets -- Trust external data without validation -- Block event loop with CPU work - -### ✅ DO: -- Choose framework based on context -- Ask user for preferences when unclear -- Use layered architecture for growing projects -- Validate all inputs -- Use environment variables for secrets -- Profile before optimizing - ---- - -## 11. Decision Checklist - -Before implementing: - -- [ ] **Asked user about stack preference?** -- [ ] **Chosen framework for THIS context?** (not just default) -- [ ] **Considered deployment target?** -- [ ] **Planned error handling strategy?** -- [ ] **Identified validation points?** -- [ ] **Considered security requirements?** - ---- - -> **Remember**: Node.js best practices are about decision-making, not memorizing patterns. Every project deserves fresh consideration based on its requirements. diff --git a/nuxt-better-auth/skill.md b/nuxt-better-auth/skill.md deleted file mode 100644 index 77f6ed8..0000000 --- a/nuxt-better-auth/skill.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -name: nuxt-better-auth -description: Use when implementing auth in Nuxt apps with @onmax/nuxt-better-auth - provides useUserSession composable, server auth helpers, route protection, and Better Auth plugins integration. -license: MIT ---- - -# Nuxt Better Auth - -Authentication module for Nuxt 4+ built on [Better Auth](https://www.better-auth.com/). Provides composables, server utilities, and route protection. - -> **Alpha Status**: This module is currently in alpha (v0.0.2-alpha.14) and not recommended for production use. APIs may change. - -## When to Use - -- Installing/configuring `@onmax/nuxt-better-auth` -- Implementing login/signup/signout flows -- Protecting routes (client and server) -- Accessing user session in API routes -- Integrating Better Auth plugins (admin, passkey, 2FA) -- Setting up database with NuxtHub -- Using clientOnly mode for external auth backends - -**For Nuxt patterns:** use `nuxt` skill -**For NuxtHub database:** use `nuxthub` skill - -## Available Guidance - -| File | Topics | -| -------------------------------------------------------------------- | ---------------------------------------------------------------------- | -| **[references/installation.md](references/installation.md)** | Module setup, env vars, config files | -| **[references/client-auth.md](references/client-auth.md)** | useUserSession, signIn/signUp/signOut, BetterAuthState, safe redirects | -| **[references/server-auth.md](references/server-auth.md)** | serverAuth, getUserSession, requireUserSession | -| **[references/route-protection.md](references/route-protection.md)** | routeRules, definePageMeta, middleware | -| **[references/plugins.md](references/plugins.md)** | Better Auth plugins (admin, passkey, 2FA) | -| **[references/database.md](references/database.md)** | NuxtHub integration, Drizzle schema, custom tables with FKs | -| **[references/client-only.md](references/client-only.md)** | External auth backend, clientOnly mode, CORS | -| **[references/types.md](references/types.md)** | AuthUser, AuthSession, type augmentation | - -## Usage Pattern - -**Load based on context:** - -- Installing module? → [references/installation.md](references/installation.md) -- Login/signup forms? → [references/client-auth.md](references/client-auth.md) -- API route protection? → [references/server-auth.md](references/server-auth.md) -- Route rules/page meta? → [references/route-protection.md](references/route-protection.md) -- Using plugins? → [references/plugins.md](references/plugins.md) -- Database setup? → [references/database.md](references/database.md) -- External auth backend? → [references/client-only.md](references/client-only.md) -- TypeScript types? → [references/types.md](references/types.md) - -**DO NOT read all files at once.** Load based on context. - -## Key Concepts - -| Concept | Description | -| ---------------------- | --------------------------------------------------------------- | -| `useUserSession()` | Client composable - user, session, loggedIn, signIn/Out methods | -| `requireUserSession()` | Server helper - throws 401/403 if not authenticated | -| `auth` route mode | `'user'`, `'guest'`, `{ user: {...} }`, or `false` | -| `serverAuth()` | Get Better Auth instance in server routes | - -## Quick Reference - -```ts -// Client: useUserSession() -const { user, loggedIn, signIn, signOut } = useUserSession() -await signIn.email({ email, password }, { onSuccess: () => navigateTo('/') }) -``` - -```ts -// Server: requireUserSession() -const { user } = await requireUserSession(event, { user: { role: 'admin' } }) -``` - -```ts -// nuxt.config.ts: Route protection -routeRules: { - '/admin/**': { auth: { user: { role: 'admin' } } }, - '/login': { auth: 'guest' }, - '/app/**': { auth: 'user' } -} -``` - -## Resources - -- [Module Docs](https://github.com/onmax/nuxt-better-auth) -- [Better Auth Docs](https://www.better-auth.com/) - ---- - -_Token efficiency: Main skill ~300 tokens, each sub-file ~800-1200 tokens_ diff --git a/nuxt-content/skill.md b/nuxt-content/skill.md deleted file mode 100644 index bf68e82..0000000 --- a/nuxt-content/skill.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -name: nuxt-content -description: Use when working with Nuxt Content v3 - provides collections (local/remote/API sources), queryCollection API, MDC rendering, database configuration, NuxtStudio integration, hooks, i18n patterns, and LLMs integration -license: MIT ---- - -# Nuxt Content v3 - -Progressive guidance for content-driven Nuxt apps with typed collections and SQL-backed queries. - -## When to Use - -Working with: - -- Content collections (`content.config.ts`, `defineCollection`) -- Remote sources (GitHub repos, external APIs via `defineCollectionSource`) -- Content queries (`queryCollection`, navigation, search) -- MDC rendering (``, prose components) -- Database configuration (SQLite, PostgreSQL, D1, LibSQL) -- Content hooks (`content:file:beforeParse`, `content:file:afterParse`) -- i18n multi-language content -- NuxtStudio or preview mode -- LLMs integration (`nuxt-llms`) - -**For writing documentation:** use `document-writer` skill -**For Nuxt basics:** use `nuxt` skill -**For NuxtHub deployment:** use `nuxthub` skill (NuxtHub v1 compatible) - -## Available Guidance - -Read specific files based on current work: - -- **[references/collections.md](references/collections.md)** - defineCollection, schemas, sources, content.config.ts -- **[references/querying.md](references/querying.md)** - queryCollection, navigation, search, surroundings -- **[references/rendering.md](references/rendering.md)** - ContentRenderer, MDC syntax, prose components, Shiki -- **[references/config.md](references/config.md)** - Database setup, markdown plugins, renderer options -- **[references/studio.md](references/studio.md)** - NuxtStudio integration, preview mode, live editing - -## Usage Pattern - -**Progressive loading - only read what you need:** - -- Setting up collections? → [references/collections.md](references/collections.md) -- Querying content? → [references/querying.md](references/querying.md) -- Rendering markdown/MDC? → [references/rendering.md](references/rendering.md) -- Configuring database/markdown? → [references/config.md](references/config.md) -- Using NuxtStudio? → [references/studio.md](references/studio.md) - -**DO NOT read all files at once.** Load based on context: - -- Editing `content.config.ts` → read collections.md -- Using `queryCollection()` → read querying.md -- Working with `` or MDC → read rendering.md -- Configuring database or markdown → read config.md -- Setting up preview/studio → read studio.md - -## Key Concepts - -| Concept | Purpose | -| --------------- | ----------------------------------------------------------------- | -| Collections | Typed content groups with schemas | -| Page vs Data | `page` = routes + body, `data` = structured data only | -| Remote sources | `source.repository` for GitHub, `defineCollectionSource` for APIs | -| queryCollection | SQL-like fluent API for content | -| MDC | Vue components inside markdown | -| ContentRenderer | Renders parsed markdown body | - -## Directory Structure - -``` -project/ -├── content/ # Content files -│ ├── blog/ # Maps to 'blog' collection -│ └── .navigation.yml # Navigation metadata -├── components/content/ # MDC components -└── content.config.ts # Collection definitions -``` - -## Official Documentation - -- Nuxt Content: https://content.nuxt.com -- MDC syntax: https://content.nuxt.com/docs/files/markdown#mdc-syntax -- Collections: https://content.nuxt.com/docs/collections/collections - -## Token Efficiency - -Main skill: ~300 tokens. Each sub-file: ~800-1200 tokens. Only load files relevant to current task. diff --git a/nuxt-modules/skill.md b/nuxt-modules/skill.md deleted file mode 100644 index 5ad6fe7..0000000 --- a/nuxt-modules/skill.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -name: nuxt-modules -description: "Use when creating Nuxt modules: (1) Published npm modules (@nuxtjs/, nuxt-), (2) Local project modules (modules/ directory), (3) Runtime extensions (components, composables, plugins), (4) Server extensions (API routes, middleware), (5) Releasing/publishing modules to npm, (6) Setting up CI/CD workflows for modules. Provides defineNuxtModule patterns, Kit utilities, hooks, E2E testing, and release automation." -license: MIT ---- - -# Nuxt Module Development - -Guide for creating Nuxt modules that extend framework functionality. - -**Related skills:** `nuxt` (basics), `vue` (runtime patterns) - -## Quick Start - -```bash -npx nuxi init -t module my-module -cd my-module && npm install -npm run dev # Start playground -npm run dev:build # Build in watch mode -npm run test # Run tests -``` - -## Available Guidance - -- **[references/development.md](references/development.md)** - Module anatomy, defineNuxtModule, Kit utilities, hooks -- **[references/testing-and-publishing.md](references/testing-and-publishing.md)** - E2E testing, best practices, releasing, publishing -- **[references/ci-workflows.md](references/ci-workflows.md)** - Copy-paste CI/CD workflow templates - -**Load based on context:** - -- Building module features? → [references/development.md](references/development.md) -- Testing or publishing? → [references/testing-and-publishing.md](references/testing-and-publishing.md) -- CI workflow templates? → [references/ci-workflows.md](references/ci-workflows.md) - -## Module Types - -| Type | Location | Use Case | -| --------- | ---------------- | -------------------------------- | -| Published | npm package | `@nuxtjs/`, `nuxt-` distribution | -| Local | `modules/` dir | Project-specific extensions | -| Inline | `nuxt.config.ts` | Simple one-off hooks | - -## Project Structure - -``` -my-module/ -├── src/ -│ ├── module.ts # Entry point -│ └── runtime/ # Injected into user's app -│ ├── components/ -│ ├── composables/ -│ ├── plugins/ -│ └── server/ -├── playground/ # Dev testing -└── test/fixtures/ # E2E tests -``` - -## Resources - -- [Module Guide](https://nuxt.com/docs/guide/going-further/modules) -- [Nuxt Kit](https://nuxt.com/docs/api/kit) -- [Module Starter](https://github.com/nuxt/starter/tree/module) diff --git a/nuxt-ui/skill.md b/nuxt-ui/skill.md deleted file mode 100644 index bb8f5e7..0000000 --- a/nuxt-ui/skill.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: nuxt-ui -description: Use when building styled UI with @nuxt/ui v4 components (Button, Modal, Form, Table, etc.) - provides ready-to-use components with Tailwind Variants theming. Use vue skill for raw component patterns, reka-ui for headless primitives. -license: MIT ---- - -# Nuxt UI v4 - -Component library for Vue 3 and Nuxt 4+ built on Reka UI (headless) + Tailwind CSS v4 + Tailwind Variants. - -**Current stable version:** v4.3.0 (December 2025) - -## When to Use - -- Installing/configuring @nuxt/ui -- Using UI components (Button, Card, Table, Form, etc.) -- Customizing theme (colors, variants, CSS variables) -- Building forms with validation -- Using overlays (Modal, Toast, CommandPalette) -- Working with composables (useToast, useOverlay) - -**For Vue component patterns:** use `vue` skill -**For Nuxt routing/server:** use `nuxt` skill - -## Available Guidance - -| File | Topics | -| ------------------------------------------------------------ | -------------------------------------------------------------------------------- | -| **[references/installation.md](references/installation.md)** | Nuxt/Vue setup, pnpm gotchas, UApp wrapper, module options, prefix, tree-shaking | -| **[references/theming.md](references/theming.md)** | Semantic colors, CSS variables, app.config.ts, Tailwind Variants | -| **[references/components.md](references/components.md)** | Component index by category (125+ components) | -| **components/\*.md** | Per-component details (button.md, modal.md, etc.) | -| **[references/forms.md](references/forms.md)** | Form components, validation (Zod/Valibot), useFormField | -| **[references/overlays.md](references/overlays.md)** | Toast, Modal, Slideover, Drawer, CommandPalette | -| **[references/composables.md](references/composables.md)** | useToast, useOverlay, defineShortcuts, useScrollspy | - -## Usage Pattern - -**Load based on context:** - -- Installing Nuxt UI? → [references/installation.md](references/installation.md) -- Customizing theme? → [references/theming.md](references/theming.md) -- Component index → [references/components.md](references/components.md) -- Specific component → [components/button.md](components/button.md), [components/modal.md](components/modal.md), etc. -- Building forms? → [references/forms.md](references/forms.md) -- Using overlays? → [references/overlays.md](references/overlays.md) -- Using composables? → [references/composables.md](references/composables.md) - -**DO NOT read all files at once.** Load based on context. - -## Key Concepts - -| Concept | Description | -| ----------------- | ---------------------------------------------------------- | -| UApp | Required wrapper component for Toast, Tooltip, overlays | -| Tailwind Variants | Type-safe styling with slots, variants, compoundVariants | -| Semantic Colors | primary, secondary, success, error, warning, info, neutral | -| Reka UI | Headless component primitives (accessibility built-in) | - -> For headless component primitives (API details, accessibility patterns, asChild): read the **reka-ui** skill - -## Quick Reference - -```ts -// nuxt.config.ts -export default defineNuxtConfig({ - modules: ['@nuxt/ui'], - css: ['~/assets/css/main.css'] -}) -``` - -```css -/* assets/css/main.css */ -@import 'tailwindcss'; -@import '@nuxt/ui'; -``` - -```vue - - -``` - -## Resources - -- [Nuxt UI Docs](https://ui.nuxt.com) -- [Component Reference](https://ui.nuxt.com/components) -- [Theme Customization](https://ui.nuxt.com/getting-started/theme) - ---- - -_Token efficiency: Main skill ~300 tokens, each sub-file ~800-1200 tokens_ diff --git a/nuxt/skill.md b/nuxt/skill.md deleted file mode 100644 index 33f86d2..0000000 --- a/nuxt/skill.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -name: nuxt -description: Use when working on Nuxt 4+ projects - provides server routes, file-based routing, middleware patterns, Nuxt-specific composables, and configuration with latest docs. Covers h3 v1 helpers (validation, WebSocket, SSE) and nitropack v2 patterns. -license: MIT ---- - -# Nuxt 4+ Development - -Progressive guidance for Nuxt 4+ projects with latest patterns and conventions. - -## When to Use - -Working with: - -- Server routes (API endpoints, server middleware, server utils) -- File-based routing (pages, layouts, route groups) -- Nuxt middleware (route guards, navigation) -- Nuxt plugins (app extensions) -- Nuxt-specific features (auto-imports, layers, modules) - -## Available Guidance - -Read specific files based on current work: - -- **[references/server.md](references/server.md)** - API routes, server middleware, validation (Zod), WebSocket, SSE -- **[references/routing.md](references/routing.md)** - File-based routing, route groups, typed router, definePage -- **[references/middleware-plugins.md](references/middleware-plugins.md)** - Route middleware, plugins, app lifecycle -- **[references/nuxt-composables.md](references/nuxt-composables.md)** - Nuxt composables (useRequestURL, useFetch, navigation) -- **[references/nuxt-components.md](references/nuxt-components.md)** - NuxtLink, NuxtImg, NuxtTime (prefer over HTML elements) -- **[references/nuxt-config.md](references/nuxt-config.md)** - Configuration, modules, auto-imports, layers - -**For Vue composables:** See `vue` skill composables.md (VueUse, Composition API patterns) -**For UI components:** use `nuxt-ui` skill -**For database/storage:** use `nuxthub` skill -**For content-driven sites:** use `nuxt-content` skill -**For creating modules:** use `nuxt-modules` skill -**For project scaffolding/CI:** use `personal-ts-setup` skill - -## Usage Pattern - -**Progressive loading - only read what you need:** - -- Creating API endpoint? → [references/server.md](references/server.md) -- Setting up pages/routing? → [references/routing.md](references/routing.md) -- Using composables/data fetching? → [references/nuxt-composables.md](references/nuxt-composables.md) -- Adding middleware/plugins? → [references/middleware-plugins.md](references/middleware-plugins.md) -- Configuring Nuxt? → [references/nuxt-config.md](references/nuxt-config.md) -- Setting up CI/ESLint? → [references/project-setup.md](references/project-setup.md) - -**DO NOT read all files at once.** Load based on context: - -- Working in `server/` → read server.md -- Working in `pages/` or `layouts/` → read routing.md -- Using `useFetch`, `useRequestURL`, navigation → read nuxt-composables.md -- Using ``, ``, `