Claude Code Plugins

Community-maintained marketplace

Feedback

>

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name anti-patterns
description Gentle reminder skill for common mistakes to avoid. Non-blocking suggestions. AUTO-ACTIVATE when user mentions (FR/EN): - erreur, error, bug, problème, problem - anti-pattern, mauvaise pratique, bad practice, avoid, éviter - pourquoi erreur, why error, comment éviter, how to avoid - any, undefined, null, timezone, siteId manquant This skill shows as a GENTLE reminder after code edits (non-blocking).

Anti-Patterns - Don't Do This

Purpose: Gentle reminders of common mistakes Source: DONT_DO.md (397 lines) Enforcement: Suggest only (non-blocking)


🚫 TypeScript

// ❌ any types
const data: any = response

// βœ… Explicit types
const data: User = response

// ❌ Non-null assertion without check
const user = getUser()!

// βœ… Proper check
const user = getUser();
if (!user) throw new Error('User not found');

🚫 React

// ❌ useState for server data
const [users, setUsers] = useState([])

// βœ… React Query
const { data: users } = useQuery({ queryKey: ['users'], ... })

// ❌ useEffect without dependencies
useEffect(() => doSomething(prop))  // Missing []

// βœ… With dependencies
useEffect(() => doSomething(prop), [prop])

// ❌ Inline objects in props (causes re-renders)
<Component style={{ margin: 10 }} />

// βœ… Memoized or extracted
const style = useMemo(() => ({ margin: 10 }), []);
<Component style={style} />

🚫 Database (Prisma)

// ❌ N+1 Queries
const users = await prisma.user.findMany()
for (const user of users) {
  const posts = await prisma.post.findMany({ where: { userId: user.id } })
}

// βœ… Use include
const users = await prisma.user.findMany({
  include: { posts: true }
});

// ❌ Queries without pagination
const allUsers = await prisma.user.findMany()  // Can return millions

// βœ… Always paginate
const users = await prisma.user.findMany({
  take: 50,
  skip: page * 50
});

🚫 API Design

// ❌ No validation
export async function POST(request: NextRequest) {
  const data = await request.json();  // No validation!
  return NextResponse.json(await createPlanning(data));
}

// βœ… Zod validation
const schema = z.object({ name: z.string().min(1) });
export async function POST(request: NextRequest) {
  const body = await request.json();
  const validation = schema.safeParse(body);

  if (!validation.success) {
    return NextResponse.json(
      { error: 'Validation failed', details: validation.error },
      { status: 400 }
    );
  }

  return NextResponse.json(await createPlanning(validation.data));
}

// ❌ Unhandled errors
export async function GET() {
  const data = await service.getData();  // Can throw
  return NextResponse.json(data);
}

// βœ… Try-catch
export async function GET() {
  try {
    const data = await service.getData();
    return NextResponse.json(data);
  } catch (error) {
    console.error('Error:', error);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

🚫 Dates & Timezone

// ❌ Send yyyy-MM-dd without timezone
const payload = {
  startDate: format(date, 'yyyy-MM-dd'),  // "2025-10-28"
  // Parsed as midnight UTC β†’ timezone bug!
};

// βœ… Always send ISO with explicit timezone
const payload = {
  startDate: startOfDay(date).toISOString(),  // 2025-10-27T23:00:00.000Z
  endDate: endOfDay(date).toISOString()
};

🚫 Critical Fields Missing

// ❌ Forget siteId when creating assignments
const assignment = await prisma.assignment.create({
  data: {
    date: request.date,
    userId: request.userId,
    operatingRoomId: request.operatingRoomId,
    // ❌ siteId missing β†’ null in DB!
  }
});

// βœ… Always include siteId
const assignment = await prisma.assignment.create({
  data: {
    date: request.date,
    userId: request.userId,
    operatingRoomId: request.operatingRoomId,
    siteId: request.siteId,  // βœ… Essential for filtering/deletion
  }
});

Impact: 55% of assignments had siteId: null, making bulk delete impossible.


🚫 UX & Accessibility

// ❌ Insufficient contrast (gray on gray)
<div className="bg-gray-50 p-3">
  <Switch />  {/* OFF state invisible on light gray background */}
</div>

// βœ… Sufficient contrast with border or white bg
<div className="bg-white border-2 border-gray-200 hover:border-blue-300 p-4 rounded-lg">
  <Label htmlFor="active" className="text-sm font-medium cursor-pointer">Active</Label>
  <Switch id="active" />
</div>

// ❌ Touch zones too small (<44px - not WCAG AAA)
<button className="p-1 text-xs">Action</button>

// βœ… Minimum 44x44px
<button className="min-h-[44px] min-w-[44px] p-3">Action</button>

// ❌ Labels not connected (accessibility broken)
<Label>Active</Label>
<Switch />

// βœ… Connected for screen readers
<Label htmlFor="active">Active</Label>
<Switch id="active" />

🚫 Authentication

// ❌ Read token from document.cookie (HttpOnly cookies inaccessible)
function getAuthToken() {
  const cookies = document.cookie.split(';');
  const token = cookies.find(c => c.includes('token='));  // Doesn't work if HttpOnly!
  return token;
}

// βœ… Use auth context
const { getAuthHeaders } = useAuth();
const headers = {
  'Content-Type': 'application/json',
  ...getAuthHeaders()  // Includes Authorization: Bearer <token>
};

// ❌ Forget credentials: 'include' in fetch
fetch('/api/endpoint', { method: 'POST' });  // Cookies not sent!

// βœ… Always include credentials for authenticated requests
fetch('/api/endpoint', {
  method: 'POST',
  credentials: 'include',
  headers: getAuthHeaders()
});

🎯 ABSOLUTE RULES

  1. ❌ NEVER: any types in TypeScript
  2. ❌ NEVER: console.log in production
  3. ❌ NEVER: Queries without pagination
  4. ❌ NEVER: Components >200 lines
  5. ❌ NEVER: Business logic in UI
  6. ❌ NEVER: Tests without cleanup
  7. ❌ NEVER: Import full libraries (use tree shaking)
  8. ❌ NEVER: APIs without Zod validation
  9. ❌ NEVER: useEffect without dependencies
  10. ❌ NEVER: Missing braces (syntax errors)
  11. ❌ NEVER: Gray on gray (contrast <3:1 WCAG)
  12. ❌ NEVER: Buttons/Switch <44px (WCAG AAA)

Source: DONT_DO.md Maintained by: Mathildanesth Team Last Update: 27 October 2025