Files
cvp/PROMPT.md
T

368 lines
18 KiB
Markdown
Raw Normal View History

# CVP — CV Personnalisé
## Vision du projet
CVP est une application web locale de recherche d'emploi intelligente.
Elle agrège automatiquement les offres d'emploi depuis des APIs gratuites (France Travail, Adzuna), analyse la compatibilité entre le profil de l'utilisateur et chaque offre via un LLM local (Phi-3 mini sur Ollama), puis génère un CV adapté et optimisé pour chaque candidature. L'objectif est d'automatiser et personnaliser la démarche de candidature pour maximiser les chances de retour.
---
## Stack technique
| Couche | Technologie | Version | Confiance | Notes |
|--------|-------------|---------|-----------|-------|
| **Frontend** | Next.js (App Router) | 14.x | 🟢 Élevée | SSR, routing, API routes |
| **UI Framework** | React | 18.x | 🟢 Élevée | |
| **Styling** | Tailwind CSS | 3.x | 🟢 Élevée | Utility-first, dark mode natif |
| **Composants UI** | shadcn/ui | latest | 🟢 Élevée | Composants accessibles, personnalisables |
| **Backend API** | Python FastAPI | 0.110+ | 🟢 Élevée | Async, typage fort, docs auto |
| **ORM** | SQLAlchemy | 2.x | 🟢 Élevée | Async support |
| **Migrations** | Alembic | latest | 🟢 Élevée | |
| **Base de données** | PostgreSQL | 16.x | 🟢 Élevée | Full-text search pour les offres |
| **LLM local** | Ollama + Phi-3 mini (3.8B) | latest | 🟡 Moyen | Quantifié Q4, tourne sur RTX 1050 Ti 4 Go |
| **API Offres** | France Travail API | v2 | 🟢 Élevée | Gratuite, officielle, ~500k offres |
| **API Offres** | Adzuna API | v1 | 🟡 Moyen | Gratuite (limite quotidienne), multi-sources |
| **Génération PDF** | WeasyPrint | latest | 🟢 Élevée | HTML → PDF fidèle |
| **Génération DOCX** | python-docx | latest | 🟢 Élevée | |
| **i18n** | next-intl | latest | 🟢 Élevée | FR par défaut, extensible |
| **Scheduler** | APScheduler | 3.x | 🟢 Élevée | Cron jobs pour scraping quotidien |
| **Validation** | Pydantic | 2.x | 🟢 Élevée | Validation des données côté backend |
### Légende confiance
- 🟢 **Élevée** : je produis du code correct et idiomatique du premier coup
- 🟡 **Moyen** : fonctionnel mais peut nécessiter des ajustements, tester en conditions réelles
- 🔵 **Via Context7** : documentation à vérifier systématiquement avant implémentation
---
## Architecture
### Vue d'ensemble
```
┌─────────────────────────────────────────┐
│ Frontend (Next.js) │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Dashboard│ │ Offres │ │ CV Gen │ │
│ │ │ │ Explorer │ │ Builder │ │
│ └─────────┘ └──────────┘ └──────────┘ │
└──────────────────┬──────────────────────┘
│ REST API
┌──────────────────▼──────────────────────┐
│ Backend (FastAPI) │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Jobs │ │ Matching │ │ CV │ │
│ │ Fetcher │ │ Engine │ │ Generator│ │
│ └────┬────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ┌────▼────┐ ┌────▼─────┐ ┌───▼──────┐ │
│ │ France │ │ Ollama │ │WeasyPrint│ │
│ │ Travail │ │ Phi-3 │ │python-doc│ │
│ │ Adzuna │ │ mini │ │ │ │
│ └─────────┘ └──────────┘ └──────────┘ │
└──────────────────┬──────────────────────┘
┌────────▼────────┐
│ PostgreSQL │
└─────────────────┘
```
### Structure des dossiers
```
cvp/
├── frontend/ # Application Next.js
│ ├── src/
│ │ ├── app/ # App Router (pages, layouts)
│ │ │ ├── [locale]/ # Routes i18n
│ │ │ │ ├── dashboard/
│ │ │ │ ├── offres/
│ │ │ │ ├── profil/
│ │ │ │ ├── cv/
│ │ │ │ ├── candidatures/
│ │ │ │ └── parametres/
│ │ │ └── api/ # API routes Next.js (proxy si besoin)
│ │ ├── components/
│ │ │ ├── ui/ # Composants shadcn/ui
│ │ │ ├── layout/ # Header, Sidebar, Footer
│ │ │ ├── offres/ # Composants liés aux offres
│ │ │ ├── cv/ # Composants liés au CV
│ │ │ └── profil/ # Composants liés au profil
│ │ ├── lib/ # Utilitaires, API client, helpers
│ │ ├── hooks/ # Custom React hooks
│ │ ├── types/ # Types TypeScript partagés
│ │ ├── messages/ # Fichiers de traduction (fr.json, en.json)
│ │ └── styles/ # Styles globaux
│ ├── public/
│ ├── next.config.js
│ ├── tailwind.config.ts
│ ├── tsconfig.json
│ └── package.json
├── backend/ # Application FastAPI
│ ├── app/
│ │ ├── main.py # Point d'entrée FastAPI
│ │ ├── config.py # Configuration (env vars, settings)
│ │ ├── api/
│ │ │ ├── routes/ # Endpoints groupés par domaine
│ │ │ │ ├── offres.py
│ │ │ │ ├── profil.py
│ │ │ │ ├── cv.py
│ │ │ │ ├── candidatures.py
│ │ │ │ └── parametres.py
│ │ │ └── deps.py # Dépendances injectées (DB session, etc.)
│ │ ├── models/ # Modèles SQLAlchemy
│ │ │ ├── offre.py
│ │ │ ├── profil.py
│ │ │ ├── competence.py
│ │ │ ├── experience.py
│ │ │ ├── formation.py
│ │ │ ├── candidature.py
│ │ │ └── cv_genere.py
│ │ ├── schemas/ # Schémas Pydantic (request/response)
│ │ ├── services/ # Logique métier
│ │ │ ├── job_fetcher.py # Agrégation offres (France Travail + Adzuna)
│ │ │ ├── matching.py # Matching profil/offre via LLM
│ │ │ ├── cv_generator.py # Génération CV (PDF, DOCX, HTML)
│ │ │ ├── llm_client.py # Interface Ollama
│ │ │ └── scheduler.py # Tâches planifiées (APScheduler)
│ │ ├── templates/ # Templates HTML pour CV
│ │ │ └── cv_pro.html
│ │ └── db/
│ │ ├── database.py # Connexion PostgreSQL
│ │ └── migrations/ # Alembic
│ ├── tests/
│ ├── requirements.txt
│ └── pyproject.toml
├── docker-compose.yml # PostgreSQL + Ollama (optionnel)
├── .env.example
├── PROMPT.md # Ce fichier
└── CLAUDE.md # Directives Claude Code
```
---
## Conventions de codage
### TypeScript / Frontend
- **Langage** : TypeScript strict (`strict: true` dans tsconfig)
- **Nommage** :
- Composants : PascalCase (`OffreCard.tsx`)
- Hooks : camelCase préfixé `use` (`useOffres.ts`)
- Utilitaires : camelCase (`formatDate.ts`)
- Types/Interfaces : PascalCase, pas de préfixe `I` (`Offre`, pas `IOffre`)
- Constantes : UPPER_SNAKE_CASE
- **Composants** : fonctionnels uniquement, pas de classes
- **State management** : React hooks (`useState`, `useContext`) — pas de Redux
- **Imports** : alias `@/` pour `src/`
- **Fichiers** : un composant par fichier, co-localiser les types avec le composant s'ils sont spécifiques
### Python / Backend
- **Version** : Python 3.11+
- **Nommage** :
- Modules et variables : snake_case
- Classes : PascalCase
- Constantes : UPPER_SNAKE_CASE
- **Typage** : annotations de type sur toutes les fonctions publiques
- **Async** : utiliser `async def` pour tous les endpoints et les accès DB
- **Imports** : absolus depuis `app.` (`from app.services.matching import ...`)
- **Docstrings** : uniquement sur les fonctions publiques de services, format Google style
- **Pas de `print()`** : utiliser `logging` systématiquement
### Git
- **Commits** : Conventional Commits en français
- `feat: ajouter le matching LLM profil/offre`
- `fix: corriger l'export PDF des CV`
- `chore: mettre à jour les dépendances`
- **Branches** : `feature/nom-court`, `fix/description`, `chore/description`
- **Ne jamais ajouter de ligne `Co-Authored-By` dans les messages de commit**
- **Trunk-based** : branches courtes, merge fréquent vers `main`
---
## Outils et plugins Claude Code
### Superpowers
- **Brainstorming** : invoquer `/superpowers:brainstorming` avant toute nouvelle feature ou décision d'architecture
- **TDD** : invoquer `/superpowers:test-driven-development` pour chaque feature — écrire les tests avant l'implémentation
- **Debugging** : invoquer `/superpowers:systematic-debugging` face à tout bug ou comportement inattendu
- **Code Review** : invoquer `/superpowers:requesting-code-review` après chaque feature complétée
- **Vérification** : invoquer `/superpowers:verification-before-completion` avant de déclarer un travail terminé
- **Plans** : invoquer `/superpowers:writing-plans` pour toute tâche multi-étapes
### Context7
- **Quand utiliser** : TOUJOURS vérifier la documentation via Context7 avant d'implémenter une intégration avec :
- France Travail API
- Adzuna API
- Ollama API
- WeasyPrint
- python-docx
- next-intl
- shadcn/ui (si doute sur un composant)
- **Directive** : ne jamais deviner une API — vérifier la signature exacte via Context7
### Frontend Design
- Invoquer le skill `frontend-design` pour toute création de page ou composant UI
- Respecter la direction esthétique définie (moderne, coloré, light/dark toggle)
### Commit
- Utiliser `/commit` pour créer les commits
- Ne jamais ajouter `Co-Authored-By` dans les messages
---
## Fonctionnalités par phase
### Phase 1 — Fondations (MVP)
- [ ] **Profil utilisateur** : formulaire de saisie du profil
- Informations personnelles (nom, email, téléphone, localisation)
- Compétences techniques (nom, niveau : débutant/intermédiaire/expert)
- Soft skills
- Expériences professionnelles (poste, entreprise, dates, description)
- Formations (diplôme, établissement, année)
- Langues parlées (langue, niveau)
- [ ] **Intégration France Travail API** : recherche et import d'offres
- Configuration des critères de recherche (métier, localisation, type contrat, mots-clés)
- Stockage des offres en base avec déduplication
- Affichage liste + détail d'une offre
- [ ] **Intégration Adzuna API** : second source d'offres
- Même logique que France Travail, adaptée à leur API
- Déduplication cross-source
- [ ] **Scheduler quotidien** : récupération automatique des nouvelles offres
- [ ] **Base de données** : modèles, migrations, seed initial
### Phase 2 — Intelligence (Matching + Génération)
- [ ] **Intégration Ollama / Phi-3 mini** : client LLM local
- Vérification que Ollama est actif, fallback gracieux si non disponible
- Gestion du timeout (le LLM local peut être lent)
- [ ] **Matching profil/offre** : analyse de compatibilité
- Score global de matching (0-100%)
- Scores détaillés : compétences techniques, soft skills, expérience, formation
- Affichage visuel des scores sur chaque offre
- Tri et filtre des offres par score
- [ ] **Génération de CV** : création du CV adapté
- Mode réorganisation : réordonne les rubriques selon la pertinence pour l'offre
- Mode reformulation : le LLM reformule les descriptions pour coller au vocabulaire de l'offre
- Choix du mode par l'utilisateur avant génération
- Preview du CV dans le navigateur (HTML)
- Export PDF (WeasyPrint)
- Export DOCX (python-docx)
- Export HTML
- Un template professionnel unique
### Phase 3 — Suivi et Polish
- [ ] **Suivi des candidatures** : mini CRM
- Statuts : intéressé → postulé → entretien → accepté / refusé
- Date de candidature
- Notes libres par candidature
- Vue tableau / kanban des candidatures
- [ ] **Dashboard** : vue d'ensemble
- Nombre d'offres récupérées (aujourd'hui, cette semaine)
- Offres avec meilleur matching
- Statistiques candidatures (postulé, en attente, refusé)
- [ ] **i18n** : internationalisation
- Interface en français par défaut
- Anglais comme seconde langue
- Architecture extensible pour d'autres langues
- [ ] **Dark/Light mode** : toggle thème
### Phase 4 — Extensions futures
- [ ] Génération de lettres de motivation
- [ ] Multi-utilisateurs avec authentification
- [ ] Notifications (nouvelles offres matching > seuil)
- [ ] Historique des CV générés
- [ ] Import de CV existant (PDF parsing)
---
## Design & UX
### Direction esthétique
- **Style** : moderne et coloré, inspiré de Stripe / Raycast
- **Couleurs** : palette vibrante avec accents de couleur forts sur fond neutre
- Primaire : bleu-violet (#6366F1 — indigo)
- Secondaire : cyan (#06B6D4)
- Accent : orange (#F59E0B) pour les scores et indicateurs
- Succès : vert (#10B981)
- Danger : rouge (#EF4444)
- Fond light : blanc (#FFFFFF) avec gris très clair (#F8FAFC)
- Fond dark : gris foncé (#0F172A) avec gris moyen (#1E293B)
- **Typographie** : Inter (UI) + JetBrains Mono (code/données)
- **Coins arrondis** : `rounded-xl` par défaut
- **Ombres** : subtiles, style glassmorphism léger
- **Animations** : transitions douces (300ms), micro-interactions sur hover
- **Dark/Light mode** : toggle avec Tailwind `dark:` classes
### Principes UX
- Dashboard comme page d'accueil
- Navigation par sidebar (desktop) / bottom nav (mobile)
- Les scores de matching sont visuellement proéminents (barres de progression colorées)
- Le workflow principal est : voir offre → consulter matching → générer CV → postuler
- Feedback visuel immédiat sur toutes les actions (loading states, toasts)
---
## Règles impératives
1. **Ne jamais ajouter `Co-Authored-By` dans les messages de commit**
2. **Ne jamais hardcoder de clés API** — utiliser des variables d'environnement via `.env`
3. **Ne jamais commit le fichier `.env`** — uniquement `.env.example`
4. **Toujours vérifier via Context7** avant d'implémenter une intégration API externe
5. **Toujours utiliser les types** — pas de `any` en TypeScript, pas de `# type: ignore` en Python
6. **Toujours gérer les erreurs des APIs externes** — France Travail, Adzuna, Ollama peuvent être indisponibles
7. **Le LLM local est optionnel** — l'app doit fonctionner sans Ollama (mode dégradé : pas de matching IA, pas de reformulation)
8. **Mono-utilisateur** — pas d'auth pour le moment, mais ne pas coupler l'architecture à un seul utilisateur (prévoir l'extensibilité)
9. **Français par défaut** — toute l'interface, les messages d'erreur, et les labels en français
10. **Responsive** — l'app doit être utilisable sur mobile même si optimisée desktop
---
## Stratégie de fiabilité
### Technologies 🟡 (confiance moyenne)
#### Ollama + Phi-3 mini
- **Risque** : performances insuffisantes sur RTX 1050 Ti 4 Go, réponses lentes ou de mauvaise qualité en français
- **Vérification** : tester la vitesse d'inférence et la qualité des réponses en français dès le début du développement
- **Fallback** : si Phi-3 mini est insuffisant en français, tester Mistral 7B Q4_K_S (plus compacte) ou Gemma 2B
- **Mode dégradé** : si Ollama n'est pas disponible, l'app fonctionne sans matching IA — afficher un message clair à l'utilisateur
- **Timeout** : fixer un timeout de 30s sur les appels Ollama, avec message explicite si dépassé
#### Adzuna API
- **Risque** : limites de requêtes quotidiennes sur le tier gratuit, format de réponse qui change
- **Vérification** : consulter la documentation via Context7 avant implémentation
- **Fallback** : si Adzuna est down ou limite atteinte, continuer avec France Travail seul
- **Monitoring** : logger les erreurs API et les limites atteintes
### Comportement quand un pattern échoue
1. **Ne pas paniquer** — activer le skill `superpowers:systematic-debugging`
2. **Isoler le problème** — tester le composant défaillant en isolation
3. **Vérifier Context7** — la documentation a peut-être changé
4. **Chercher une alternative** — si un package ne fonctionne pas, chercher une alternative mature avant de bricoler
5. **Communiquer** — dire clairement ce qui ne fonctionne pas et pourquoi
### Vérification systématique
- Avant chaque commit : les tests passent, le linter est clean, l'app build
- Avant de déclarer une feature terminée : tester le workflow complet manuellement
- Avant d'intégrer une nouvelle API : lire la doc via Context7, tester un appel simple en isolation
- Avant de pousser du code LLM : vérifier la qualité des prompts avec au moins 3 exemples variés