<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luca BEROULE</title>
    <description>The latest articles on DEV Community by Luca BEROULE (@sh0ck3r).</description>
    <link>https://dev.to/sh0ck3r</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4181217%2Fd093b3f9-ef06-45eb-a8cb-ff9a354cba21.jpg</url>
      <title>DEV Community: Luca BEROULE</title>
      <link>https://dev.to/sh0ck3r</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sh0ck3r"/>
    <language>en</language>
    <item>
      <title>#HackAVP AVPRO : l'espace recruteur qui remplace la boîte mail par un swipe (et explique chaque score)</title>
      <dc:creator>Luca BEROULE</dc:creator>
      <pubDate>Tue, 20 Oct 2026 06:42:31 +0000</pubDate>
      <link>https://dev.to/sh0ck3r/hackavp-avpro-lespace-recruteur-qui-remplace-la-boite-mail-par-un-swipe-et-explique-chaque-10ph</link>
      <guid>https://dev.to/sh0ck3r/hackavp-avpro-lespace-recruteur-qui-remplace-la-boite-mail-par-un-swipe-et-explique-chaque-10ph</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Une candidature reçue n'est pas une candidature traitée.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Track :&lt;/strong&gt; onPrem&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notre contribution au &lt;strong&gt;#HackAVP&lt;/strong&gt;, le hackathon de l'OPT-NC, de Station N et de la commission Data &amp;amp; IA d'OPEN NC, réalisée dans le cours &lt;em&gt;Interopérabilité des SI&lt;/em&gt; du M2 MIAGE de l'IAE de Nouvelle-Calédonie. Dans &lt;strong&gt;JobMatch NC&lt;/strong&gt;, le projet de notre promo, nous nous occupons de la brique &lt;strong&gt;recruteur&lt;/strong&gt; (MS6).&lt;/p&gt;

