Add Claude commands, remote-exec script, and skills

- commands/remote.md for remote execution
- remote-exec.sh script
- skills: claudeception, kubernetes-latest-tag-image-pull, react-hooks-order-early-return
This commit is contained in:
Viktor Barzin 2026-02-03 19:17:05 +00:00
parent 09631b3530
commit fde360dbdc
44 changed files with 3053 additions and 0 deletions

View file

@ -0,0 +1,118 @@
---
name: nextjs-server-side-error-debugging
description: |
Debug getServerSideProps and getStaticProps errors in Next.js. Use when:
(1) Page shows generic error but browser console is empty, (2) API routes
return 500 with no details, (3) Server-side code fails silently, (4) Error
only occurs on refresh not client navigation. Check terminal/server logs
instead of browser for actual error messages.
author: Claude Code
version: 1.0.0
date: 2024-01-15
---
# Next.js Server-Side Error Debugging
## Problem
Server-side errors in Next.js don't appear in the browser console, making debugging
frustrating when you're looking in the wrong place. The browser shows a generic error
page or 500 status, but no stack trace or useful error information appears in DevTools.
## Context / Trigger Conditions
This skill applies when:
- Page displays "Internal Server Error" or custom error page
- Browser console shows no errors, or only a generic fetch failure
- You're using `getServerSideProps`, `getStaticProps`, or API routes
- Error only occurs on page refresh or direct navigation (not client-side transitions)
- The error is intermittent and hard to reproduce in the browser
Common misleading symptoms:
- "Unhandled Runtime Error" modal that doesn't show the real cause
- Network tab shows 500 but response body is empty or generic
- Error disappears when you add console.log (timing issue)
## Solution
### Step 1: Check the Terminal
The actual error with full stack trace appears in the terminal where `npm run dev`
or `next dev` is running. This is the **first place to look**.
```bash
# If you don't see the terminal, find the process
ps aux | grep next
# Or restart with visible output
npm run dev
```
### Step 2: Add Explicit Error Handling
For persistent debugging, wrap server-side code with try-catch:
```typescript
export async function getServerSideProps(context) {
try {
const data = await fetchSomething();
return { props: { data } };
} catch (error) {
console.error('getServerSideProps error:', error);
// Return error state instead of throwing
return { props: { error: error.message } };
}
}
```
### Step 3: For Production Errors
Check your hosting provider's logs:
- **Vercel**: Dashboard → Project → Logs (Functions tab)
- **AWS**: CloudWatch Logs
- **Netlify**: Functions tab in dashboard
- **Self-hosted**: Check your Node.js process logs
### Step 4: Common Causes
1. **Environment variables**: Missing in production but present locally
2. **Database connections**: Connection string issues, cold starts
3. **Import errors**: Server-only code accidentally imported on client
4. **Async/await**: Missing await on async operations
5. **JSON serialization**: Objects that can't be serialized (dates, functions)
## Verification
After checking the terminal, you should see:
- Full stack trace with file name and line number
- The actual error message (not generic 500)
- Variable values if you added console.log statements
## Example
**Symptom**: User reports page shows "Internal Server Error" after clicking a link.
**Investigation**:
1. Open browser DevTools → Console: Empty
2. Network tab shows: `GET /dashboard → 500`
3. Check terminal running `npm run dev`:
```
Error: Cannot read property 'id' of undefined
at getServerSideProps (/app/pages/dashboard.tsx:15:25)
at renderToHTML (/app/node_modules/next/dist/server/render.js:428:22)
```
**Cause found**: Database query returned `null` instead of user object.
## Notes
- In development, Next.js sometimes shows an error overlay, but it often has less
detail than the terminal output
- `reactStrictMode: true` in `next.config.js` causes double-execution of server
functions in development, which can make debugging confusing
- For API routes, the error appears in the same terminal as page errors
- Client-side errors (in useEffect, event handlers) DO appear in browser console—
this skill only applies to server-side code
- If using `next start` (production mode locally), errors may be less verbose;
check `NODE_ENV` and consider adding custom error logging

View file

@ -0,0 +1,161 @@
---
name: prisma-connection-pool-exhaustion
description: |
Fix Prisma "Too many connections" and connection pool exhaustion errors in
serverless environments (Vercel, AWS Lambda, Netlify). Use when: (1) Error
"P2024: Timed out fetching a new connection from the pool", (2) PostgreSQL
"too many connections for role", (3) Database works locally but fails in
production serverless, (4) Intermittent database timeouts under load.
author: Claude Code
version: 1.0.0
date: 2024-02-20
---
# Prisma Connection Pool Exhaustion in Serverless
## Problem
Serverless functions create a new Prisma client instance on each cold start. Each
instance opens multiple database connections (default: 5 per instance). With many
concurrent requests, this quickly exhausts the database's connection limit (often
20-100 for managed databases).
## Context / Trigger Conditions
This skill applies when you see:
- `P2024: Timed out fetching a new connection from the connection pool`
- PostgreSQL: `FATAL: too many connections for role "username"`
- MySQL: `Too many connections`
- Works fine locally with `npm run dev` but fails in production
- Errors appear during traffic spikes, then resolve
- Database dashboard shows connections at or near limit
Environment indicators:
- Deploying to Vercel, AWS Lambda, Netlify Functions, or similar
- Using Prisma with PostgreSQL, MySQL, or another connection-based database
- Database is managed (PlanetScale, Supabase, Neon, RDS, etc.)
## Solution
### Step 1: Use Connection Pooling Service
The recommended solution is to use a connection pooler like PgBouncer or Prisma
Accelerate, which sits between your serverless functions and the database.
**For Supabase:**
```
# .env
# Use the pooled connection string (port 6543, not 5432)
DATABASE_URL="postgresql://user:pass@db.xxx.supabase.co:6543/postgres?pgbouncer=true"
```
**For Neon:**
```
# .env
DATABASE_URL="postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/dbname?sslmode=require"
# Neon has built-in pooling
```
**For Prisma Accelerate:**
```bash
npx prisma generate --accelerate
```
### Step 2: Configure Prisma Connection Limits
In your `schema.prisma`:
```prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
// Limit connections per Prisma instance
relationMode = "prisma"
}
```
In your connection URL or Prisma client:
```typescript
// lib/prisma.ts
import { PrismaClient } from '@prisma/client'
const globalForPrisma = global as unknown as { prisma: PrismaClient }
export const prisma = globalForPrisma.prisma || new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL + '?connection_limit=1'
}
}
})
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
```
### Step 3: Singleton Pattern (Development)
Prevent hot-reload from creating new clients:
```typescript
// lib/prisma.ts
import { PrismaClient } from '@prisma/client'
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
```
### Step 4: URL Parameters
Add these to your connection string:
```
?connection_limit=1&pool_timeout=20&connect_timeout=10
```
- `connection_limit=1`: One connection per serverless instance
- `pool_timeout=20`: Wait up to 20s for available connection
- `connect_timeout=10`: Fail fast if can't connect in 10s
## Verification
After applying fixes:
1. Deploy to production
2. Run a load test: `npx autocannon -c 100 -d 30 https://your-app.com/api/test`
3. Check database dashboard—connections should stay within limits
4. No more P2024 errors in logs
## Example
**Before** (error under load):
```
[ERROR] PrismaClientKnownRequestError:
Invalid `prisma.user.findMany()` invocation:
Timed out fetching a new connection from the connection pool.
```
**After** (with connection pooling):
```
# Using Supabase pooler URL
DATABASE_URL="postgresql://...@db.xxx.supabase.co:6543/postgres?pgbouncer=true&connection_limit=1"
```
Database connections stable at 10-15 even under heavy load.
## Notes
- Different managed databases have different pooling solutions—check your provider's docs
- PlanetScale (MySQL) uses a different architecture and doesn't have this issue
- `connection_limit=1` is aggressive; start there and increase if you see latency
- The singleton pattern only helps in development; in production serverless, each
instance is isolated
- If using Prisma with Next.js API routes, each route invocation may be a separate
serverless function
- Consider Prisma Accelerate for built-in caching + pooling: https://www.prisma.io/accelerate

View file

