Aller au contenu principal

Guide Vibe Coding — 17 prompts prêts à coller

17 prompts éprouvés pour Claude Code et Cursor. Copiez un prompt, collez-le dans votre chat IA, et livrez des fonctionnalités en quelques minutes. Chaque prompt référence les vrais fichiers de ce dépôt, pas un squelette générique.


Comment utiliser ce guide

Avec Claude Code (CLI)

cd /chemin/vers/heartco
claude
# Collez n'importe quel prompt ci-dessous dans le chat

Avec Cursor

  1. Ouvrez ce projet dans Cursor
  2. Appuyez sur Cmd+L (Mac) ou Ctrl+L (Windows) pour ouvrir le chat IA
  3. Copiez-collez n'importe quel prompt ci-dessous
  4. Référencez des fichiers avec @nomdefichier quand c'est indiqué
  5. Laissez-le tourner

🏗️ Modules et fonctionnalités

1. Ajouter un nouveau module (scaffolding complet)

Prompt :

J'ai besoin de créer un nouveau module appelé "{{module_name}}" dans ce dépôt HeartCo.
Suis la structure du template de module dans @src/modules/_template/.

Étapes :
1. Copie src/modules/_template vers src/modules/{{module_name}}
2. Crée un fragment de modèle Prisma (à ajouter dans prisma/schema.prisma) :
   - Doit inclure organizationId pour l'isolation multi-tenant
   - Ajoute @@index([organizationId]) pour la performance des requêtes
   - Ajoute le modèle à ORG_SCOPED_MODELS dans src/lib/prisma-org-scope.ts
3. Crée un router tRPC dans src/server/api/routers/{{module_name}}.ts :
   - Implémente les opérations CRUD (create, read, list, update, delete)
   - Utilise staffProcedure pour les routes internes, protectedProcedure pour le portail client
   - Valide toutes les entrées avec Zod
   - Assure le filtrage par organizationId sur toutes les écritures (update/delete)
4. Enregistre le router dans @src/server/api/root.ts :
   - Importe le nouveau router
   - Ajoute-le à l'objet createTRPCRouter
5. Crée une page dans src/app/dashboard/{{module_name}}/page.tsx :
   - Utilise les composants DataTable et ItemDialog du template
   - Récupère les données via le hook tRPC (api.{{module_name}}.list.useQuery())
6. Mets à jour la navigation dans src/components/layout/sidebar.tsx :
   - Ajoute une entrée de menu pointant vers /dashboard/{{module_name}}
7. Crée des tests unitaires dans src/server/api/routers/__tests__/{{module_name}}.test.ts :
   - Mocke le client Prisma
   - Teste toutes les opérations CRUD
   - Teste la sécurité (filtrage par organizationId)

Une fois en place, lance :
- pnpm prisma generate
- pnpm typecheck
- pnpm test
- pnpm lint:fix

Résultat attendu : un module CRUD complet et fonctionnel, avec page, router, composants et tests.

Fichiers de contexte : @src/modules/_template/ @src/server/api/root.ts @prisma/schema.prisma @src/lib/prisma-org-scope.ts

Résultat attendu : un module complet, prêt pour la production, avec page, router tRPC, modèle Prisma, composants et tests.

Vérifier que ça marche :

pnpm typecheck
pnpm dev
# Va sur http://localhost:3000/dashboard/{{module_name}}
# Essaie de créer, lire, modifier et supprimer des éléments
pnpm test -- {{module_name}}

2. Ajouter un champ à un modèle existant

Prompt :

J'ai besoin d'ajouter un champ au modèle Prisma "{{ModelName}}".

Détails du champ :
- Nom : {{fieldName}}
- Type : {{fieldType}} (ex : String, Int, Boolean, DateTime)
- Requis/Optionnel : {{required}}
- Valeur par défaut : {{defaultValue}} (le cas échéant)
- Indexé : {{isIndexed}} (true/false)

Étapes :
1. Ajoute le champ à prisma/schema.prisma dans le modèle {{ModelName}}
2. Si le modèle a déjà organizationId, PAS BESOIN de le rajouter
3. Crée une migration Prisma :
   - npx prisma migrate dev --name add_{{fieldName}}_to_{{model_name}}
4. Mets à jour le router tRPC dans src/server/api/routers/{{router_name}}.ts :
   - Mets à jour les schémas Zod (validation d'entrée)
   - Mets à jour les procédures du router pour inclure le nouveau champ dans les requêtes/mutations
5. Mets à jour le composant React :
   - S'il s'agit d'un formulaire, ajoute un champ avec react-hook-form
   - S'il s'agit d'un tableau, ajoute une colonne à DataTable
6. Lance le pipeline complet :
   - pnpm prisma generate
   - pnpm typecheck
   - pnpm test
   - pnpm lint:fix

N'oublie PAS l'étape de migration : les migrations sont commitées dans git.

Fichiers de contexte : @prisma/schema.prisma @src/server/api/routers/ (le router concerné)

Résultat attendu : un nouveau champ ajouté au modèle, une migration Prisma créée, le router et l'interface mis à jour.

Vérifier que ça marche :

npx prisma migrate status
pnpm typecheck
pnpm test -- {{router_name}}
pnpm dev
# Vérifie que le champ apparaît dans les formulaires/tableaux

3. Créer un tableau de bord KPI pour

Prompt :

Crée une page de tableau de bord KPI pour {{module_name}} dans src/app/dashboard/{{module_name}}/analytics/page.tsx.

Exigences :
1. Affiche 4 métriques clés dans une grille de cartes :
   - {{metric1_name}} (valeur, tendance, unité)
   - {{metric2_name}} (valeur, tendance, unité)
   - {{metric3_name}} (valeur, tendance, unité)
   - {{metric4_name}} (valeur, tendance, unité)
2. Ajoute un sélecteur de plage de dates (shadcn DatePicker, optionnel)
3. Utilise Recharts pour la visualisation :
   - Graphique en ligne pour les séries temporelles
   - Graphique en barres pour la comparaison
4. Récupère les données via une requête tRPC (à créer si absente) :
   - src/server/api/routers/{{module_name}}.ts → procédure analytics
   - La requête retourne : { metrics: {...}, chartData: [...] }
5. Style :
   - Utilise le composant Card de shadcn
   - Applique Tailwind pour la mise en page (grid-cols-4 sur desktop, grid-cols-1 sur mobile)
   - Support du mode sombre (utilise les tokens de design.md)
   - Ajoute des animations subtiles (Framer Motion au scroll)
6. Gestion des erreurs :
   - Affiche un squelette de chargement pendant la récupération
   - Affiche un message d'erreur si la requête échoue
   - Repli propre en l'absence de données

Utilise @src/components/landing/ pour les patterns d'animation et @src/lib/utils.ts pour l'utilitaire cn().

Fichiers de contexte : @src/components/ui/card.tsx @src/lib/utils.ts ./.claude/rules/design.md

Résultat attendu : une page d'analytics soignée, avec cartes KPI, graphiques et filtrage par date.

Vérifier que ça marche :

pnpm dev
# Va sur /dashboard/{{module_name}}/analytics
# Vérifie que les métriques se chargent et que les graphiques s'affichent
# Vérifie le design responsive sur mobile

4. Ajouter une page avec formulaire (création/édition)

Prompt :

Crée une page de formulaire pour {{resource_name}} dans src/app/dashboard/{{module_name}}/[id]/page.tsx (édition) et une modale de création dans src/components/{{module_name}}/{{resource_name}}Form.tsx.

Détails du formulaire :
- Ressource : {{resource_name}}
- Champs : {{field1_name}} (type : {{type1}}), {{field2_name}} (type : {{type2}}), ...
- Endpoint de création : api.{{module_name}}.create.useMutation()
- Endpoint de mise à jour : api.{{module_name}}.update.useMutation()
- Endpoint de suppression : api.{{module_name}}.delete.useMutation() (optionnel)

Implémentation :
1. Crée un schéma Zod dans src/server/api/routers/{{module_name}}.ts :
   - Définis createInput et updateInput avec la validation appropriée
   - Ajoute des raffinements personnalisés si besoin (ex : validations de dates)
2. Crée les procédures tRPC :
   - create : staffProcedure + validation d'entrée → sauvegarde en BDD
   - update : staffProcedure + validation d'entrée + vérification organizationId
   - delete : staffProcedure + suppression douce ou définitive (à décider)
3. Crée le composant formulaire dans src/components/{{module_name}}/{{resource_name}}Form.tsx :
   - Utilise react-hook-form + react-hook-form/resolvers
   - Connecte les champs du formulaire au schéma Zod (zodResolver)
   - Ajoute un handler de soumission : appelle la mutation → navigue en cas de succès
   - Affiche un état de chargement pendant la mutation
   - Affiche un toast d'erreur si la mutation échoue
4. Crée la page dans src/app/dashboard/{{module_name}}/[id]/page.tsx :
   - Récupère les données de la ressource existante en édition
   - Passe les données au composant formulaire
   - Affiche un 404 si la ressource n'est pas trouvée (protection IDOR)
5. Ajoute les champs du formulaire :
   - Champs texte : <Input /> de shadcn
   - Select : <Select /> de shadcn
   - Cases à cocher : <Checkbox /> de shadcn
   - Date/heure : <DatePicker /> de shadcn
   - Texte enrichi : envisage @tiptap/react si besoin
6. Stylise le formulaire :
   - Utilise Tailwind pour la mise en page (flex, grid)
   - Ajoute un espacement et une typographie soignés
   - Marque les champs requis d'un astérisque
   - Affiche les erreurs de validation en ligne

Utilise @src/modules/_template/components/ItemForm.tsx comme référence structurelle.

Fichiers de contexte : @src/modules/_template/components/ItemForm.tsx @src/components/ui/ @src/lib/utils.ts

Résultat attendu : un formulaire de création/édition pleinement fonctionnel, avec validation, gestion d'erreurs et sécurité de type.

Vérifier que ça marche :

pnpm typecheck
pnpm dev
# Va sur le formulaire de création
# Remplis les champs et soumets → vérifie que les données sont sauvegardées en BDD
# Édite une ressource existante → vérifie que les données se chargent et se mettent à jour
# Déclenche des erreurs de validation → vérifie que les messages s'affichent

5. Créer un tableau Kanban pour

Prompt :

Crée un tableau Kanban (glisser-déposer) pour {{resource_name}} dans src/app/dashboard/{{module_name}}/kanban/page.tsx.

Exigences :
1. Colonnes de statut : {{status1}}, {{status2}}, {{status3}}, {{status4}} (selon ton domaine métier)
2. Cartes :
   - Affiche {{field1}}, {{field2}}, {{field3}} sur chaque carte
   - Code couleur selon priorité/catégorie (optionnel)
   - Clic pour ouvrir la modale de détail (pattern ItemDialog)
3. Glisser-déposer :
   - Utilise la librairie dnd-kit (déjà dans le projet)
   - Glisser une carte d'une colonne à l'autre met à jour son statut
   - Mise à jour optimiste de l'UI + mutation serveur
   - Annulation si la mutation échoue
4. Récupération des données :
   - Récupère tous les éléments groupés par statut
   - Ou récupère tous les éléments et groupe-les côté React (plus simple pour un petit jeu de données)
5. Style :
   - Conteneurs de colonnes avec bordure et fond
   - Cartes avec ombre au survol
   - Animations de glissement fluides
   - Mobile : bascule en défilement vertical (pas de glisser-déposer au toucher)

Prends comme référence le pattern Kanban du CRM dans src/app/dashboard/crm/[id]/kanban/page.tsx.

Étapes :
1. Crée les procédures tRPC dans src/server/api/routers/{{module_name}}.ts :
   - listByStatus : retourne les éléments groupés par statut
   - updateStatus : change le statut d'un élément (mutation)
2. Crée le composant Kanban dans src/components/{{module_name}}/KanbanBoard.tsx :
   - Utilise dnd-kit pour le glisser-déposer
   - Affiche les colonnes de statut dans une grille horizontale
3. Crée la page dans src/app/dashboard/{{module_name}}/kanban/page.tsx
4. Ajoute à la navigation de la sidebar

Fichiers de contexte : @src/app/dashboard/crm/ (pour la référence Kanban du CRM), @src/lib/utils.ts

Résultat attendu : un tableau Kanban pleinement fonctionnel, avec mises à jour de statut par glisser-déposer.

Vérifier que ça marche :

pnpm dev
# Va sur /dashboard/{{module_name}}/kanban
# Glisse des cartes entre les colonnes → vérifie que le statut se met à jour en BDD
# Rafraîchis la page → vérifie que les changements persistent
# Vue mobile → vérifie l'absence de glisser-déposer, mais les détails restent cliquables

🔌 Intégrations

6. Intégrer une API externe (avec cache)

Prompt :

Intègre l'API {{api_name}} dans HeartCo.

Détails de l'API :
- URL de base : {{api_url}}
- Authentification : {{auth_type}} (Bearer, clé API, OAuth)
- Limite de débit : {{rate_limit}}
- Endpoints clés : {{endpoints}}
- Exemple de réponse : {{example_response}}

Implémentation :
1. Crée une couche de service dans src/lib/api/{{api_name}}-client.ts :
   - Authentifie-toi auprès de l'API (utilise des variables d'environnement pour les secrets)
   - Implémente des fonctions typées pour chaque endpoint
   - Ajoute la gestion d'erreurs et une logique de nouvelle tentative (backoff exponentiel)
   - Type les réponses avec des interfaces TypeScript
2. Ajoute une couche de cache Redis :
   - Cache les requêtes GET de 5 à 60 min (selon l'endpoint)
   - Invalide le cache lors des mutations
   - Pattern : vérifie Redis d'abord → appelle l'API → stocke dans Redis
   - Format de clé Redis : "{{api_name}}:{{resource_id}}"
3. Crée les procédures tRPC dans src/server/api/routers/{{module_name}}.ts :
   - Appelle le service → ajoute à la réponse du contexte
   - Ajoute des gardes requirePermission() si nécessaire
   - Valide organizationId pour l'isolation multi-tenant
4. Gère les limites de débit avec élégance :
   - En cas de rate limit, retourne les données en cache (si disponibles)
   - Journalise les avertissements de rate limit
   - Implémente une stratégie de backoff
5. Ajoute les variables d'environnement dans src/env.js :
   - {{API_NAME}}_API_KEY
   - {{API_NAME}}_BASE_URL
   - Valide au démarrage de l'app
6. Crée des tests :
   - Mocke le client API dans src/server/api/routers/__tests__/
   - Teste les hits/miss de cache
   - Teste les scénarios d'erreur

Utilise @src/modules/bridge/client.ts comme référence pour les patterns d'intégration API.

Fichiers de contexte : @src/modules/bridge/client.ts @src/env.js @src/lib/redis.ts

Résultat attendu : une intégration API de niveau production, avec cache, gestion d'erreurs et sécurité de type.

Vérifier que ça marche :

pnpm typecheck
pnpm test -- {{module_name}}
pnpm dev
# Appelle la procédure tRPC → vérifie la réponse de l'API
# Rappelle-la → vérifie la mise en cache (vérifie Redis)
# Coupe l'API → vérifie le repli propre

7. Ajouter des webhooks entrants (avec vérification HMAC)

Prompt :

Ajoute le support de webhooks pour {{webhook_provider}} (ex : Stripe, Bridge, Mistral).

Détails du webhook :
- Fournisseur : {{webhook_provider}}
- Types d'événements : {{event_types}}
- En-tête de signature : {{signature_header}} (ex : "x-webhook-signature")
- Secret : stocké en variable d'environnement sous {{SECRET_ENV_VAR}}
- Structure du payload attendu : {{payload_structure}}

Implémentation :
1. Crée un handler de webhook dans src/app/api/webhooks/{{webhook_provider}}/route.ts :
   - Accepte les requêtes POST
   - Extrait le corps brut de la requête (nécessaire pour la vérification HMAC)
   - Vérifie la signature HMAC avec crypto.timingSafeEqual (jamais avec ===)
   - Parse et valide le payload avec Zod
   - Réponds 200 immédiatement (traitement asynchrone)
2. Crée un processeur de webhook dans src/server/webhooks/{{webhook_provider}}-processor.ts :
   - Gère chaque type d'événement (if/switch sur event.type)
   - Met à jour la base de données selon l'événement
   - Utilise organizationId du payload ou du contexte de l'événement
   - Ajoute la journalisation d'erreurs (journalise les événements non parsables)
3. Mises à jour de la base de données :
   - Exemple : sur "payment.success" → met à jour le statut de la facture
   - Exemple : sur "user.created" → synchronise vers le CRM
   - Toujours envelopper dans try/catch, toujours journaliser les échecs
4. Ajoute des tests dans src/server/webhooks/__tests__/ :
   - Teste qu'une signature valide passe, qu'une signature invalide est rejetée
   - Teste que chaque type d'événement est traité correctement
   - Teste la vérification HMAC (crypto.timingSafeEqual)
5. Configuration de l'environnement :
   - Ajoute {{SECRET_ENV_VAR}} à .env.example
   - Valide dans src/env.js

Règles de sécurité critiques :
- Utilise TOUJOURS crypto.timingSafeEqual pour la vérification HMAC
- N'utilise JAMAIS === pour comparer des signatures (vulnérabilité de type timing attack)
- Vérifie la signature avant de traiter le payload
- Journalise tous les échecs de signature (attaques potentielles)
- Réponds 200 même si le traitement échoue (n'invite pas à des tentatives infinies)
- Utilise le filtrage par organizationId sur toutes les mises à jour de BDD

Prends comme référence @src/app/api/bridge/webhook/route.ts et @src/modules/bridge/__tests__/webhook-hmac.test.ts pour les patterns de webhook existants.

Fichiers de contexte : @src/app/api/bridge/webhook/route.ts @src/modules/bridge/__tests__/webhook-hmac.test.ts @src/env.js

Résultat attendu : un handler de webhook sécurisé, de niveau production, avec vérification HMAC et journalisation d'erreurs.

Vérifier que ça marche :

pnpm typecheck
pnpm test -- webhooks
# Utilise ngrok ou un outil équivalent pour exposer localhost
# Envoie un webhook de test depuis le fournisseur
# Vérifie que le payload est traité et la BDD mise à jour
# Envoie une signature invalide → vérifie le rejet

8. Ajouter des événements temps réel avec Pusher

Prompt :

Ajoute le support de notifications temps réel avec Pusher.

Scénarios :
- {{scenario1}} (ex : "Quand une nouvelle facture est créée, notifier tous les managers")
- {{scenario2}} (ex : "Quand un message de chat est envoyé, notifier le destinataire en temps réel")

Implémentation :
1. Configure le client Pusher :
   - Ajoute NEXT_PUBLIC_PUSHER_KEY, PUSHER_SECRET, PUSHER_CLUSTER au .env
   - Valide dans src/env.js
   - Crée les instances Pusher dans src/lib/pusher-server.ts (serveur) et src/lib/pusher-client.ts (client), si elles n'existent pas déjà
2. Crée un déclencheur côté serveur dans le router tRPC :
   - Après la création d'une ressource {{resource}} (ex : Invoice), appelle pusher.trigger()
   - Nom du canal : "org_{{organizationId}}_{{resource_type}}"
   - Nom de l'événement : "{{resource_type}}.created"
   - Données : payload JSON (évite les données sensibles)
3. Crée l'abonnement côté client :
   - Utilise useEffect pour s'abonner au canal Pusher
   - Appelle pusher.subscribe("org_..." + organizationId)
   - Écoute l'événement : channel.bind("{{event_name}}", callback)
   - Met à jour l'état React sur événement
   - Nettoyage : désabonne au démontage
4. Mises à jour de l'interface :
   - Affiche une notification toast à la réception de l'événement
   - Met à jour la liste en temps réel de façon optionnelle (re-fetch ou ajout à l'état)
   - Mises à jour optimistes pour une meilleure UX
5. Sécurité :
   - Abonne-toi uniquement aux canaux de ta propre organisation (utilise organizationId)
   - Vérifie la signature Pusher sur les canaux privés (le cas échéant)
   - N'envoie pas de données sensibles via les événements Pusher
6. Tests :
   - Mocke Pusher dans les tests unitaires (vi.mock() en début de test)
   - Teste que le déclencheur est appelé avec le bon canal/événement
   - Teste l'abonnement et le callback

Utilise @src/lib/pusher-server.ts et @src/lib/pusher-client.ts, et cherche les usages Pusher existants dans le dépôt.

Fichiers de contexte : @src/lib/pusher-server.ts @src/lib/pusher-client.ts @src/env.js

Résultat attendu : des notifications temps réel fonctionnelles entre plusieurs onglets et utilisateurs.

Vérifier que ça marche :

pnpm dev
# Ouvre 2 fenêtres de navigateur, même organisation
# Crée une {{resource}} dans une fenêtre
# Vérifie que la notification apparaît immédiatement dans l'autre fenêtre
# Vérifie la console du navigateur pour les logs de debug Pusher

9. Ajouter un fournisseur IA (Mistral)

Prompt :

Intègre {{ai_provider}} pour {{use_case}}.

Détails de l'intégration :
- Fournisseur : {{ai_provider}}
- Variable d'environnement de clé API : {{API_KEY_VAR}}
- Modèle : {{model_name}}
- Cas d'usage : {{use_case}} (ex : "générer des résumés de factures", "analyser des images")
- Entrée : {{input_structure}}
- Sortie attendue : {{output_structure}}
- Limite de débit/quota : {{quota_info}}

Implémentation :
1. Crée un client IA dans src/lib/ai/{{provider_name}}-client.ts :
   - Initialise le client avec la clé API depuis l'environnement
   - Implémente une fonction pour ton cas d'usage (ex : generateSummary())
   - Gère le streaming si applicable (pour les réponses longues)
   - Ajoute un timeout (ex : 30 s) et une logique de nouvelle tentative
   - Retourne une réponse typée (interface TypeScript)
   - Journalise l'usage de l'API (tokens, latence) pour le suivi du quota freemium
2. Ajoute au système de quota freemium (si applicable) :
   - Ajoute {{ai_use_case}}PerMonth à src/lib/freemium/freemium-limits.ts
   - Appelle checkFreemiumLimit() dans le router tRPC avant l'appel API
   - Incrémente le compteur d'usage après un appel API réussi
   - Référence : ./.claude/rules/freemium.md
3. Crée une procédure tRPC dans src/server/api/routers/{{module_name}}.ts :
   - Entrée : {{input_fields}} (validée par Zod)
   - Vérifie le quota freemium
   - Appelle le client IA
   - Stocke le résultat en BDD (si besoin)
   - Retourne une réponse typée
4. Optionnel : ajoute au contexte du prompt :
   - Si multi-tour : maintiens l'historique de conversation en BDD
   - Stocke le prompt système en config ou en base
5. Gestion d'erreurs :
   - Erreurs de rate limit → suggère de réessayer plus tard
   - Entrée invalide → retourne BAD_REQUEST
   - Erreurs API → journalise et retourne une erreur générique (n'expose pas les détails de l'API)
6. Tests :
   - Mocke les réponses de l'API {{ai_provider}}
   - Teste l'application du quota
   - Teste les scénarios d'erreur

Utilise @src/lib/ai/ comme référence pour les patterns d'intégration IA (l'intégration Mistral existante).

Fichiers de contexte : @src/lib/ai/ @src/env.js @src/lib/freemium/ ./.claude/rules/freemium.md

Résultat attendu : une fonctionnalité IA pleinement intégrée, avec gestion de quota et gestion d'erreurs.

Vérifier que ça marche :

pnpm typecheck
pnpm dev
# Appelle la procédure tRPC IA
# Vérifie que la réponse est retournée et stockée (si applicable)
# Vérifie que l'usage du quota est incrémenté
# Dépasse le quota → vérifie le message d'erreur propre

🔐 Authentification et sécurité

10. Ajouter un nouveau rôle utilisateur au RBAC

Prompt :

Ajoute un nouveau rôle "{{role_name}}" (ex : "FINANCE_MANAGER") au système RBAC.

Détails du rôle :
- Nom du rôle : {{role_name}} (doit être en MAJUSCULES)
- Permissions : {{permission_list}} (ex : "facturation:read", "comptabilite:export_fec")
- Peut gérer : {{manages_resources}} (optionnel)
- Hiérarchie de rôle parent : {{inherits_from}} (optionnel, ex : hérite de MANAGER)

Implémentation :
1. Ajoute le rôle à l'union de type dans src/lib/permissions/matrix.ts :
   - Ajoute "{{role_name}}" à la définition du type Role
2. Ajoute à la matrice de permissions (même fichier) :
   - Définis l'objet de permissions pour {{role_name}}
   - Assigne un tableau de chaînes de permission
   - Suis le format "ressource:action"
   - Référence les permissions existantes (ne crée pas de doublons)
3. Mets à jour le schéma Prisma dans prisma/schema.prisma :
   - Si le rôle détermine des valeurs par défaut de champ, ajoute une migration
   - Exemple : "role: {{role_name}}" → accès en lecture seule à certaines tables
4. Mets à jour l'interface de sélection de rôle :
   - Vérifie que src/app/dashboard/organization/members/page.tsx affiche le nouveau rôle dans le menu déroulant
   - Assure-toi que seul ADMIN peut assigner ce rôle
5. Crée un seed de rôle (si applicable) :
   - Ajoute aux seeders de base de données si tu utilises un seed Prisma
6. Ajoute des tests dans src/__tests__/security/ :
   - Teste que le rôle a les bonnes permissions
   - Teste que le rôle ne peut pas accéder aux ressources interdites
   - Teste la hiérarchie de rôle si applicable

Suis la structure de la matrice RBAC dans @src/lib/permissions/matrix.ts — c'est la source de vérité.

Fichiers de contexte : @src/lib/permissions/matrix.ts @prisma/schema.prisma @src/__tests__/security/

Résultat attendu : un nouveau rôle disponible dans l'interface de gestion des membres, avec les bonnes restrictions de permissions.

Vérifier que ça marche :

pnpm test:security
pnpm typecheck
pnpm dev
# Va sur /dashboard/organization/members
# Vérifie que le nouveau rôle apparaît dans le menu déroulant
# Assigne le rôle à un utilisateur de test
# Connecte-toi en tant que cet utilisateur → vérifie l'accès aux bonnes ressources
# Essaie d'accéder à une ressource interdite → vérifie l'erreur 403

11. Ajouter une permission granulaire à la matrice RBAC

Prompt :

Ajoute une nouvelle permission granulaire "{{permission_string}}" (ex : "invoices:void").

Détails de la permission :
- Chaîne de permission : {{permission_string}} (format : "ressource:action")
- Description : {{description}}
- Quels rôles peuvent l'utiliser : {{role_list}} (ex : ADMIN, DIRECTION, MANAGER)
- Remplace/s'ajoute à : {{existing_permission}} (si refactoring)

Implémentation :
1. Ajoute la chaîne de permission à l'union de type Permission dans @src/lib/permissions/matrix.ts :
   - Ligne 22, ajoute : | "{{permission_string}}"
   - Garde l'ordre alphabétique au sein du groupe de ressource
2. Mets à jour les assignations de permissions par rôle (dans le même fichier) :
   - Pour chaque rôle qui doit avoir cette permission, ajoute la chaîne à son tableau de permissions
3. Mets à jour le garde du router tRPC :
   - Trouve la procédure tRPC qui a besoin de cette permission
   - Remplace staffProcedure ou un autre garde par : requirePermission("{{permission_string}}")
   - Exemple : export const {{procName}} = {{procedure}}.use(requirePermission("{{permission_string}}"))
4. Mets à jour les vérifications de permission :
   - Si vérification dynamique, utilise hasPermission(ctx.session, "{{permission_string}}")
5. Ajoute à l'interface (menu déroulant d'assignation de rôle) :
   - Vérifie que la nouvelle permission apparaît dans les paramètres d'organisation (si une interface de permissions existe)
   - La plupart des projets gèrent ça uniquement via matrix.ts
6. Ajoute un test :
   - src/__tests__/security/rbac.test.ts → teste que le rôle a la permission

Référence : @src/lib/permissions/matrix.ts (source de vérité), @src/server/api/trpc.ts (helper requirePermission).

Fichiers de contexte : @src/lib/permissions/matrix.ts @src/server/api/trpc.ts @src/__tests__/security/

Résultat attendu : une nouvelle permission appliquée dans les routers tRPC, accessible seulement aux rôles autorisés.

Vérifier que ça marche :

pnpm test:security
pnpm typecheck
pnpm dev
# En tant que rôle autorisé, appelle la procédure protégée → réussit
# En tant que rôle non autorisé, appelle la procédure → échoue avec FORBIDDEN
# Vérifie que la procédure utilise le garde requirePermission()

12. Ajouter un fournisseur OAuth (GitHub, Google, etc.)

Prompt :

Ajoute la connexion OAuth via {{oauth_provider}} (ex : GitHub, Google, Azure AD).

Détails du fournisseur :
- Fournisseur : {{oauth_provider}}
- Client ID : {{client_id_env_var}}
- Client Secret : {{client_secret_env_var}}
- Scopes : {{scopes}} (ex : "user:email", "profile")
- URL de callback : https://{{domain}}/api/auth/callback/{{provider_slug}}

Implémentation :
1. Configure les identifiants du fournisseur :
   - Va dans la console développeur de {{provider}}
   - Crée une app OAuth avec l'URL de callback ci-dessus
   - Copie le Client ID et le Secret
   - Ajoute au .env : {{CLIENT_ID_ENV_VAR}}={{id}}, {{CLIENT_SECRET_ENV_VAR}}={{secret}}
   - Ajoute au .env.example (SANS le secret)
2. Mets à jour la config NextAuth dans src/app/api/auth/[...nextauth]/route.ts :
   - Importe {{Provider}}Provider depuis next-auth/providers/{{provider_slug}}
   - Ajoute au tableau providers :
     {{Provider}}Provider({
       clientId: env.{{CLIENT_ID_ENV_VAR}},
       clientSecret: env.{{CLIENT_SECRET_ENV_VAR}},
       allowDangerousEmailAccountLinking: false,
     })
3. Ajoute les variables d'environnement à src/env.js :
   - {{CLIENT_ID_ENV_VAR}}: z.string(),
   - {{CLIENT_SECRET_ENV_VAR}}: z.string(),
4. Teste le flux OAuth :
   - Lance pnpm dev
   - Va sur /api/auth/signin
   - Clique sur "{{OAuth Provider}}"
   - Autorise l'app
   - Vérifie la redirection vers le dashboard
5. Gère les nouveaux utilisateurs :
   - La logique existante dans les callbacks NextAuth doit créer l'utilisateur automatiquement
   - Vérifie que user.organizationId est bien défini (un callback custom peut être nécessaire)
6. Sécurité :
   - Stocke les secrets dans l'environnement (jamais commité)
   - Utilise une validation de callback sécurisée
   - Valide les tokens du fournisseur

Référence : src/app/api/auth/[...nextauth]/route.ts pour les exemples OAuth existants.

Fichiers de contexte : @src/app/api/auth/[...nextauth]/route.ts @src/env.js .env.example

Résultat attendu : une connexion OAuth fonctionnelle, avec provisioning automatique des utilisateurs.

Vérifier que ça marche :

pnpm dev
# Va sur /api/auth/signin
# Clique sur {{OAuth Provider}}
# Autorise et vérifie la connexion
# Vérifie que l'utilisateur est créé en base
# Déconnecte-toi et reconnecte-toi → vérifie que l'utilisateur existant est retrouvé

🎨 UI et design

13. Personnaliser le design system (theming)

Prompt :

Personnalise les couleurs, polices et tokens du design system HeartCo.

Personnalisations :
- Couleur de marque : {{hex_color}} (ex : #6366f1)
- Couleur d'accent : {{accent_color}}
- Police (titres) : {{heading_font}} (ex : "Plus Jakarta Sans")
- Police (corps) : {{body_font}} (ex : "Geist")
- Mode sombre : activé/désactivé
- Tokens supplémentaires : {{custom_tokens}}

Implémentation :
1. Mets à jour la config Tailwind dans tailwind.config.ts :
   - colors.brand : mets à jour vers {{brand_color}}
   - colors.accent : mets à jour vers {{accent_color}}
   - fonts : mets à jour les polices de titre et de corps
   - Ajoute des tokens de couleur personnalisés si besoin
2. Mets à jour les variables CSS dans src/styles/globals.css :
   - --color-brand: {{hex_color}}
   - --color-accent: {{accent_color}}
   - --color-dark: {{dark_bg}}
   - --color-light: {{light_bg}}
3. Mets à jour le thème shadcn/ui (si tu utilises un bouton de bascule mode sombre) :
   - src/components/ui/theme-provider.tsx
   - Ajuste le schéma par défaut (light/dark/system)
4. Mets à jour les tokens de design marketing :
   - Référence : @./.claude/rules/design.md
   - Assure-toi qu'aucune couleur n'est codée en dur dans les composants
   - Utilise des couleurs basées sur des tokens : bg-brand, text-brand, etc.
5. Teste le thème sur toutes les pages :
   - Pages du dashboard
   - Sections de la landing page
   - Bascule mode sombre
   - Responsive mobile
6. Commite les changements :
   - Mets à jour tailwind.config.ts
   - Mets à jour globals.css
   - Commite avec : chore: customize design system colors

Lance :
- pnpm lint:fix (linting des classes Tailwind)
- pnpm format:write

Fichiers de contexte : @tailwind.config.ts @src/styles/globals.css @./.claude/rules/design.md

Résultat attendu : un theming cohérent sur toute l'application, avec les nouvelles couleurs de marque.

Vérifier que ça marche :

pnpm dev
# Vérifie les pages /dashboard et / pour les nouvelles couleurs
# Bascule le mode sombre → vérifie que les deux thèmes utilisent les nouvelles couleurs
# Aucune couleur codée en dur ne doit apparaître (utilise les tokens)
# Vue mobile → vérifie le responsive

14. Créer une librairie de composants réutilisables

Prompt :

Crée un composant réutilisable {{component_name}} dans src/components/{{component_name}}.tsx.

Détails du composant :
- Nom : {{component_name}} (ex : "CardWithBadge")
- Props : {{prop_list}} (ex : "title: string, badge: string, onClick?: () => void")
- Variantes : {{variants}} (ex : "primary, secondary, outline")
- Cas d'usage : {{use_case}}
- Où il est utilisé : {{usage_locations}} (actuel/futur)

Implémentation :
1. Crée le fichier du composant dans src/components/{{component_name}}.tsx :
   - Accepte les props via une interface TypeScript
   - Utilise forwardRef si le composant doit accepter une ref
   - Implémente plusieurs variantes avec l'utilitaire cn()
   - Ajoute des commentaires JSDoc (explique les props et les variantes)
2. Style :
   - Utilise les classes Tailwind (cn() pour la fusion)
   - Support du mode sombre (utilise les tokens de couleur, jamais codées en dur)
   - Ajoute des états hover/active/focus
   - Design responsive si applicable
3. Accessibilité :
   - HTML sémantique approprié (button, div, section, etc.)
   - Labels ARIA où nécessaire
   - Navigation au clavier si interactif
   - États focus visibles
4. Documentation :
   - JSDoc sur le composant et les props
   - Commentaire d'exemple d'usage
5. Export :
   - Ajoute l'export à src/components/index.ts (si centralisé)
   - Ou exporte directement depuis le fichier
6. Crée une story (optionnel, si Storybook est utilisé) :
   - src/components/{{component_name}}.stories.tsx
   - Montre toutes les variantes
   - Montre avec différents contenus

Prends comme référence les composants shadcn/ui pour les patterns : @src/components/ui/

Fichiers de contexte : @src/components/ui/ @src/lib/utils.ts @./.claude/rules/design.md

Résultat attendu : un composant réutilisable, bien documenté, avec plusieurs variantes.

Vérifier que ça marche :

pnpm typecheck
# Importe et utilise {{component_name}} dans une page de test
pnpm dev
# Vérifie que le composant s'affiche correctement
# Teste toutes les variantes
# Teste le mode sombre
# Teste le design responsive sur mobile

🚀 DevOps et déploiement

15. Déployer en production (Vercel + Supabase)

Prompt :

Configure le déploiement en production de HeartCo sur Vercel avec PostgreSQL Supabase.

Prérequis :
- Compte Vercel créé
- Projet Supabase créé
- Dépôt GitHub connecté à Vercel

Étapes :
1. Configuration Supabase :
   - Crée un projet PostgreSQL dans Supabase
   - Copie DATABASE_URL (variable d'environnement)
   - Lance les migrations : npx prisma migrate deploy
   - Crée des sauvegardes dans le dashboard Supabase
2. Variables d'environnement Vercel :
   - Configure toutes les variables .env dans les paramètres du projet Vercel :
     - DATABASE_URL (depuis Supabase)
     - NEXTAUTH_SECRET (génère avec : openssl rand -base64 32)
     - NEXTAUTH_URL (https://tondomaine.com)
     - Secrets des fournisseurs OAuth (GitHub, Google, etc.)
     - Clés Stripe, clés Pusher, clés API Mistral
     - Toutes les variables de .env.example
   - Ne commite JAMAIS .env dans git
3. Migrations Prisma :
   - Assure-toi que toutes les migrations sont commitées dans git
   - Vercel lance "pnpm install && pnpm build" automatiquement
   - Le script de build doit inclure : npx prisma generate && npx prisma migrate deploy
   - Vérifie que next.config.js a l'étape de build Prisma (si nécessaire)
4. Sauvegardes de base de données :
   - Active les sauvegardes quotidiennes automatiques dans Supabase
   - Stocke les identifiants de sauvegarde de façon sécurisée
5. Monitoring :
   - Configure la journalisation d'erreurs (Sentry recommandé)
   - Surveille les logs Vercel dans le dashboard
   - Configure le monitoring des requêtes de base dans Supabase
6. Domaine personnalisé :
   - Pointe le DNS vers Vercel
   - Configure le CNAME dans les paramètres du projet Vercel
   - Mets à jour NEXTAUTH_URL et les URL de callback OAuth
7. SSL/TLS :
   - Vercel active HTTPS automatiquement
   - Surveille le statut du certificat SSL
8. Vérifie le déploiement :
   - Déclenche un déploiement depuis un git push
   - Vérifie les logs de build Vercel (aucune erreur)
   - Ouvre l'app en ligne et teste les fonctionnalités clés
   - Vérifie que les écritures en base persistent

Utilise les checklists de variables d'environnement de .env.example.

Fichiers de contexte : .env.example @next.config.js @prisma/schema.prisma @package.json

Résultat attendu : l'app en ligne sur Vercel, avec déploiement automatique à chaque push git.

Vérifier que ça marche :

# Push vers la branche main
# Vérifie le dashboard Vercel → le build se termine
# Visite l'URL en ligne → vérifie que toutes les fonctionnalités marchent
# Vérifie la base de données → les nouvelles données persistent
# Surveille les logs Vercel → aucune erreur

16. Ajouter des tests pour un module (Vitest + Testing Library)

Prompt :

Crée des tests complets pour le module {{module_name}}.

Périmètre des tests :
- Tests unitaires des procédures du router (CRUD)
- Tests de sécurité (IDOR, vérifications de permission)
- Tests d'intégration (interactions BDD)
- Optionnel : tests E2E avec Playwright

Implémentation :
1. Crée le fichier de test dans src/server/api/routers/__tests__/{{module_name}}.test.ts :
   - Utilise Vitest (describe, it, expect)
   - Mocke le client Prisma
   - Mocke le contexte tRPC (utilisateur, session, permissions)
2. Structure de test :
   describe("{{module_name}} router", () => {
     describe("create", () => {
       it("devrait créer un élément avec une entrée valide", async () => { ... })
       it("devrait rejeter une entrée invalide", async () => { ... })
       it("devrait appliquer l'isolation par organizationId", async () => { ... })
     })
     describe("read/list", () => {
       it("devrait retourner les éléments filtrés par organizationId", async () => { ... })
       it("devrait paginer les résultats", async () => { ... })
     })
     describe("update", () => {
       it("devrait mettre à jour son propre élément", async () => { ... })
       it("devrait rejeter la mise à jour d'éléments d'une autre org (IDOR)", async () => { ... })
     })
     describe("delete", () => {
       it("devrait supprimer un élément avec la permission", async () => { ... })
       it("devrait rejeter la suppression sans permission", async () => { ... })
     })
   })
3. Cas de test de sécurité :
   - IDOR : essaie de lire/éditer/supprimer un élément d'une autre organisation → attends NOT_FOUND
   - Permissions : essaie une procédure sans la permission requise → attends FORBIDDEN
   - RBAC : des rôles différents doivent avoir des accès différents
   - Validation d'entrée : entrée Zod invalide → attends BAD_REQUEST
4. Patterns de mock :
   - vi.mock("~/server/db") pour Prisma
   - Helper createMockContext() pour le contexte tRPC
   - Utilise faker.js pour les données fictives
5. Mock de la base de données :
   - N'utilise jamais de vraie base de données dans les tests
   - Mocke les méthodes Prisma avec vi.spyOn()
   - Retourne des données fictives depuis les spies
6. Lance les tests :
   - pnpm test -- {{module_name}}
   - Vérifie la couverture : pnpm test -- --coverage
7. E2E (optionnel) :
   - Crée e2e/{{module_name}}.spec.ts avec Playwright
   - Teste le flux utilisateur complet (formulaire de création → soumission → vérification dans la liste)

Référence : @src/server/api/routers/__tests__/ pour les patterns de test existants.

Fichiers de contexte : @src/server/api/routers/__tests__/ @./.claude/rules/testing.md

Résultat attendu : une couverture de test supérieure à 80 %, avec des tests unitaires, de sécurité et E2E.

Vérifier que ça marche :

pnpm test -- {{module_name}}
# Tous les tests passent
# Le rapport de couverture affiche > 80 %
pnpm test:security
# Les tests de sécurité passent (IDOR, vérifications de permission)

17. Déboguer une erreur tRPC (guide de diagnostic)

Prompt :

J'ai une erreur avec la procédure tRPC {{procedure_name}}.

Détails de l'erreur :
- Message d'erreur : {{error_message}}
- Procédure : {{procedure_path}} (ex : "api.invoices.list")
- Contexte : {{context}} (ce qui déclenche l'erreur)
- Stack trace : {{stack_trace}} (si disponible)

Étapes de diagnostic :
1. Vérifie que la procédure tRPC existe :
   - Vérifie que src/server/api/routers/{{router}}.ts a bien export const {{procName}}
   - Vérifie qu'elle est enregistrée dans src/server/api/root.ts : {{routerName}}: {{routerName}}Router
   - Redémarre le serveur de dev si la procédure vient d'être ajoutée
2. Vérifie la validation d'entrée :
   - Vérifie que le schéma Zod correspond à l'entrée attendue
   - Utilise Zod .parse() dans les tests pour déboguer les erreurs de validation
   - Vérifie que le frontend envoie le bon format d'entrée (console.log côté client)
3. Vérifie le contexte et les permissions :
   - Si l'erreur est UNAUTHORIZED → vérifie que l'utilisateur est connecté (vérifie la session NextAuth)
   - Si l'erreur est FORBIDDEN → vérifie que l'utilisateur a la permission (vérifie la matrice RBAC)
   - Si l'erreur est NOT_FOUND → vérifie que le filtrage par organizationId est correct
4. Vérifie les requêtes de base de données :
   - Ajoute console.log(input) dans la procédure pour déboguer
   - Vérifie que la requête Prisma est correcte (vérifie prisma/schema.prisma)
   - Si multi-tenant : vérifie organizationId dans la clause WHERE
   - Utilise findFirst (jamais findUnique pour les ressources scopées par organisation)
5. Vérifie le format de réponse d'erreur :
   - Les erreurs tRPC doivent être des TRPCError (pas des Error)
   - Codes d'erreur : "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "BAD_REQUEST" | etc.
   - N'expose pas de données sensibles dans les messages d'erreur
6. Vérifie la gestion d'erreur côté frontend :
   - Vérifie que la mutation/requête a bien .useQuery()/.useMutation()
   - Vérifie l'objet d'erreur : error.data.code et error.data.message
   - Journalise l'erreur dans la console du navigateur pour plus de détails
7. Vérifie les logs :
   - Lance pnpm dev → vérifie le terminal pour les logs côté serveur
   - Vérifie la console du navigateur (F12) pour les erreurs côté client
   - Ajoute console.log() à chaque étape pour tracer l'exécution
8. Redémarre et reconstruis :
   - Arrête le serveur de dev
   - Supprime .next et generated/prisma/
   - Lance pnpm install
   - Lance pnpm prisma generate
   - Lance pnpm dev

Si ça bloque encore :
- Partage la stack trace complète
- Partage le code d'erreur tRPC (UNAUTHORIZED, FORBIDDEN, etc.)
- Partage le code de la procédure (masque les secrets)
- Partage le code frontend qui appelle la procédure

Fichiers de contexte : @src/server/api/routers/ (le router concerné) @src/server/api/trpc.ts @src/lib/permissions/matrix.ts

Résultat attendu : l'erreur diagnostiquée et corrigée, avec la cause racine identifiée.

Vérifier que ça marche :

pnpm dev
# Redéclenche la procédure
# Vérifie qu'elle réussit sans erreur
# Vérifie que les logs navigateur/serveur sont propres
# Si ça persiste, vérifie le code d'erreur et retrace depuis l'étape correspondante

💡 Astuces

  • Référence toujours @CLAUDE.md en début de session — il contient les conventions exactes de ton projet
  • Utilise @src/lib/permissions/matrix.ts quand tu travailles sur l'auth/la sécurité — c'est la source de vérité
  • Utilise @src/modules/_template/ comme point de départ pour tout nouveau module — fait gagner 30 minutes
  • Lance pnpm typecheck après chaque changement généré par l'IA — attrape les erreurs de type tôt
  • Garde des commits atomiques : une fonctionnalité = un commit — rend l'historique git propre et lisible
  • En cas de doute sur l'isolation multi-tenant, ajoute organizationId à la clause WHERE — mieux vaut prévenir
  • Teste les vulnérabilités IDOR en essayant d'accéder/d'éditer des ressources d'une autre organisation — sécurité critique
  • Utilise le système de quota freemium avant d'appeler des API coûteuses — évite les dérapages de coûts
  • Le mode sombre est obligatoire — utilise les tokens CSS, jamais de couleurs codées en dur
  • Utilise ctx.orgDb pour les lectures (filtre automatiquement organizationId), mais ajoute organizationId manuellement pour les écritures

🎯 Checklist de workflow

Après avoir collé un prompt et que l'IA a généré du code :

  1. Typecheck : pnpm typecheck — doit passer
  2. Tests : pnpm test — aucun nouvel échec
  3. Lint : pnpm lint:fix && pnpm format:write
  4. Commit : ajoute les fichiers modifiés un par un (git add <fichier>, jamais git add -A en une seule fois — ça capte aussi le travail d'une éventuelle autre session en cours sur le même dépôt), puis git commit -m "type: message"
  5. Dev : pnpm dev → vérifie que la fonctionnalité marche dans le navigateur

Si le schéma Prisma a été modifié :

  • npx prisma generate → npx prisma migrate dev --name <descriptif>

Voilà. Tu peux livrer.


Bonne chance, vibecoder. Livre vite, ne casse rien. 🚀