&lt;p&gt;Côté candidat, Adopte un Job permet de swiper les vrais postes de l'OPT-NC et de comprendre pourquoi ils nous correspondent (&lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc"&gt;l'article de Bastian&lt;/a&gt;). Mais un swipe à droite, ça crée une candidature… et quelqu'un, de l'autre côté, doit la lire, la comprendre et y répondre.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc" class="crayons-story__hidden-navigation-link"&gt;#HackAVP Adopte un Job : swipe les postes de l'OPT-NC, vois pourquoi ils te correspondent&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/c2b" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4193513%2Fdf36c2ad-f955-491b-a1e1-2f51e47c6438.png" alt="c2b profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/c2b" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Bastian
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Bastian
                
                
              
              &lt;div id="story-author-preview-content-4876145" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/c2b" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4193513%2Fdf36c2ad-f955-491b-a1e1-2f51e47c6438.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Bastian&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc" id="article-link-4876145"&gt;
          #HackAVP Adopte un Job : swipe les postes de l'OPT-NC, vois pourquoi ils te correspondent
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hackavp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hackavp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hackathon"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hackathon&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opendata"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opendata&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;17&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            10 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;C'est ce qu'on a construit : &lt;strong&gt;AVPRO&lt;/strong&gt;, l'espace recruteur d'Adopte un Job.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;Code source&lt;/strong&gt; : &lt;a href="https://github.com/DamienJmt/avpro" rel="noopener noreferrer"&gt;github.com/DamienJmt/avpro&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎬 &lt;strong&gt;Démo vidéo&lt;/strong&gt; : 3 min 38 (plus bas)&lt;/li&gt;
&lt;li&gt;👥 &lt;strong&gt;Équipe&lt;/strong&gt; : Damien &amp;amp; Luca, module &lt;strong&gt;MS6 – AVPRO-NC&lt;/strong&gt; du #HackAVP&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Le contexte : recruter, c'est encore souvent laborieux
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu27fzdl0o48x78r5b8u9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu27fzdl0o48x78r5b8u9.png" alt="Le constat : boîte mail, pièces jointes, tableau Excel" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aujourd'hui, une candidature à un avis de vacance de poste (AVP), c'est très souvent :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📧 &lt;strong&gt;un mail&lt;/strong&gt;, parfois un « RE: RE: Candidature », parfois une relance ;&lt;/li&gt;
&lt;li&gt;📎 &lt;strong&gt;des pièces jointes&lt;/strong&gt; à ouvrir une par une : &lt;code&gt;CV_final_v3.pdf&lt;/code&gt;, &lt;code&gt;CV(1).docx&lt;/code&gt;, &lt;code&gt;scan_cv.jpg&lt;/code&gt;… ;&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;un tableau Excel&lt;/strong&gt; pour savoir qui a été vu, qui a été relancé, qui est un doublon ;&lt;/li&gt;
&lt;li&gt;⏳ et au bout, &lt;strong&gt;des candidats qui attendent des semaines&lt;/strong&gt; sans savoir où ils en sont.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le recruteur passe son temps à &lt;em&gt;trier&lt;/em&gt; au lieu d'&lt;em&gt;évaluer&lt;/em&gt;. Et le candidat, lui, n'a aucune visibilité.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 La réponse : AVPRO
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fij0kwho68ymgwvwshkh5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fij0kwho68ymgwvwshkh5.png" alt="AVPRO remplace tout ça par un seul outil" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AVPRO remplace tout ça par &lt;strong&gt;un seul outil&lt;/strong&gt; :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Avant&lt;/th&gt;
&lt;th&gt;Avec AVPRO&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;📥 Réception&lt;/td&gt;
&lt;td&gt;des mails éparpillés&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;toutes les candidatures au même endroit&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔍 Évaluation&lt;/td&gt;
&lt;td&gt;ouvrir chaque CV, comparer à la fiche de poste&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;un score de compatibilité expliqué&lt;/strong&gt;, compétence par compétence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✋ Décision&lt;/td&gt;
&lt;td&gt;un mail à rédiger&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;un geste&lt;/strong&gt; : à droite on présélectionne, à gauche on écarte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔔 Réponse&lt;/td&gt;
&lt;td&gt;des semaines d'attente&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;le candidat voit la décision aussitôt&lt;/strong&gt; dans son app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📅 Entretiens&lt;/td&gt;
&lt;td&gt;un fil de mails&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;suivis dans l'outil&lt;/strong&gt;, sans un seul mail&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;L'idée est volontairement symétrique à Adopte un Job : le candidat swipe des postes, &lt;strong&gt;le recruteur swipe des candidatures&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎬 La démo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/tjHP83BT0JM" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Les données de la démo (candidats, AVP, scores) sont fictives.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Notre place dans le projet commun du Master MIAGE
&lt;/h2&gt;

