CV Maker est une application web Next.js 14 permettant de créer, éditer et exporter des CVs professionnels. L'éditeur est temps-réel avec prévisualisation instantanée. L'IA locale (Ollama / phi3:mini) assiste la rédaction sans envoyer de données à l'extérieur.
/print/[id]. Mise en page A4 pixel-perfect.Chaque template est un composant React avec son propre rendu. Le choix du template est modifiable à tout moment depuis l'éditeur.
Mise en page traditionnelle, sobre et universelle. Idéal pour tous secteurs.
serif · gris foncéDesign épuré bleu. Accent sur la lisibilité et les titres de section.
sans-serif · bleuTypographie aérée, espaces généreux. Maximum de clarté.
sans-serif · neutre2 colonnes avec barre latérale sombre. Accents dorés.
serif · or · 2 colEn-tête coloré, tags de compétences, style dynamique.
sans-serif · violetInspiration terminal développeur, fond sombre, accents verts.
monospace · vert/workshop) permet de créer des variantes personnalisées basées sur les templates Élégant, Créatif ou Tech, avec choix libre des couleurs primaire/accent et de la police. Ces thèmes sont sauvegardés en base et disponibles dans l'éditeur.Chaque section peut être remplie indépendamment. Les entrées (expériences, formations, compétences…) sont réordonnables par glisser-déposer via react-sortablejs.
Infos personnelles — champs disponibles
| Champ | Type | Description |
|---|---|---|
firstName / lastName | Texte | Prénom et nom affichés en en-tête |
jobTitle | Texte | Titre du poste recherché ou actuel |
email / phone / address / city | Texte | Coordonnées de contact |
linkedin / website | URL | Liens professionnels optionnels |
summary | Textarea | Accroche / résumé du profil |
photoUrl | Image | Photo de profil (upload + recadrage) |
Niveaux de compétences / langues
| Type | Format | Valeurs |
|---|---|---|
| Compétence / Logiciel | Numérique 1-5 | Débutant → Expert (barre de progression) |
| Langue | Enum texte | Notions · Débutant · Intermédiaire · Avancé · Courant · Bilingue · Langue maternelle |
Inscription — /register
- Champs : nom, email, mot de passe (hashé bcrypt)
- Validation Zod côté serveur
- Après inscription → redirigé vers
/dashboard - Le premier compte créé peut être promu admin via
seed-admin.jsou directement en BDD
Connexion — /login
- Email + mot de passe → vérification bcrypt
- JWT signé (secret dans
JWT_SECRET) stocké en cookiehttpOnly - Durée du token : configurable (défaut 7 jours)
- Déconnexion :
POST /api/auth/logout→ suppression du cookie
Middleware Next.js — src/middleware.ts
- Intercepte toutes les requêtes vers les routes protégées
- Vérifie la présence et la validité du JWT dans le cookie
- Redirige vers
/loginsi non authentifié - Routes publiques :
/login,/register,/api/auth/* - Routes admin : vérification du flag
isAdmindans le JWT
Page principale après connexion. Affiche tous les CVs de l'utilisateur avec leurs métadonnées.
POST /api/cv et redirige vers l'éditeur./editor/[id]. Les modifications sont sauvegardées manuellement.GET /api/export/[id] → génère et télécharge le PDF.DELETE /api/cv/[id] (cascade sur les données du CV).L'éditeur est une interface split-screen : le formulaire à gauche, la prévisualisation à droite. Chaque modification se reflète instantanément dans la prévisualisation.
Navigation entre sections
Onglets latéraux pour basculer entre Infos perso, Expériences, Formation, Compétences, Langues, Logiciels, Loisirs.
Saisie des données
Formulaires validés par React Hook Form + Zod. Les entrées multiples (expériences, compétences…) s'ajoutent dynamiquement.
Choix du template
Sélecteur de template en haut de l'éditeur. Basculement instantané entre les 6 templates intégrés et les thèmes personnalisés.
Photo de profil
Upload via POST /api/upload-photo (max 5 Mo, JPEG/PNG). Outil de recadrage intégré (react-image-crop). Stockée dans /public/uploads.
Sauvegarde
Bouton "Enregistrer" → PUT /api/cv/[id]. Les données sont stockées en JSON dans la colonne data de la table CV.
react-sortablejs. L'ordre est persisté à la sauvegarde.L'IA fonctionne entièrement en local via Ollama (modèle phi3:mini). Elle assiste la rédaction des textes du CV depuis l'éditeur, ainsi que l'analyse de CVs externes au format PDF.
Actions disponibles dans l'éditeur
POST /api/ai. L'endpoint attend { action, text, context } et renvoie { result }. Le modèle est configurable via la variable d'env OLLAMA_MODEL (défaut : phi3:mini).ollama-init télécharge le modèle automatiquement. Si l'IA renvoie une erreur 503, c'est que le modèle est encore en cours de téléchargement — réessayer après quelques minutes.L'export PDF utilise Puppeteer (Chromium headless) pour rendre la page /print/[id] et l'exporter en PDF A4 haute fidélité. Ce qui s'affiche dans la prévisualisation est exactement ce qui sera dans le PDF.
Flux d'export
Requête GET /api/export/[id]
L'utilisateur clique "Télécharger PDF" → requête authentifiée envoyée au serveur.
Puppeteer lance le navigateur
Chromium headless démarre en interne et navigue vers http://localhost:3000/print/[id].
Rendu de la page /print/[id]
La page de print utilise un layout épuré (sans navigation) et affiche le CV dans son template avec toutes les données.
Génération du PDF A4
Puppeteer exporte en PDF format A4, marges zéro. Le buffer est renvoyé avec Content-Type: application/pdf.
GET /api/admin/export/[id], même s'il ne lui appartient pas.L'atelier permet de créer des variantes visuelles des templates Élégant, Créatif et Tech, avec un aperçu en temps réel.
CustomTemplate. Disponible dans le sélecteur de template de l'éditeur.Préréglages couleurs
| Nom | Couleur primaire | Couleur accent |
|---|---|---|
| Or | #1a1a2e | #b8860b |
| Violet | #7c3aed | #f59e0b |
| Vert | #0f172a | #22c55e |
| Rouge | #7f1d1d | #f97316 |
| Bleu | #1e3a8a | #38bdf8 |
| Rose | #4a044e | #f472b6 |
| Teal | #134e4a | #2dd4bf |
| Ardoise | #0f172a | #94a3b8 |
Permet d'uploader un CV PDF existant (pas forcément créé avec CV Maker) pour obtenir une analyse IA instantanée.
- Upload d'un fichier PDF (max 10 Mo)
- Extraction du texte via
pdf-parse(nécessite un PDF avec texte sélectionnable, pas scanné) - Analyse IA : score /10, 3 points forts, 3 axes d'amélioration, conseil clé
- L'action est journalisée (nom du fichier, nombre de pages, taille, caractères extraits)
Accessible uniquement aux utilisateurs avec isAdmin = true. 4 onglets disponibles.
Onglet Vue d'ensemble
- Nombre total d'utilisateurs inscrits
- Nombre total de CVs créés
- CVs créés ce mois-ci
- Répartition des CVs par template (Classique, Moderne, Minimaliste…)
Onglet Utilisateurs
- Liste de tous les comptes : nom, email, date d'inscription, nombre de CVs, statut admin
- Recherche en temps réel par nom ou email
- Affichage du badge admin pour les comptes privilégiés
Onglet CVs
- Liste de tous les CVs de tous les utilisateurs
- Recherche par titre, nom utilisateur ou email
- Template utilisé, dates de création et modification
- Bouton export PDF pour chaque CV via
GET /api/admin/export/[id]
Onglet Journaux
- Journal de toutes les actions enregistrées sur la plateforme
- Filtre par type d'action
- Chaque entrée : date/heure, utilisateur, action, IP, métadonnées JSON
httpOnly — inaccessible au JavaScript client. Signé avec JWT_SECRET (à changer en production).isAdmin pour /admin et /api/admin/*.userId. Un utilisateur ne peut jamais lire, modifier ou supprimer le CV d'un autre. Seul l'admin y a accès.CF-Connecting-IP → X-Forwarded-For → remoteAddress. Supporte Cloudflare.JWT_SECRET et ADMIN_PASSWORD dans le .env. Les valeurs par défaut du docker-compose.yml sont des placeholders non sécurisés.User
| Colonne | Type | Note |
|---|---|---|
| id | UUID PK | Identifiant unique (uuid v4) |
| STRING UNIQUE | Email de connexion | |
| password | STRING | Hash bcrypt |
| name | STRING | Nom affiché |
| isAdmin | BOOLEAN | true = accès admin. Défaut false |
| createdAt / updatedAt | DATETIME | Auto-géré par Prisma |
CV
| Colonne | Type | Note |
|---|---|---|
| id | UUID PK | |
| userId | UUID FK | Référence User.id — cascade on delete |
| title | STRING | Nom du CV. Défaut "Mon CV" |
| template | STRING | ID du template (ex: "classic", "custom-uuid"). Défaut "classic" |
| data | JSON | Objet CVData complet (toutes les sections) |
| createdAt / updatedAt | DATETIME |
CustomTemplate
| Colonne | Type | Note |
|---|---|---|
| id | UUID PK | |
| userId | UUID FK | Référence User.id — cascade on delete |
| name | STRING | Nom du thème personnalisé |
| base | STRING | Template de base (elegant, creative, tech) |
| primaryColor | STRING | Couleur primaire hex. Défaut #1a1a2e |
| accentColor | STRING | Couleur accent hex. Défaut #b8860b |
| fontFamily | STRING | Police CSS. Défaut "Georgia, serif" |
| createdAt / updatedAt | DATETIME |
Log
| Colonne | Type | Note |
|---|---|---|
| id | UUID PK | |
| userId | UUID NULL FK | NULL si action avant connexion |
| action | STRING | Ex: LOGIN, CV_CREATED, PDF_ANALYZED… |
| ip | STRING NULL | IP réelle du client |
| meta | JSON NULL | Données contextuelles (ex: nom du fichier, ID du CV…) |
| createdAt | DATETIME | Horodatage UTC auto |
/prisma/migrations/ et appliquées automatiquement au démarrage du conteneur via prisma migrate deploy dans entrypoint.sh.L'application tourne dans 4 conteneurs Docker orchestrés par Docker Compose avec démarrage automatique.
Conteneurs
| Conteneur | Image | Rôle |
|---|---|---|
cv-maker-app | Dockerfile (Next.js 14) | Application web — port 8083:3000 |
cv-maker-db | postgres:16-alpine | Base de données PostgreSQL |
cv-maker-ollama | ollama/ollama:latest | Serveur IA local (LLM) |
cv-maker-ollama-init | ollama/ollama:latest | Télécharge le modèle IA au 1er démarrage puis s'arrête |
Volumes Docker
| Volume | Contenu |
|---|---|
pgdata | Données PostgreSQL persistantes |
uploads | Photos de profil uploadées (/app/public/uploads) |
ollama_data | Modèles Ollama téléchargés (évite re-téléchargement) |
Variables d'environnement clés
| Variable | Défaut | Description |
|---|---|---|
JWT_SECRET | à définir | Secret de signature JWT — obligatoire en production |
ADMIN_EMAIL | [email protected] | Email du compte admin créé au premier démarrage |
ADMIN_PASSWORD | admin1234 | Mot de passe admin initial — à changer immédiatement |
OLLAMA_MODEL | phi3:mini | Modèle LLM à utiliser (ex: llama3, mistral) |
DATABASE_URL | PostgreSQL interne | URL de connexion Prisma |
Démarrage initial
Copier le .env
Copier .env.example → .env et renseigner JWT_SECRET, ADMIN_EMAIL, ADMIN_PASSWORD.
Lancer les conteneurs
docker compose up -d depuis /DATA/AppData/cv-maker/. PostgreSQL et Ollama passent par un healthcheck avant le démarrage de l'app.
Migrations automatiques
L'entrypoint.sh exécute prisma migrate deploy puis node seed-admin.js (crée le compte admin s'il n'existe pas).
Téléchargement du modèle IA
Le conteneur ollama-init télécharge phi3:mini (≈ 2 Go) une seule fois dans le volume ollama_data.
Accéder à l'application
Ouvrir http://<serveur>:8083 et se connecter avec les identifiants admin du .env.
seed-admin.js est idempotent : il ne crée le compte admin que s'il n'existe pas déjà. Il peut être relancé sans risque.Pages
| Page | URL | Accès |
|---|---|---|
| Landing | / | Public |
| Connexion | /login | Public |
| Inscription | /register | Public |
| Dashboard | /dashboard | Connecté |
| Éditeur | /editor/[id] | Connecté (propriétaire) |
| Impression / PDF | /print/[id] | Connecté (propriétaire) |
| Analyse PDF | /analyze | Connecté |
| Atelier de thèmes | /workshop | Connecté |
| Administration | /admin | Admin uniquement |
API — Authentification
| Méthode | Endpoint | Description |
|---|---|---|
| POST | /api/auth/login | Connexion → cookie JWT |
| POST | /api/auth/logout | Déconnexion → supprime le cookie |
| GET | /api/auth/me | Renvoie les infos de l'utilisateur connecté |
| POST | /api/auth/register | Inscription d'un nouveau compte |
API — CVs
| Méthode | Endpoint | Description |
|---|---|---|
| GET | /api/cv | Liste les CVs de l'utilisateur connecté |
| POST | /api/cv | Crée un nouveau CV vide |
| GET | /api/cv/[id] | Récupère un CV par ID |
| PUT | /api/cv/[id] | Met à jour les données d'un CV |
| DELETE | /api/cv/[id] | Supprime un CV |
API — Export PDF
| Méthode | Endpoint | Description |
|---|---|---|
| GET | /api/export/[id] | Exporte le CV en PDF (propriétaire uniquement) |
| GET | /api/admin/export/[id] | Export PDF admin (tout CV) — admin uniquement |
API — Templates personnalisés
| Méthode | Endpoint | Description |
|---|---|---|
| GET | /api/templates | Liste les thèmes personnalisés de l'utilisateur |
| POST | /api/templates | Crée un nouveau thème personnalisé |
| GET | /api/templates/[id] | Récupère un thème par ID |
| DELETE | /api/templates/[id] | Supprime un thème personnalisé |
API — IA & Médias
| Méthode | Endpoint | Description |
|---|---|---|
| POST | /api/ai | Actions IA : rephrase, dynamic, shorten, expand, generate_summary, analyze |
| POST | /api/analyze-pdf | Analyse d'un CV PDF uploadé via multipart/form-data |
| POST | /api/upload-photo | Upload photo de profil (JPEG/PNG, max 5 Mo) |