Skip to content

feat(candidatures): éditeur de CV in-app, suivi, design par-CV & compétences clés - #22

Merged
Tbeaumont79 merged 1 commit into
mainfrom
feat/cv-editor-candidatures
Jun 21, 2026
Merged

Tbeaumont79 merged 1 commit into
mainfrom
feat/cv-editor-candidatures

Conversation

@Tbeaumont79

@Tbeaumont79 Tbeaumont79 commented Jun 21, 2026 •

Copy link
Copy Markdown
Owner

Parcours

Import/profil → offre → score de match → génération → édition → export, avec persistance des candidatures (plus de perte au changement d'onglet) et suivi.

Highlights

  • Persistance & suivi : modèle Candidature (statuts brouillon→postulé→entretien→refusé/accepté), endpoints list/detail/patch/delete, page /candidatures. La génération persiste le CV et redirige vers l'éditeur.
  • Éditeur in-app (/candidatures/:id) : édition de contenu provenance-safe (sections, textes, ordre, ajout/suppression), aperçu live débouncé, sauvegarde, statut, export PDF, suppression. Panneau Apparence : disposition, couleurs, police, tokens photo (position, taille en px, marge, padding, rayon sidebar) + recadrage interactif (déplacer/zoomer).
  • Compétences clés = phrases verbe d'action, stockées au profil, extraites du CV importé, injectées au-dessus des expériences et adaptées à l'offre sans rien inventer (repli verbatim).
  • Profil : identité complète, langues, formations, « CV de base » (design + contenu) extrait d'un PDF ; import dédupliqué (plus de doublons au ré-import).
  • Rendu : gabarit maîtrisé + tokens, export forcé sur 1 page (cut), élagage des sections vides, bornage des tokens côté serveur.

Migrations

5 migrations Prisma additives (identity, languages, base_cv_design, candidatures, key_skills).

Vérification

  • npx vitest run : 118 (app) + 6 (shared) verts.
  • npx nuxt typecheck : clean.
  • Rendus PDF de contrôle relus (1 page, photo, sidebar, compétences clés).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added candidature management system to save, track, and edit job applications
    • Introduced CV design customization with layout, color, font, and photo placement options
    • Profile enhancements: language proficiency levels, education entries, and key skills
    • PDF CV import with automatic profile data extraction
    • CV editor with real-time preview and export capabilities
  • Chores

    • Removed design system demo page

…étences clés

Parcours complet : import/profil → offre → match → génération → édition → export,
avec persistance des candidatures (plus de perte au changement d'onglet).

Persistance & suivi
- Modèle Candidature (statuts brouillon→postulé→entretien→refusé/accepté),
  endpoints list/detail/patch/delete, page de suivi /candidatures.
- La génération persiste le CV et redirige vers l'éditeur.

Éditeur in-app (/candidatures/:id)
- Édition contenu (sections, textes, ordre, ajout/suppression) provenance-safe,
  aperçu live débouncé, sauvegarde, statut, export PDF, suppression.
- Apparence : disposition, couleurs, police, et tokens photo
  (position, taille en px, marge, padding, rayon sidebar).
- Recadrage interactif de la photo (déplacer + zoomer), sortie nette.

Compétences clés (phrases verbe d'action)
- Stockées au profil, extraites du CV importé, injectées au-dessus des
  expériences et ADAPTÉES à l'offre sans rien inventer (repli verbatim).

Profil
- Identité complète, langues, formations, « CV de base » (design + contenu)
  extrait d'un PDF ; import dédupliqué (plus de doublons au ré-import).

Rendu
- Gabarit maîtrisé + tokens (cv-html), export forcé sur 1 page (cut),
  élagage des sections vides, validation/bornage des tokens côté serveur.

Tests : 118 (app) + 6 (shared) ; typecheck clean. Page /ui supprimée.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@netlify

netlify Bot commented Jun 21, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for monumental-speculoos-a69398 ready!

Name Link
🔨 Latest commit 2a2eb5d
🔍 Latest deploy log https://app.netlify.com/projects/monumental-speculoos-a69398/deploys/6a3831efc00885000896f85d
😎 Deploy Preview https://deploy-preview-22--monumental-speculoos-a69398.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9e7a8d83-2510-4558-bda6-f3873255776c

📥 Commits

Reviewing files that changed from the base of the PR and between 9489c20 and 2a2eb5d.

📒 Files selected for processing (69)
  • .gitignore
  • apps/app/.env.example
  • apps/app/components/cv/CvDesignPanel.vue
  • apps/app/components/cv/CvPhotoInput.vue
  • apps/app/components/cv/CvTemplate.vue
  • apps/app/layouts/default.vue
  • apps/app/pages/candidature.vue
  • apps/app/pages/candidatures/[id].vue
  • apps/app/pages/candidatures/index.vue
  • apps/app/pages/profil.vue
  • apps/app/pages/ui.vue
  • apps/app/prisma/migrations/20260619075016_profile_identity/migration.sql
  • apps/app/prisma/migrations/20260619082630_profile_languages/migration.sql
  • apps/app/prisma/migrations/20260619083557_profile_base_cv_design/migration.sql
  • apps/app/prisma/migrations/20260619122800_candidatures/migration.sql
  • apps/app/prisma/migrations/20260619133422_profile_key_skills/migration.sql
  • apps/app/prisma/schema.prisma
  • apps/app/server/api/candidature/analyze.post.ts
  • apps/app/server/api/candidature/generate.post.ts
  • apps/app/server/api/candidatures/[id].delete.ts
  • apps/app/server/api/candidatures/[id].get.ts
  • apps/app/server/api/candidatures/[id].patch.ts
  • apps/app/server/api/candidatures/index.get.ts
  • apps/app/server/api/cv/export-pdf.post.ts
  • apps/app/server/api/cv/preview.post.ts
  • apps/app/server/api/profile/cv-design.delete.ts
  • apps/app/server/api/profile/cv-design.put.ts
  • apps/app/server/api/profile/cv-design/extract.post.ts
  • apps/app/server/api/profile/education.post.ts
  • apps/app/server/api/profile/education/[id].delete.ts
  • apps/app/server/api/profile/experiences.post.ts
  • apps/app/server/api/profile/index.get.ts
  • apps/app/server/api/profile/index.put.ts
  • apps/app/server/api/profile/languages.post.ts
  • apps/app/server/api/profile/languages/[id].delete.ts
  • apps/app/server/api/usage/current.get.ts
  • apps/app/server/services/cv-content-extract.ts
  • apps/app/server/services/cv-design-extract.ts
  • apps/app/server/services/keyskills-adapt.ts
  • apps/app/server/services/matching.ts
  • apps/app/server/utils/anthropic.ts
  • apps/app/server/utils/candidature-serialize.ts
  • apps/app/server/utils/cv-design-tokens.ts
  • apps/app/server/utils/cv-design.ts
  • apps/app/server/utils/cv-html.ts
  • apps/app/server/utils/cv-render-input.ts
  • apps/app/server/utils/pdf.ts
  • apps/app/server/utils/profile-serialize.ts
  • apps/app/test/candidature-serialize.spec.ts
  • apps/app/test/cv-content-extract.spec.ts
  • apps/app/test/cv-design-extract.spec.ts
  • apps/app/test/cv-design-tokens.spec.ts
  • apps/app/test/cv-html.spec.ts
  • apps/app/test/cv-render-input.spec.ts
  • apps/app/test/keyskills-adapt.spec.ts
  • apps/app/test/match-contracts.spec.ts
  • apps/app/test/match-report.spec.ts
  • apps/app/test/matching.spec.ts
  • apps/app/test/photo-crop.spec.ts
  • apps/app/test/profile-serialize.spec.ts
  • apps/app/utils/photo-crop.ts
  • packages/shared/src/candidature.ts
  • packages/shared/src/cv.ts
  • packages/shared/src/fixtures/sample-cv.ts
  • packages/shared/src/index.ts
  • packages/shared/src/match.ts
  • packages/shared/src/offer.ts
  • packages/shared/src/profile.ts
  • packages/shared/src/provenance.ts

📝 Walkthrough

Walkthrough

This PR introduces full candidature lifecycle persistence (DB schema, CRUD API, list and editor pages), a CvDesign token system driving themed HTML/PDF rendering with sidebar layout, photo placement, and font support, expanded profile fields (identity, languages, education, key skills, base CV design via PDF extraction), LLM services for CV content/design extraction and key-skills adaptation, and a client-side photo crop component.

Changes

Candidature persistence, CV design system, and profile enrichment

Layer / File(s) Summary
Shared contracts: CV design, section kinds, profile, candidature DTOs, and DB schema
packages/shared/src/cv.ts, packages/shared/src/profile.ts, packages/shared/src/candidature.ts, packages/shared/src/match.ts, packages/shared/src/offer.ts, packages/shared/src/provenance.ts, packages/shared/src/index.ts, packages/shared/src/fixtures/sample-cv.ts, apps/app/prisma/schema.prisma, apps/app/prisma/migrations/*
Adds CvDesign/CvLayout, CvKeySkillEntry/CvLanguageEntry section variants, expanded ProfileDTO/ParsedCvProfile, and CandidatureStatus/CandidatureDTO/UpdateCandidatureRequest to the shared package. Prisma schema and five migrations add LanguageLevel enum, Language model, Candidature model, and new profile columns (fullName, email, phone, location, links, keySkills, baseCvDesign). ESM .js specifiers updated across shared re-exports.
CV design token normalization, HTML rendering, and PDF options
apps/app/server/utils/cv-design-tokens.ts, apps/app/server/utils/cv-design.ts, apps/app/server/utils/cv-html.ts, apps/app/server/utils/cv-render-input.ts, apps/app/server/utils/pdf.ts, apps/app/test/cv-design-tokens.spec.ts, apps/app/test/cv-html.spec.ts, apps/app/test/cv-render-input.spec.ts
normalizeDesign sanitizes all CvDesign fields (colors, fonts, numeric clamps, raster-only photo data-URLs). buildCvHtml gains a design parameter driving sidebar layout, photo placement, keyskills/languages section rendering, pruneSections, and Google Fonts injection. loadBaseCvDesign fetches the profile's stored design. parseRenderInput centralizes CV body validation and provenance checks. renderHtmlToPdf gains fullBleed margin option.
Anthropic multimodal, CV extraction services, key-skills adaptation, and matching updates
apps/app/server/utils/anthropic.ts, apps/app/server/services/cv-content-extract.ts, apps/app/server/services/cv-design-extract.ts, apps/app/server/services/keyskills-adapt.ts, apps/app/server/services/matching.ts, apps/app/test/cv-content-extract.spec.ts, apps/app/test/cv-design-extract.spec.ts, apps/app/test/keyskills-adapt.spec.ts, apps/app/test/match-*.spec.ts
LlmRequest.user extended to accept LlmContentBlock[] for PDF/image inputs; error logging improved. extractCvContent and extractCvDesign parse structured output from base64 PDFs. adaptKeySkills rewrites candidate phrases against an analyzed offer. matching.ts schema rebuilt with $defs/$ref provenance, language IDs included in allowed set, keySkills stripped from LLM payload, and capCvLength truncation added.
Profile API expansion: identity, languages, education, key skills, and base CV design
apps/app/server/api/profile/index.{get,put}.ts, apps/app/server/api/profile/languages*.ts, apps/app/server/api/profile/education*.ts, apps/app/server/api/profile/cv-design*.ts, apps/app/server/api/profile/cv-design/extract.post.ts, apps/app/server/utils/profile-serialize.ts, apps/app/test/profile-serialize.spec.ts
Profile GET/PUT accept and return all new identity/contact fields and languages. New endpoints: POST/DELETE /api/profile/languages, POST/DELETE /api/profile/education, PUT/DELETE /api/profile/cv-design, and POST /api/profile/cv-design/extract (multipart PDF → parallel extractCvDesign + extractCvContent + metering). profile-serialize adds LanguageRow, toLanguageDTO, and baseCvDesign normalization.
Candidature API CRUD, generate endpoint persistence, and usage quota bypass
apps/app/server/api/candidature/generate.post.ts, apps/app/server/api/candidatures/[id].{get,patch,delete}.ts, apps/app/server/api/candidatures/index.get.ts, apps/app/server/utils/candidature-serialize.ts, apps/app/server/api/usage/current.get.ts, apps/app/.env.example, apps/app/test/candidature-serialize.spec.ts
generate.post accepts {offer, match}, validates server-side fullName (409), overwrites CV header with account identity, adapts key skills, persists a Candidature row, and returns {cv, candidatureId}. Full CRUD routes added for /api/candidatures. toCandidatureListItemDTO/toCandidatureDTO serialize rows to DTOs. DISABLE_GENERATION_LIMIT env flag bypasses quota in both generate and usage endpoints.
CV preview and export-PDF endpoints with design theming
apps/app/server/api/cv/preview.post.ts, apps/app/server/api/cv/export-pdf.post.ts
New POST /api/cv/preview returns themed HTML using parseRenderInput + loadBaseCvDesign + buildCvHtml. POST /api/cv/export-pdf refactored to delegate validation to parseRenderInput, apply base design fallback, and enable fullBleed rendering when a design is present.
CV design panel, photo crop utility and component, CvTemplate section kinds
apps/app/utils/photo-crop.ts, apps/app/components/cv/CvDesignPanel.vue, apps/app/components/cv/CvPhotoInput.vue, apps/app/components/cv/CvTemplate.vue, apps/app/test/photo-crop.spec.ts
Pure photo-crop.ts geometry helpers (fitCropSide, coverCropSide, cropSideForZoom, clampCrop). CvPhotoInput.vue adds file upload, drag-to-move cropper, zoom, and iterative-quality JPEG encoding. CvDesignPanel.vue exposes all CvDesign token controls. CvTemplate.vue adds keyskills (bullet list) and languages (tag) rendering branches.
Candidature list/editor pages, profile page expansion, and navigation
apps/app/pages/candidatures/index.vue, apps/app/pages/candidatures/[id].vue, apps/app/pages/candidature.vue, apps/app/pages/profil.vue, apps/app/pages/ui.vue (removed), apps/app/layouts/default.vue, .gitignore
candidatures/index.vue lists candidatures with status badges. candidatures/[id].vue is a full editor with live debounced preview (iframe), per-section CRUD, save/export/delete actions. candidature.vue removes the done step and redirects to the editor on success. profil.vue gains languages, education, key skills, and a PDF-based "CV de base" import section with dedup-aware apply. "Mes candidatures" added to nav; /ui dev page removed.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant candidaturePage as candidature.vue
  participant GenerateAPI as POST /api/candidature/generate
  participant adaptKeySkills
  participant prismaDB as Prisma DB
  participant EditorPage as candidatures/[id].vue
  participant PreviewAPI as POST /api/cv/preview
  participant ExportAPI as POST /api/cv/export-pdf

  User->>candidaturePage: submit offer + match
  candidaturePage->>GenerateAPI: {offer, match}
  GenerateAPI->>prismaDB: fetch user name/email
  GenerateAPI->>adaptKeySkills: adapt keySkills to offer
  adaptKeySkills-->>GenerateAPI: adapted phrases[]
  GenerateAPI->>prismaDB: candidature.create(snapshot, cv, design)
  GenerateAPI-->>candidaturePage: {cv, candidatureId}
  candidaturePage->>EditorPage: navigate /candidatures/:id
  EditorPage->>prismaDB: GET /api/candidatures/:id
  EditorPage->>PreviewAPI: POST {cv, design} (debounced)
  PreviewAPI-->>EditorPage: themed HTML (srcdoc iframe)
  User->>EditorPage: export PDF
  EditorPage->>ExportAPI: POST {cv, design}
  ExportAPI-->>EditorPage: PDF blob download
Loading
sequenceDiagram
  participant User
  participant ProfilPage as profil.vue
  participant ExtractAPI as POST /api/profile/cv-design/extract
  participant anthropicComplete
  participant extractCvDesign
  participant extractCvContent
  participant DesignPutAPI as PUT /api/profile/cv-design
  participant prismaDB as Prisma DB

  User->>ProfilPage: upload PDF (CV de base)
  ProfilPage->>ExtractAPI: multipart PDF
  ExtractAPI->>anthropicComplete: PDF base64 (parallel)
  anthropicComplete-->>extractCvDesign: design tokens
  anthropicComplete-->>extractCvContent: ParsedCvProfile
  ExtractAPI-->>ProfilPage: {design, parsed}
  User->>ProfilPage: review & apply
  ProfilPage->>DesignPutAPI: PUT normalizeDesign(design)
  DesignPutAPI->>prismaDB: profile.baseCvDesign = design
  ProfilPage->>prismaDB: PATCH header fields (if empty)
  ProfilPage->>prismaDB: POST experiences/education/skills/languages (dedup)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • Tbeaumont79/cv-optimizer#17: Both PRs modify apps/app/layouts/default.vue navigation — PR #17 introduced the dev-only "Design system" link that this PR removes and replaces with "Mes candidatures".

Poem

🐇 Hop hop, the rabbit types away,
A candidature saved each day!
Design tokens, sidebar-left so neat,
PDF crops and key skills complete.
The LLM adapts with flair—
Now every CV's beyond compare! ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cv-editor-candidatures

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Tbeaumont79
Tbeaumont79 merged commit f94344c into main Jun 21, 2026
4 of 7 checks passed
@Tbeaumont79
Tbeaumont79 deleted the feat/cv-editor-candidatures branch July 2, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant