Communitygithub.com

Conventions de Codage & Bonnes Pratiques

Conventions de codage de base applicables à tous les projets. Utilisez ce skill pour la lisibilité, la qualité et la révision du code, et les skills plus spécialisés pour les frameworks spécifiques.

Qu'est-ce que Conventions de Codage & Bonnes Pratiques ?

Ce skill établit les standards fondamentaux de codage et les bonnes pratiques à respecter dans l'ensemble des projets. Il sert de socle commun et est activé lors du démarrage d'un nouveau projet, de la révision de code, du refactoring, ou de la mise en place d'outils de linting et de formatage. Il couvre les principes de qualité essentiels (KISS, DRY, YAGNI, lisibilité), les conventions de nommage, l'immutabilité, la gestion des erreurs et l'organisation des fichiers. Le skill propose des exemples concrets en TypeScript/JavaScript, React et pour les API REST, avec des motifs à suivre (pass) et à éviter (fail). Il est conçu pour être utilisé comme une référence universelle, tandis que des skills plus spécifiques (comme `frontend-patterns` ou `backend-patterns`) doivent être employés pour les patrons propres à chaque framework.

Compatible avec~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/coding-standards

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait Conventions de Codage & Bonnes Pratiques ?

Conventions de codage de base applicables à tous les projets.

Ce skill constitue le socle commun, et non le guide détaillé d'un framework.

  • Utilisez frontend-patterns pour React, la gestion d'état, les formulaires, le rendu et l'architecture UI.
  • Utilisez backend-patterns ou api-design pour les couches de référentiel/service, la conception des endpoints, la validation et les préoccupations spécifiques au serveur.
  • Utilisez rules/common/coding-style.md lorsque vous avez besoin de la couche de règle réutilisable la plus courte plutôt que d'un parcours complet.

Quand l'Activer

  • Démarrage d'un nouveau projet ou module
  • Révision du code pour la qualité et la maintenabilité
  • Refactoring du code existant pour suivre les conventions
  • Application de la cohérence des noms, du formatage ou de la structure
  • Mise en place de règles de linting, de formatage ou de vérification de types
  • Intégration de nouveaux contributeurs aux conventions de codage

Limites du Périmètre

Activez ce skill pour :

  • les noms descriptifs
  • l'immutabilité par défaut
  • l'application de la lisibilité, KISS, DRY et YAGNI
  • les attentes en matière de gestion des erreurs et la révision des odeurs de code

N'utilisez pas ce skill comme source principale pour :

  • la composition React, les hooks ou les motifs de rendu
  • l'architecture backend, la conception d'API ou la stratification de base de données
  • les conseils propres à un framework lorsqu'une compétence ECC plus spécifique existe déjà

Principes de Qualité du Code

1. Lisibilité avant tout

  • Le code est plus lu qu'écrit
  • Noms de variables et de fonctions clairs
  • Code auto-documenté privilégié par rapport aux commentaires
  • Formatage cohérent

2. KISS (Keep It Simple, Stupid)

  • La solution la plus simple qui fonctionne
  • Éviter le sur-engineering
  • Pas d'optimisation prématurée
  • Facile à comprendre > code astucieux

3. DRY (Don't Repeat Yourself)

  • Extraire la logique commune dans des fonctions
  • Créer des composants réutilisables
  • Partager des utilitaires entre les modules
  • Éviter la programmation copier-coller

4. YAGNI (You Aren't Gonna Need It)

  • Ne construisez pas de fonctionnalités avant qu'elles ne soient nécessaires
  • Évitez la généralité spéculative
  • N'ajoutez de la complexité que lorsque c'est nécessaire
  • Commencez simple, refactorez quand nécessaire

Standards TypeScript/JavaScript

Nommage des Variables

// PASS : BON : Noms descriptifs
const marketSearchQuery = 'election'
const isUserAuthenticated = true
const totalRevenue = 1000

// FAIL : MAUVAIS : Noms flous
const q = 'election'
const flag = true
const x = 1000

Nommage des Fonctions

// PASS : BON : Motif verbe-nom
async function fetchMarketData(marketId: string) { }
function calculateSimilarity(a: number[], b: number[]) { }
function isValidEmail(email: string): boolean { }

// FAIL : MAUVAIS : Flou ou nom seul
async function market(id: string) { }
function similarity(a, b) { }
function email(e) { }

Motif d'Immutabilité (CRITIQUE)

// PASS : TOUJOURS utiliser l'opérateur spread
const updatedUser = {
  ...user,
  name: 'Nouveau Nom'
}

const updatedArray = [...items, newItem]

// FAIL : NE JAMAIS muter directement
user.name = 'Nouveau Nom'  // MAUVAIS
items.push(newItem)     // MAUVAIS

Gestion des Erreurs

// PASS : BONNE : Gestion d'erreur complète
async function fetchData(url: string) {
  try {
    const response = await fetch(url)

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }

    return await response.json()
  } catch (error) {
    console.error('Échec de récupération :', error)
    throw new Error('Impossible de récupérer les données')
  }
}

// FAIL : MAUVAISE : Aucune gestion d'erreur
async function fetchData(url) {
  const response = await fetch(url)
  return response.json()
}

Bonnes Pratiques Async/Await

// PASS : BON : Exécution parallèle quand c'est possible
const [users, markets, stats] = await Promise.all([
  fetchUsers(),
  fetchMarkets(),
  fetchStats()
])

// FAIL : MAUVAIS : Séquentiel quand ce n'est pas nécessaire
const users = await fetchUsers()
const markets = await fetchMarkets()
const stats = await fetchStats()

Sécurité des Types

// PASS : BON : Types appropriés
interface Market {
  id: string
  name: string
  status: 'active' | 'resolved' | 'closed'
  created_at: Date
}

function getMarket(id: string): Promise<Market> {
  // Implémentation
}

// FAIL : MAUVAIS : Utilisation de 'any'
function getMarket(id: any): Promise<any> {
  // Implémentation
}

Bonnes Pratiques React

Structure des Composants

// PASS : BON : Composant fonctionnel avec types
interface ButtonProps {
  children: React.ReactNode
  onClick: () => void
  disabled?: boolean
  variant?: 'primary' | 'secondary'
}

export function Button({
  children,
  onClick,
  disabled = false,
  variant = 'primary'
}: ButtonProps) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={`btn btn-${variant}`}
    >
      {children}
    </button>
  )
}

// FAIL : MAUVAIS : Pas de types, structure floue
export function Button(props) {
  return <button onClick={props.onClick}>{props.children}</button>
}

Hooks Personnalisés

// PASS : BON : Hook personnalisé réutilisable
export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState<T>(value)

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value)
    }, delay)

    return () => clearTimeout(handler)
  }, [value, delay])

  return debouncedValue
}

// Utilisation
const debouncedQuery = useDebounce(searchQuery, 500)

Gestion d'État

// PASS : BON : Mises à jour d'état correctes
const [count, setCount] = useState(0)

// Mise à jour fonctionnelle pour un état basé sur l'état précédent
setCount(prev => prev + 1)

// FAIL : MAUVAIS : Référence directe à l'état
setCount(count + 1)  // Peut être obsolète dans des scénarios asynchrones

Rendu Conditionnel

// PASS : BON : Rendu conditionnel clair
{isLoading && <Spinner />}
{error && <ErrorMessage error={error} />}
{data && <DataDisplay data={data} />}

// FAIL : MAUVAIS : Enfer ternaire
{isLoading ? <Spinner /> : error ? <ErrorMessage error={error} /> : data ? <DataDisplay data={data} /> : null}

Standards de Conception d'API

Conventions REST

GET    /api/markets              # Lister tous les marchés
GET    /api/markets/:id          # Obtenir un marché spécifique
POST   /api/markets              # Créer un nouveau marché
PUT    /api/markets/:id          # Mettre à jour un marché (complet)
PATCH  /api/markets/:id          # Mettre à jour un marché (partiel)
DELETE /api/markets/:id          # Supprimer un marché

# Paramètres de requête pour le filtrage
GET /api/markets?status=active&limit=10&offset=0

Format de Réponse

// PASS : BON : Structure de réponse cohérente
interface ApiResponse<T> {
  success: boolean
  data?: T
  error?: string
  meta?: {
    total: number
    page: number
    limit: number
  }
}

// Réponse de succès
return NextResponse.json({
  success: true,
  data: markets,
  meta: { total: 100, page: 1, limit: 10 }
})

// Réponse d'erreur
return NextResponse.json({
  success: false,
  error: 'Requête invalide'
}, { status: 400 })

Validation des Entrées

import { z } from 'zod'

// PASS : BON : Validation par schéma
const CreateMarketSchema = z.object({
  name: z.string().min(1).max(200),
  description: z.string().min(1).max(2000),
  endDate: z.string().datetime(),
  categories: z.array(z.string()).min(1)
})

export async function POST(request: Request) {
  const body = await request.json()

  try {
    const validated = CreateMarketSchema.parse(body)
    // Continuer avec les données validées
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json({
        success: false,
        error: 'Échec de validation',
        details: error.issues
      }, { status: 400 })
    }
  }
}

Organisation des Fichiers

Structure du Projet

src/
├── app/                    # Routeur d'application Next.js
│   ├── api/               # Routes API
│   ├── markets/           # Pages des marchés
│   └── (auth)/           # Pages d'authentification (groupes de routes)
├── components/            # Composants React
│   ├── ui/               # Composants UI génériques
│   ├── forms/            # Composants de formulaires
│   └── layouts/          # Composants de mise en page
├── hooks/                # Hooks React personnalisés
├── lib/                  # Utilitaires et configurations
│   ├── api/             # Clients API
│   ├── utils/           # Fonctions d'aide
│   └── constants/       # Constantes
├── types/                # Types TypeScript
└── styles/              # Styles globaux

