feat: ajouter le PROMPT.md — spécification complète du projet CVP
Définition de la vision, stack technique, architecture, conventions, fonctionnalités par phase et stratégie de fiabilité.
This commit is contained in:
@@ -0,0 +1,367 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user