&lt;p&gt;Le #HackAVP s'inscrit dans &lt;strong&gt;JobMatch NC&lt;/strong&gt;, le projet commun de la promo :&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/maud_granger_nc/jobmatch-nc-quand-linteroperabilite-devient-plus-quun-defi-technique-1ma" class="crayons-story__hidden-navigation-link"&gt;#HackAVP JOBMATCH NC : quand l'interopérabilité devient plus qu'un défi technique&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/maud_granger_nc" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4195180%2Fdf339e0f-064d-44d9-b9b2-312cf52d6c74.jpg" alt="maud_granger_nc profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/maud_granger_nc" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Maud Granger
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Maud Granger
                
                
              
              &lt;div id="story-author-preview-content-4880801" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/maud_granger_nc" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4195180%2Fdf339e0f-064d-44d9-b9b2-312cf52d6c74.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Maud Granger&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/maud_granger_nc/jobmatch-nc-quand-linteroperabilite-devient-plus-quun-defi-technique-1ma" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/maud_granger_nc/jobmatch-nc-quand-linteroperabilite-devient-plus-quun-defi-technique-1ma" id="article-link-4880801"&gt;
          #HackAVP JOBMATCH NC : quand l'interopérabilité devient plus qu'un défi technique
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hackavp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hackavp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/interoperability"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;interoperability&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/api"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;api&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/projectmanagement"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;projectmanagement&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/maud_granger_nc/jobmatch-nc-quand-linteroperabilite-devient-plus-quun-defi-technique-1ma" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/maud_granger_nc/jobmatch-nc-quand-linteroperabilite-devient-plus-quun-defi-technique-1ma#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              2&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F59474p3punay2z8nramx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F59474p3punay2z8nramx.png" alt="La chaîne des 7 modules du #HackAVP" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le #HackAVP réunit &lt;strong&gt;sept groupes&lt;/strong&gt;, chacun sur un maillon de la chaîne :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;th&gt;Projet&lt;/th&gt;
&lt;th&gt;Équipe&lt;/th&gt;
&lt;th&gt;Article&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MS1&lt;/td&gt;
&lt;td&gt;CV Forge&lt;/td&gt;
&lt;td&gt;Florian&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/florian_doudoute/hackavp-cv-forge-lusine-a-cv-boostee-par-ia-locale-4a64"&gt;lire&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS2&lt;/td&gt;
&lt;td&gt;HACKAVPI&lt;/td&gt;
&lt;td&gt;Dan &amp;amp; Thimotée&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/pastek/hackavpi-dp8"&gt;lire&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS3&lt;/td&gt;
&lt;td&gt;Adopte un Job&lt;/td&gt;
&lt;td&gt;Bastian&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc"&gt;lire&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS4&lt;/td&gt;
&lt;td&gt;CV Generator&lt;/td&gt;
&lt;td&gt;Anthony &amp;amp; Kim&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/spewq/hackavp-cv-generator-la-solution-de-preparation-de-candidature-1p30"&gt;lire&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS5&lt;/td&gt;
&lt;td&gt;CV-Matching&lt;/td&gt;
&lt;td&gt;Jo-Michel&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/jocc0/cv-matching-le-bon-profil-preuves-a-lappui-hackavp-4oh8"&gt;lire&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MS6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AVPRO-NC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Damien &amp;amp; Luca&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;vous y êtes&lt;/em&gt; 👋&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS7&lt;/td&gt;
&lt;td&gt;Insight Squad&lt;/td&gt;
&lt;td&gt;Élodie &amp;amp; Matthieu&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dev.to/elodie_tran_data/et-si-les-donnees-du-recrutement-repondaient-a-nos-questions--1d5o"&gt;lire&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nous, c'est &lt;strong&gt;MS6, le côté recruteur&lt;/strong&gt;. AVPRO n'a ni base de données ni serveur à lui : il s'appuie sur trois autres modules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MS2 – HACKAVPI&lt;/strong&gt; : l'API commune (comptes, AVP, candidatures, profils, décisions, entretiens).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MS3 – Adopte un Job&lt;/strong&gt; : les candidats, leur CV au format &lt;strong&gt;JSON Resume&lt;/strong&gt; et les critères qu'ils ont saisis (métier visé, contrat, zone, disponibilité).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MS5 – CV-Matching&lt;/strong&gt; : le score de compatibilité entre un CV et un AVP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour tout savoir sur l'API commune, l'article de l'équipe HACKAVPI :&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/pastek/hackavpi-dp8" class="crayons-story__hidden-navigation-link"&gt;HACKAVPI : L'API au coeur du projet HackAVP&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/pastek" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4195037%2Fdb464d71-b159-4a74-84ce-ee9e2e3c7b0c.png" alt="pastek profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/pastek" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Thimotée
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Thimotée
                
                
              
              &lt;div id="story-author-preview-content-4880260" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/pastek" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4195037%2Fdb464d71-b159-4a74-84ce-ee9e2e3c7b0c.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Thimotée&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/pastek/hackavpi-dp8" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/pastek/hackavpi-dp8" id="article-link-4880260"&gt;
          HACKAVPI : L'API au coeur du projet HackAVP
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/api"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;api&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/backend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;backend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hackavp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hackavp&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/pastek/hackavpi-dp8" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/pastek/hackavpi-dp8#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              3&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Concrètement : un swipe à droite dans Adopte un Job crée une candidature dans HACKAVPI, AVPRO la récupère, demande son score à CV-Matching, et la décision du recruteur repart dans HACKAVPI, où le candidat la voit.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 Le parcours recruteur, étape par étape
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Je me connecte
&lt;/h3&gt;