Nommage des Fichiers

components/Button.tsx          # PascalCase pour les composants
hooks/useAuth.ts              # camelCase avec le préfixe 'use'
lib/formatDate.ts             # camelCase pour les utilitaires
types/market.types.ts         # camelCase avec le suffixe .types

Commentaires & Documentation

Quand Commenter

// PASS : BON : Expliquer POURQUOI, pas QUOI
// Utiliser un backoff exponentiel pour éviter de submerger l'API pendant les pannes
const delay = Math.min(1000 * Math.pow(2, retryCount), 30000)

// Mutation délibérée ici pour des raisons de performance avec de grands tableaux
items.push(newItem)

// FAIL : MAUVAIS : Énoncer l'évidence
// Incrémenter le compteur de 1
count++

// Définir le nom sur le nom de l'utilisateur
name = user.name

JSDoc pour les APIs Publiques

/**
 * Recherche des marchés par similarité sémantique.
 *
 * @param query - Requête de recherche en langage naturel
 * @param limit - Nombre maximum de résultats (défaut : 10)
 * @returns Tableau de marchés triés par score de similarité
 * @throws {Error} Si l'API OpenAI échoue ou si Redis est indisponible
 *
 * @example
 * ```typescript
 * const results = await searchMarkets('election', 5)
 * console.log(results[0].name) // "Trump vs Biden"
 * ```
 */
export async function searchMarkets(
  query: string,
  limit: number = 10
): Promise<Market[]> {
  // Implémentation
}

Bonnes Pratiques de Performance

Mémoïsation

import { useMemo, useCallback } from 'react'

// PASS : BON : Mémoïser les calculs coûteux
// Copier avant de trier - Array.prototype.sort mute sur place
const sortedMarkets = useMemo(() => {
  return [...markets].sort((a, b) => b.volume - a.volume)
}, [markets])

// PASS : BON : Mémoïser les callbacks
const handleSearch = useCallback((query: string) => {
  setSearchQuery(query)
}, [])

Chargement Paresseux (Lazy Loading)

import { lazy, Suspense } from 'react'

// PASS : BON : Charger paresseusement les composants lourds
const HeavyChart = lazy(() => import('./HeavyChart'))

export function Dashboard() {
  return (
    <Suspense fallback={<Spinner />}>
      <HeavyChart />
    </Suspense>
  )
}

Requêtes de Base de Données

// PASS : BON : Sélectionner uniquement les colonnes nécessaires
const { data } = await supabase
  .from('markets')
  .select('id, name, status')
  .limit(10)

// FAIL : MAUVAIS : Tout sélectionner
const { data } = await supabase
  .from('markets')
  .select('*')

Standards de Test

Structure de Test (Motif AAA)

test('calcule la similarité correctement', () => {
  // Arrange (Disposer)
  const vector1 = [1, 0, 0]
  const vector2 = [0, 1, 0]

  // Act (Agir)
  const similarity = calculateCosineSimilarity(vector1, vector2)

  // Assert (Affirmer)
  expect(similarity).toBe(0)
})

Nommage des Tests

// PASS : BON : Noms de test descriptifs
test('retourne un tableau vide quand aucun marché ne correspond à la requête', () => { })
test('lève une erreur quand la clé API OpenAI est manquante', () => { })
test('utilise la recherche par sous-chaîne en secours quand Redis est indisponible', () => { })

// FAIL : MAUVAIS : Noms de test vagues
test('fonctionne', () => { })
test('test recherche', () => { })

Détection des Odeurs de Code

Surveillez ces anti-patrons :

1. Fonctions Longues

// FAIL : MAUVAIS : Fonction > 50 lignes
function processMarketData() {
  // 100 lignes de code
}

// PASS : BON : Diviser en fonctions plus petites
function processMarketData() {
  const validated = validateData()
  const transformed = transformData(validated)
  return saveData(transformed)
}

2. Imbrication Profonde

// FAIL : MAUVAIS : 5+ niveaux d'imbrication
if (user) {
  if (user.isAdmin) {
    if (market) {
      if (market.isActive) {
        if (hasPermission) {
          // Faire quelque chose
        }
      }
    }
  }
}

// PASS : BON : Retours anticipés
if (!user) return
if (!user.isAdmin) return
if (!market) return
if (!market.isActive) return
if (!hasPermission) return

// Faire quelque chose

3. Nombres Magiques

// FAIL : MAUVAIS : Nombres non expliqués
if (retryCount > 3) { }
setTimeout(callback, 500)

// PASS : BON : Constantes nommées
const MAX_RETRIES = 3
const DEBOUNCE_DELAY_MS = 500

if (retryCount > MAX_RETRIES) { }
setTimeout(callback, DEBOUNCE_DELAY_MS)

Rappel : La qualité du code n'est pas négociable. Un code clair et maintenable permet un développement rapide et un refactoring en toute confiance.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Skills associés