@ -0,0 +1,237 @@
---
name: typescript-circular-dependency
description: |
Detect and resolve TypeScript/JavaScript circular import dependencies. Use when:
(1) "Cannot access 'X' before initialization" at runtime, (2) Import returns
undefined unexpectedly, (3) "ReferenceError: Cannot access X before initialization",
(4) Type errors that disappear when you change import order, (5) Jest/Vitest tests
fail with undefined imports that work in browser.
author: Claude Code
version: 1.0.0
date: 2024-03-10
---
# TypeScript Circular Dependency Detection and Resolution
## Problem
Circular dependencies occur when module A imports from module B, which imports
(directly or indirectly) from module A. TypeScript compiles successfully, but at
runtime, one of the imports evaluates to `undefined` because the module hasn't
finished initializing yet.
## Context / Trigger Conditions
Common error messages:
```
ReferenceError: Cannot access 'UserService' before initialization
```
```
TypeError: Cannot read properties of undefined (reading 'create')
```
```
TypeError: (0 , _service.doSomething) is not a function
```
Symptoms that suggest circular imports:
- Import is `undefined` even though the export exists
- Error only appears at runtime, not during TypeScript compilation
- Moving an import statement changes which import is undefined
- Tests fail but the app works (or vice versa)
- Adding `console.log` at the top of a file changes behavior
## Solution
### Step 1: Detect the Cycle
Use a tool to visualize dependencies:
```bash
# Install madge
npm install -g madge
# Find circular dependencies
madge --circular --extensions ts,tsx src/
# Generate visual graph
madge --circular --image graph.svg src/
```
Or use the TypeScript compiler:
```bash
# Check for cycles (requires tsconfig setting)
npx tsc --listFiles | head -50
```
### Step 2: Identify the Pattern
Common circular dependency patterns:
**Pattern A: Service-to-Service**
```
services/userService.ts → services/orderService.ts → services/userService.ts
```
**Pattern B: Type imports**
```
types/user.ts → types/order.ts → types/user.ts
```
**Pattern C: Index barrel files**
```
components/index.ts → components/Button.tsx → components/index.ts
```
### Step 3: Resolution Strategies
**Strategy 1: Extract Shared Dependencies**
Before:
```typescript
// userService.ts
import { OrderService } from './orderService';
export class UserService { ... }
// orderService.ts
import { UserService } from './userService';
export class OrderService { ... }
```
After:
```typescript
// types/interfaces.ts (new file - no imports from services)
export interface IUserService { ... }
export interface IOrderService { ... }
// userService.ts
import { IOrderService } from '../types/interfaces';
export class UserService implements IUserService { ... }
```
**Strategy 2: Dependency Injection**
```typescript
// orderService.ts
export class OrderService {
constructor(private userService: IUserService) {}
// Instead of importing UserService directly
}
// main.ts
const userService = new UserService();
const orderService = new OrderService(userService);
```
**Strategy 3: Dynamic Imports**
```typescript
// Only import when needed, not at module level
async function processOrder() {
const { UserService } = await import('./userService');
// ...
}
```
**Strategy 4: Use Type-Only Imports**
If you only need types (not values), use type-only imports:
```typescript
// This doesn't create a runtime dependency
import type { User } from './userService';
```
**Strategy 5: Restructure Barrel Files**
Before (problematic):
```typescript
// components/index.ts
export * from './Button';
export * from './Modal'; // Modal imports Button from './index'
```
After:
```typescript
// components/Modal.tsx
import { Button } from './Button'; // Direct import, not from index
```
### Step 4: Prevent Future Cycles
Add to your CI/build process:
```json
// package.json
{
"scripts": {
"check:circular": "madge --circular --extensions ts,tsx src/"
}
}
```
Or configure ESLint:
```javascript
// .eslintrc.js
module.exports = {
plugins: ['import'],
rules: {
'import/no-cycle': ['error', { maxDepth: 10 }]
}
}
```
## Verification
1. Run `madge --circular src/` - should report no cycles
2. Run your test suite - previously undefined imports should work
3. Delete `node_modules` and reinstall - app should still work
4. Build for production - no runtime errors
## Example
**Problem**: `OrderService` is undefined when imported in `UserService`
**Detection**:
```bash
$ madge --circular src/
Circular dependencies found!
src/services/userService.ts → src/services/orderService.ts → src/services/userService.ts
```
**Fix**: Extract shared interface
```typescript
// NEW: src/types/services.ts
export interface IOrderService {
createOrder(userId: string): Promise<Order>;
}
// MODIFIED: src/services/userService.ts
import type { IOrderService } from '../types/services';
export class UserService {
constructor(private orderService: IOrderService) {}
}
// MODIFIED: src/services/orderService.ts
// No longer imports UserService
export class OrderService implements IOrderService {
async createOrder(userId: string): Promise<Order> { ... }
}
```
## Notes
- TypeScript `import type` is your friend—it's erased at runtime and can't cause cycles
- Barrel files (`index.ts`) are a common source of accidental cycles
- The order of exports in a file can matter when there's a cycle
- Jest/Vitest may handle module resolution differently than your bundler
- Some bundlers (Webpack, Vite) have better cycle handling than others
- `require()` can sometimes mask circular dependency issues that `import` exposes