&lt;p&gt;Un écran simple : adresse et mot de passe. Pas d'inscription libre, &lt;strong&gt;un compte recruteur ne peut être créé que par un recruteur ou un admin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;À la connexion, l'API renvoie un &lt;strong&gt;jeton JWT valable 1 h&lt;/strong&gt;. AVPRO lit le rôle dans le jeton : si c'est un compte candidat, il est poliment renvoyé vers Adopte un Job. Quand le jeton expire, on revient à la connexion, sans écran cassé.&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Je swipe les candidatures
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frfkyk4a63m0zqtnazq8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frfkyk4a63m0zqtnazq8s.png" alt="L'écran Swipe : la carte du candidat et le détail du score" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Une carte = une candidature à traiter.&lt;/strong&gt; On y voit d'un coup d'œil :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le &lt;strong&gt;score de compatibilité&lt;/strong&gt; (« 88 % · très bonne adéquation ») et le nombre de compétences du poste couvertes ;&lt;/li&gt;
&lt;li&gt;l'&lt;strong&gt;expérience&lt;/strong&gt;, le &lt;strong&gt;niveau de formation&lt;/strong&gt;, la &lt;strong&gt;disponibilité&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;des repères verts quand le candidat &lt;strong&gt;vise ce métier&lt;/strong&gt; ou &lt;strong&gt;cherche dans cette zone&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;ses &lt;strong&gt;compétences&lt;/strong&gt;, avec en vert celles que le matching a reconnues dans le poste.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;À droite pour &lt;strong&gt;présélectionner&lt;/strong&gt;, à gauche pour &lt;strong&gt;écarter&lt;/strong&gt; : à la souris, au doigt, ou avec les boutons sous la carte.&lt;/p&gt;

&lt;h3&gt;
  
  
  3️⃣ Je comprends le score
&lt;/h3&gt;

&lt;p&gt;À côté de la carte (ou dans une feuille sur téléphone), le panneau de détail répond à la vraie question : &lt;strong&gt;pourquoi ce score ?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Points forts&lt;/strong&gt; : chaque compétence attendue par l'AVP, avec &lt;strong&gt;la phrase du CV qui la prouve&lt;/strong&gt; (« Développement web React / TypeScript — &lt;em&gt;“Développeuse React et Node depuis 4 ans”&lt;/em&gt; »).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;À vérifier&lt;/strong&gt; : ce qui est seulement approchant (« Bases de données SQL — &lt;em&gt;au plus proche : “PostgreSQL”&lt;/em&gt; »).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Savoir-être, à vérifier en entretien&lt;/strong&gt; : ce qu'un CV ne peut pas prouver.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prérequis&lt;/strong&gt; : permis, diplôme… marqués &lt;em&gt;rempli&lt;/em&gt;, &lt;em&gt;non rempli&lt;/em&gt; ou &lt;em&gt;à vérifier&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Et à part, &lt;strong&gt;ce que le candidat recherche&lt;/strong&gt; : métier, contrat, lieu, disponibilité, affichés en &lt;em&gt;oui / non / inconnu&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Choix assumé : les critères du candidat ne font pas de score.&lt;/strong&gt; S'il ne vise pas ce contrat ou cette zone, la carte l'indique (« hors de ses critères ») mais le recruteur peut le retenir quand même. &lt;strong&gt;L'outil éclaire, le recruteur décide.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4️⃣ Je filtre
&lt;/h3&gt;

&lt;p&gt;Une recherche (nom, métier, intitulé de poste) et des filtres &lt;strong&gt;Poste · Direction · Lieu du poste · Options&lt;/strong&gt; (&lt;em&gt;profil renseigné&lt;/em&gt;, &lt;em&gt;CV déposé&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Plusieurs choix dans une même catégorie, c'est l'un &lt;strong&gt;ou&lt;/strong&gt; l'autre ; d'une catégorie à l'autre, c'est les deux. Et &lt;strong&gt;chaque case annonce combien de candidats elle garderait&lt;/strong&gt; avant même qu'on la coche : plus de filtre qui vide l'écran par surprise.&lt;/p&gt;

&lt;h3&gt;
  
  
  5️⃣ Je décide… et j'ai 30 secondes pour changer d'avis
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fta4for4l4ll9ec739ozy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fta4for4l4ll9ec739ozy.png" alt="La barre d'envoi différé : « envoi dans 28 s »" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dans l'API, une décision est &lt;strong&gt;définitive&lt;/strong&gt; et &lt;strong&gt;le candidat la voit immédiatement&lt;/strong&gt;. Un swipe trop rapide ne doit pas devenir un refus envoyé à quelqu'un.&lt;/p&gt;

&lt;p&gt;Alors &lt;strong&gt;une décision ne part qu'après 30 secondes&lt;/strong&gt;. Pendant ce délai, une barre en bas de l'écran affiche « envoi dans 28 s » avec &lt;strong&gt;Annuler&lt;/strong&gt; et &lt;strong&gt;Envoyer maintenant&lt;/strong&gt; ; le bouton &lt;strong&gt;Retour&lt;/strong&gt; du swipe et l'onglet Candidats permettent aussi d'annuler. Et si on ferme la page, les décisions en attente partent quand même.&lt;/p&gt;

&lt;h3&gt;
  
  
  6️⃣ Je suis mes candidatures
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd9b4z3u081q7ug1m190x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd9b4z3u081q7ug1m190x.png" alt="L'onglet Candidats" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L'onglet &lt;strong&gt;Candidats&lt;/strong&gt; reprend tout, par statut : &lt;strong&gt;À traiter&lt;/strong&gt;, &lt;strong&gt;Présélectionné&lt;/strong&gt;, &lt;strong&gt;Toutes&lt;/strong&gt;. Chaque ligne garde sa case de compatibilité, et une candidature retirée par le candidat apparaît grisée.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Statut dans l'API&lt;/th&gt;
&lt;th&gt;Dans AVPRO&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EN_ATTENTE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;À traiter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VALIDEE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Présélectionné&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REJETEE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rejetée&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ANNULEE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retirée par le candidat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;VALIDEE&lt;/code&gt; + &lt;code&gt;entretienAProg&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Entretien&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  7️⃣ Je valide un entretien
&lt;/h3&gt;

&lt;p&gt;Un profil présélectionné peut passer &lt;strong&gt;en entretien&lt;/strong&gt;, après une confirmation. Il rejoint l'onglet &lt;strong&gt;Entretiens&lt;/strong&gt;, avec un récapitulatif du &lt;strong&gt;poste&lt;/strong&gt; (intitulé, référence, direction, lieu, contrat, début, date limite) et de la &lt;strong&gt;candidature&lt;/strong&gt; (profil, contact, expérience, formation, disponibilité, compatibilité).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Choix de périmètre : AVPRO marque l'entretien &lt;strong&gt;à programmer&lt;/strong&gt;, il ne gère pas l'agenda. La date et le lieu restent l'affaire du recruteur.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  8️⃣ Et aussi
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AVP&lt;/strong&gt; : les avis de vacance de poste, les ouverts d'abord, triés par date limite, avec le nombre de candidatures à traiter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Profil&lt;/strong&gt; : l'adresse du compte et le changement de mot de passe par un code reçu par mail.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📱 Responsive : ordinateur et téléphone
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01fj6ou4emz8l1kziwc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F01fj6ou4emz8l1kziwc3.png" alt="AVPRO sur ordinateur et sur téléphone" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un recruteur ne trie pas toujours à son bureau. Sur &lt;strong&gt;grand écran&lt;/strong&gt;, AVPRO affiche un menu latéral et le détail du score en panneau à côté de la carte. Sur &lt;strong&gt;téléphone&lt;/strong&gt;, les onglets passent &lt;strong&gt;en bas de l'écran&lt;/strong&gt;, et le détail s'ouvre &lt;strong&gt;d'un geste&lt;/strong&gt;, en feuille, depuis le score de la carte.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛤️ Track choisie : onPrem
&lt;/h2&gt;

&lt;p&gt;AVPRO est un front &lt;strong&gt;100 % statique&lt;/strong&gt; : pas de base de données, pas de serveur à nous. Le dossier produit par &lt;code&gt;vite build&lt;/code&gt; se dépose sur n'importe quel serveur web, y compris &lt;strong&gt;les serveurs de l'OPT-NC&lt;/strong&gt;, sans cloud tiers.&lt;/p&gt;

&lt;p&gt;Les données ne quittent pas la chaîne du projet : elles restent dans l'API commune (MS2), et le CV n'est envoyé au matching (MS5) &lt;strong&gt;que sans identité&lt;/strong&gt;. La seule clé sensible, celle du matching, reste côté serveur et n'est jamais livrée au navigateur.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Sous le capot (pour les devs)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzlj2lnxys7phkz3xfowu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzlj2lnxys7phkz3xfowu.png" alt="L'architecture du front" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  La stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React 19&lt;/strong&gt; + &lt;strong&gt;TypeScript strict&lt;/strong&gt; + &lt;strong&gt;Vite 7&lt;/strong&gt;, sortie &lt;strong&gt;100 % statique&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Même socle et même design que l'app candidat&lt;/strong&gt; : les CSS d'Adopte un Job sont repris tels quels, pour une fusion simple dans &lt;code&gt;beta/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pas de base, pas de serveur à nous&lt;/strong&gt; : tout passe par l'API commune (MS2) et par CV-Matching (MS5).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Un seul fichier parle à l'API
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqi9dgo1q2m21n2f9kg87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqi9dgo1q2m21n2f9kg87.png" alt="Les routes utilisées, écran par écran" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/api.ts&lt;/code&gt; est &lt;strong&gt;le seul fichier&lt;/strong&gt; qui appelle HACKAVPI. Il traduit leurs réponses dans les formes de &lt;code&gt;src/types.ts&lt;/code&gt; (&lt;code&gt;Avp&lt;/code&gt;, &lt;code&gt;Candidat&lt;/code&gt;, &lt;code&gt;Candidature&lt;/code&gt;) : les écrans ne connaissent jamais le format de l'API. Quand l'API change, un seul fichier s'adapte.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Écran&lt;/th&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Connexion&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /auth/login&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET /avp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swipe, Candidats&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;GET /candidatures&lt;/code&gt; · &lt;code&gt;GET /profils&lt;/code&gt; · &lt;code&gt;GET /profils/{id}/cv&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Décision&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;POST /swipes/recruteurs/candidature/{id}&lt;/code&gt; &lt;code&gt;{ estLike }&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entretien&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;PATCH /candidatures/{id}/entretien-a-prog&lt;/code&gt; &lt;code&gt;{ entretienAProg }&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compatibilité&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;POST /v1/score&lt;/code&gt; &lt;code&gt;{ reference, cv }&lt;/code&gt; (CV-Matching)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Profil&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;POST /auth/forgot-password&lt;/code&gt; · &lt;code&gt;POST /auth/reset-password&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Les trois listes (AVP, candidatures, profils) sont chargées &lt;strong&gt;en parallèle, toutes pages lues&lt;/strong&gt; (100 par page), au démarrage et à chaque « Actualiser ».&lt;/p&gt;

&lt;h3&gt;
  
  
  Les données : plusieurs formats de CV, une seule forme
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg9xt3u8052nmfk7f5yrb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg9xt3u8052nmfk7f5yrb.png" alt="Le CV au format JSON Resume" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dans l'API, plusieurs formats de CV circulent :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le &lt;strong&gt;JSON Resume&lt;/strong&gt; écrit par l'app candidat, avec les critères dans &lt;code&gt;meta.criteres&lt;/code&gt; ;&lt;/li&gt;
&lt;li&gt;le JSON Resume produit par la &lt;strong&gt;lecture du CV déposé&lt;/strong&gt; (&lt;code&gt;cvJsonGenere&lt;/code&gt;) ;&lt;/li&gt;
&lt;li&gt;les &lt;strong&gt;formats courts&lt;/strong&gt; des comptes de démonstration (&lt;code&gt;titre&lt;/code&gt;, &lt;code&gt;competences: string[]&lt;/code&gt;, &lt;code&gt;experiences: {poste, annees}[]&lt;/code&gt;…).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;api.ts&lt;/code&gt; les ramène tous à &lt;strong&gt;une seule forme &lt;code&gt;Candidat&lt;/code&gt;&lt;/strong&gt; : années d'expérience cumulées, niveau de formation (Bac → Bac+5), compétences dédoublonnées, critères. Les zones sont recalculées comme dans l'app candidat (&lt;strong&gt;Grand Nouméa, Sud, Nord, Îles&lt;/strong&gt;) pour comparer un AVP aux zones visées.&lt;/p&gt;

&lt;h3&gt;
  
  
  La décision différée
&lt;/h3&gt;

&lt;p&gt;Le cœur du « droit à l'erreur » tient en quelques lignes dans &lt;code&gt;App.tsx&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Une décision du recruteur est définitive dans l'API et le candidat la voit
   aussitôt : elle n'est envoyée qu'après ce délai, annulable jusque-là. */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DELAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;avant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;minuteurs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;avant&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;avant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;maj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preselectionne&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rejete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// l'écran change tout de suite&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;envoie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;DELAI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;minuteurs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;setAttente&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;echeance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;DELAI&lt;/span&gt; &lt;span class="p"&gt;}]);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et pour ne rien perdre à la fermeture de l'onglet, les décisions en attente partent sur &lt;code&gt;pagehide&lt;/code&gt; avec un &lt;code&gt;fetch(..., { keepalive: true })&lt;/code&gt;, que le navigateur termine seul.&lt;/p&gt;

&lt;h3&gt;
  
  
  Le matching, à la demande
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;src/matching.ts&lt;/code&gt; appelle CV-Matching &lt;strong&gt;uniquement quand un écran affiche un score&lt;/strong&gt;, &lt;strong&gt;trois appels à la fois au plus&lt;/strong&gt;, et garde les résultats pour la session (un candidat ne change pas de CV pendant qu'on le regarde). Les composants s'abonnent au cache avec &lt;code&gt;useSyncExternalStore&lt;/code&gt; ; « Actualiser » le vide.&lt;/p&gt;

&lt;h3&gt;
  
  
  CORS et clé d'API
&lt;/h3&gt;

&lt;p&gt;Le serveur commun n'envoie pas d'en-têtes CORS, et CV-Matching exige une clé &lt;code&gt;X-API-Key&lt;/code&gt;. En développement, &lt;strong&gt;le proxy Vite règle les deux&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vite.config.ts&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api-matching&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MATCHING_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://myz0-cv-matching.hf.space&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;changeOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;rewrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;api-matching/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="c1"&gt;// MATCHING_API_KEY vient de .env.local, sans préfixe VITE_ :&lt;/span&gt;
  &lt;span class="c1"&gt;// elle reste côté serveur et n'est jamais dans le code envoyé au navigateur.&lt;/span&gt;
  &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MATCHING_API_KEY&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-API-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MATCHING_API_KEY&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En production, il faudra un relais du même genre (comme le &lt;code&gt;relais.php&lt;/code&gt; d'Adopte un Job), déclaré dans &lt;code&gt;VITE_API_URL&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Données personnelles
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fla1uv7n8dmdiici8alor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fla1uv7n8dmdiici8alor.png" alt="Le CV part sans identité vers CV-Matching" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Le CV envoyé à CV-Matching part sans identité&lt;/strong&gt; : ni nom, ni adresse, ni téléphone, ni profils en ligne. Le service n'en a pas besoin, elles n'ont pas à quitter l'API commune. On retire même le nom quand il apparaît dans le résumé (« Léa Wamytan, 3 ans d'expérience… »).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// api.ts — extrait de cvPourMatching()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;$schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;references&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_refs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;reste&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;reste&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;basics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sansNom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="c1"&gt;// le nom du candidat est retiré du résumé&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;objet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;objet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;La clé du matching n'est jamais dans le navigateur&lt;/strong&gt; (voir le proxy plus haut).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seule la session vit dans le navigateur&lt;/strong&gt; : le jeton, en &lt;code&gt;sessionStorage&lt;/code&gt;, effacé à la fermeture de l'onglet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Les données de la démo sont fictives.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚖️ Nos arbitrages
&lt;/h2&gt;

&lt;p&gt;Quelques décisions qu'on a dû trancher, et pourquoi :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Un score qui s'explique, plutôt qu'un classement opaque.&lt;/strong&gt; Un pourcentage seul ne dit rien ; les preuves tirées du CV, si.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Les critères du candidat informent, ils ne filtrent pas.&lt;/strong&gt; Exclure automatiquement quelqu'un parce qu'il a coché « CDI » sur un CDD, c'est passer à côté de profils.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;30 secondes de délai plutôt qu'une confirmation à chaque swipe.&lt;/strong&gt; Une popup « Êtes-vous sûr ? » casse le rythme du tri ; un délai annulable protège sans gêner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pas d'agenda d'entretien.&lt;/strong&gt; On marque l'entretien à programmer, on ne réinvente pas le calendrier du recruteur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aucune base à nous.&lt;/strong&gt; Une seule source de vérité, l'API commune : ce que voit le recruteur est exactement ce que voit le candidat.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Et ensuite ?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fusionner AVPRO dans l'app Adopte un Job&lt;/strong&gt; (&lt;code&gt;beta/&lt;/code&gt;) : même socle, mêmes CSS, il reste à importer les styles communs et à ajouter quelques icônes au sprite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Un relais de production&lt;/strong&gt; pour le CORS et la clé du matching, comme côté candidat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Le renouvellement de session&lt;/strong&gt; : le jeton dure 1 h sans renouvellement aujourd'hui.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Le changement d'adresse du compte&lt;/strong&gt;, que l'API ne permet pas encore.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 Pour finir
&lt;/h2&gt;

&lt;p&gt;Adopte un Job aide le candidat à trouver &lt;strong&gt;le&lt;/strong&gt; poste qui lui correspond. AVPRO aide le recruteur à trouver &lt;strong&gt;les&lt;/strong&gt; candidats qui correspondent à son poste, et à leur répondre vite.&lt;/p&gt;

&lt;p&gt;Fini la boîte mail qui déborde : chaque candidature arrive au même endroit, avec un score qui s'explique, une décision en un geste et un candidat qui sait où il en est.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Et vous, côté recruteur ou côté candidat : qu'est-ce qui vous a le plus fait perdre de temps dans un recrutement ?&lt;/strong&gt; Dites-le-nous en commentaire 👇&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Damien &amp;amp; Luca — AVPRO-NC (MS6), #HackAVP, Master MIAGE · IAE Nouvelle-Calédonie × OPT-NC&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/DamienJmt/avpro" rel="noopener noreferrer"&gt;Code source&lt;/a&gt; · &lt;a href="https://dev.to/maud_granger_nc/jobmatch-nc-quand-linteroperabilite-devient-plus-quun-defi-technique-1ma"&gt;JobMatch NC, le projet de la promo&lt;/a&gt; · &lt;a href="https://dev.to/pastek/hackavpi-dp8"&gt;HACKAVPI (MS2)&lt;/a&gt; · &lt;a href="https://dev.to/c2b/adopte-un-job-on-swipe-les-vrais-postes-de-lopt-nc-et-on-voit-pourquoi-ils-nous-correspondent-48pc"&gt;Adopte un Job (MS3)&lt;/a&gt; · &lt;a href="https://dev.to/jocc0/cv-matching-le-bon-profil-preuves-a-lappui-hackavp-4oh8"&gt;CV-Matching (MS5)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hackavp</category>
      <category>hackathon</category>
      <category>react</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
