TalentVision — Documentation

Documentation technique de la plateforme Sodexo Ma Carrière, déployée sur sodexo.coconutservices.fr. Gestion des talents, compétences, évolutions de carrière, et 3 bots IA connectés à Langflow.

Stack technique
Frontend : HTML/CSS/JS statique (Cloudflare Pages)
Backend : Cloudflare Pages Functions (Workers)
Base de données : Cloudflare D1 (SQLite)
IA / Bots : Langflow sur flow.coconutservices.fr

Architecture

┌──────────────────────────────────────────────────────┐ │ Frontend (Cloudflare Pages — statique) │ │ │ │ ┌──────────┐ Toggle [DEMO] [PROD] [DOC] │ │ │ DEMO │ → Données hardcodées en HTML │ │ │ PROD │ → fetch(/api/...) → D1 + Langflow │ │ │ DOC │ → /docs/ (cette page) │ │ └──────────┘ │ └──────────┬───────────────────────┬───────────────────┘ │ │ ▼ ▼ ┌─────────────────────┐ ┌──────────────────────────┐ │ /functions/api/ │ │ Langflow │ │ Pages Functions │ │ flow.coconutservices.fr │ │ │ │ │ │ employees.js │ │ • ChatbotFAQ │ │ employees/[id].js │ │ • ExtractionCV │ │ stats.js │ │ • MatchingEvolution │ │ notifications.js │ │ │ │ search.js │ │ (Ollama LLM backend) │ │ │ │ └──────────────────────────┘ │ ▼ │ │ ┌──────────────┐ │ │ │ Cloudflare D1 │ │ │ │ (SQLite) │ │ │ │ sodexo-talent│ │ │ └──────────────┘ │ └─────────────────────-┘

Arborescence du projet

coconut-website/ ├── index.html # Homepage Ma Carrière ├── wrangler.toml # Config Cloudflare ├── schema.sql # Schéma D1 ├── seed.sql # Données initiales ├── _routes.json # Routage Pages Functions │ ├── shared/ │ ├── dashboard.css # Design system complet │ ├── styles.css # Styles globaux │ └── mode.js # Toggle DEMO/PROD + notifications │ ├── BackOffice/ │ ├── index.html # Dashboard RH central │ ├── employees.html # Liste des collaborateurs │ ├── alexandre-esteves.html # Profil détaillé │ ├── antoine-moreau.html # Profil détaillé │ ├── marguerite-eyei.html # Profil détaillé │ └── gabriel-lowensohn.html # Profil détaillé │ ├── ChatbotFAQ/ │ └── index.html # Bot FAQ RH ├── ExtractionCV/ │ └── index.html # Bot extraction de CV ├── MatchingEvolution/ │ └── index.html # Bot matching candidats │ ├── docs/ │ └── index.html # Cette page │ └── functions/api/ ├── employees.js # GET /api/employees ├── employees/ │ └── [id].js # GET /api/employees/:id ├── stats.js # GET /api/stats ├── notifications.js # GET /api/notifications ├── notifications/ │ └── read.js # POST /api/notifications/read ├── search.js # GET /api/search ├── chat.js # POST /api/chat ├── extract-cv.js # POST /api/extract-cv └── matching.js # POST /api/matching

Base de données — Cloudflare D1

La base sodexo-talent utilise Cloudflare D1 (SQLite distribué). Le schéma est défini dans schema.sql et les données initiales dans seed.sql.

Tables

TableDescriptionClé primaireFK
employeesCollaborateurs (infos, scores, badges)id TEXT
skillsCompétences par employé (%)id INTEGERemployee_id
gapsGaps de compétences identifiésid INTEGERemployee_id
career_pathParcours carrière (timeline)id INTEGERemployee_id
turnover_factorsFacteurs de risque turnoverid INTEGERemployee_id
evaluationsÉvaluations (manager, auto-éval)id INTEGERemployee_id
notificationsNotifications globalesid INTEGER
context_signalsSignaux contextuels (RH/manager)id INTEGERemployee_id
statsKPI globaux (clé/valeur)key TEXT

Table employees — Colonnes principales

ColonneTypeDescription
idTEXT PKIdentifiant unique (ex: alexandre-esteves)
first_name, last_nameTEXTPrénom et nom
job_titleTEXTPoste actuel
affiliateTEXTFiliale Sodexo
siteTEXTSite géographique
evolution_scoreINTEGERScore d'évolution (0-100)
risk_levelTEXTlow / medium / high
turnover_risk_pctINTEGERRisque de turnover (%)
engagement_pctINTEGEREngagement (%)
badge_labelTEXTBadge (Haut Potentiel, etc.)
profile_pageTEXTURL de la page profil

Déploiement de la base

# Créer la base D1
npx wrangler d1 create sodexo-talent

# Appliquer le schéma
npx wrangler d1 execute sodexo-talent --file=schema.sql

# Insérer les données initiales
npx wrangler d1 execute sodexo-talent --file=seed.sql

API — Employees

GET /api/employees

Liste paginable et filtrable de tous les collaborateurs.

ParamètreTypeDescription
searchstringRecherche nom/prénom/poste (LIKE)
affiliatestringFiltre par filiale
sitestringFiltre par site
departmentstringFiltre par département
riskstringFiltre par niveau de risque
score_minintegerScore d'évolution minimum
score_maxintegerScore d'évolution maximum
sortstringTri : name, score, risk, tenure

Réponse :

{
  "employees": [
    {
      "id": "alexandre-esteves",
      "first_name": "Alexandre",
      "last_name": "Esteves",
      "job_title": "Chef de projet digital",
      "evolution_score": 82,
      "risk_level": "low",
      "badge_label": "Haut Potentiel",
      ...
    }
  ]
}

API — Employee Detail

GET /api/employees/:id

Profil complet d'un collaborateur avec toutes ses données associées.

Réponse :

{
  "employee": { ... },
  "skills": [
    { "name": "Leadership", "percentage": 88, "category": "soft" }
  ],
  "gaps": [
    { "competence": "Anglais C1", "gap_level": "moyen", "training_recommendation": "..." }
  ],
  "career_path": [
    { "title": "...", "company": "Sodexo", "date_range": "2022-...", "status": "current" }
  ],
  "turnover_factors": [ ... ],
  "evaluations": [ ... ],
  "context_signals": [ ... ]
}

API — Stats

GET /api/stats

KPI globaux du dashboard.

{
  "stats": [
    { "key": "total_employees", "value": "847", "change_label": "+12", "change_direction": "up" },
    { "key": "avg_evolution_score", "value": "72", ... },
    { "key": "turnover_risk", "value": "8.2%", ... },
    { "key": "high_potential", "value": "23", ... }
  ]
}

API — Notifications

GET /api/notifications

Liste des notifications, triées par date décroissante.

{
  "notifications": [
    {
      "id": 1,
      "title": "Nouvelle évaluation",
      "message": "Antoine Moreau a complété son auto-évaluation",
      "timestamp": "2025-01-15T10:30:00Z",
      "is_read": 0,
      "icon": "eval",
      "target_page": "/BackOffice/antoine-moreau.html"
    }
  ]
}

POST /api/notifications/read

Marque toutes les notifications comme lues. Body vide.

// Response
{ "success": true }

GET /api/search?q=...

Proxy vers l'API Brave Search. Utilisé pour la recherche contextuelle.

ParamètreTypeRequisDescription
qstringouiTerme de recherche
Authentification
Nécessite la variable d'environnement BRAVE_SEARCH_API_KEY configurée dans Cloudflare.

Langflow — ChatbotFAQ

POST /api/chat

Proxy vers le flow Langflow ChatbotFAQ. Répond aux questions RH des collaborateurs.

Champ bodyTypeRequisDescription
messagestringouiMessage de l'utilisateur
conversationIdstringnonID session pour continuité
// Request
{ "message": "Combien de jours de congés me reste-t-il ?" }

// Response
{ "response": "Selon votre solde actuel, il vous reste..." }
Langflow
Base URL : https://flow.coconutservices.fr
Route interne : /api/v1/run/{FLOW_ID}
Variable : LANGFLOW_CHAT_FLOW_ID (default: chatbot-faq)

Langflow — Extraction CV

POST /api/extract-cv

Upload de CV (PDF/DOCX) pour extraction automatique des compétences via Langflow.

ChampTypeDescription
filesFormDataUn ou plusieurs fichiers CV
// Response
{
  "results": [
    { "file": "cv-moreau.pdf", "result": "Compétences extraites : ..." }
  ]
}
Fonctionnement
Les fichiers sont convertis en base64 côté Worker puis envoyés dans le champ tweaks.file_content du payload Langflow. Variable : LANGFLOW_CV_FLOW_ID (default: extraction-cv)

Langflow — Matching Évolution

POST /api/matching

Déclenche le pipeline de matching candidat/poste via Langflow.

Champ bodyTypeDescription
employeeIdstringID de l'employé (optionnel, sinon tous)
actionstringstart = pipeline global
// Request
{ "action": "start" }

// Response
{ "status": "running", "result": "Pipeline démarré pour 847 collaborateurs..." }

Mode DEMO / PROD / DOC

Un toggle 3 boutons est présent dans la topbar de toutes les pages. Le mode est persisté via localStorage('sodexo_mode').

ModeComportementCouleur
DEMODonnées hardcodées en HTML (aucun appel réseau)Orange
PRODDonnées chargées depuis D1 via fetch(/api/...)Vert
DOCRedirige vers /docs/ (cette page)Bleu Sodexo

JavaScript (/shared/mode.js)

var SODEXO_MODE = localStorage.getItem('sodexo_mode') || 'demo';

function setMode(mode) {
  SODEXO_MODE = mode;
  localStorage.setItem('sodexo_mode', mode);
  // Met à jour les boutons + appelle onModeChange() si défini
}

function apiFetch(endpoint) {
  return fetch('/api' + endpoint).then(function(r) { return r.json(); });
}

function apiPost(endpoint, data) {
  return fetch('/api' + endpoint, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  }).then(function(r) { return r.json(); });
}
Intégration
Chaque page peut définir une fonction onModeChange(mode) qui sera appelée automatiquement quand l'utilisateur change de mode. En mode PROD, cette fonction déclenche les appels API pour remplacer les données hardcodées.

Design Tokens

Variables CSS définies dans /shared/dashboard.css :

VariableValeurUsage
--sodexo-primary #283897Bleu Sodexo principal
--sodexo-primary-light #E7E9F7Fond hover / sélection
--sodexo-primary-dark #2A295CTitres, texte fort
--sodexo-accent #DA2020Rouge alerte / badge
--sodexo-green #2ecc71Succès, mode PROD
--sodexo-orange #f39c12Warning, mode DEMO
--sodexo-bg #f4f5f7Fond de page
--sodexo-border #e8e8e8Bordures, séparateurs

Vues par rôle

Les pages profils disposent de 3 vues avec des informations différentes selon le rôle :

RôleClasse CSSVisibilité
RH.view-rhTout : scores, signaux, turnover, gaps, évaluations
Manager.view-managerCompétences, évaluations, gaps (sans signaux sensibles)
Collaborateur.view-collabVue personnelle : compétences propres, carrière, formations

Le toggle de rôle est dans la topbar des pages profils. Il ajoute la classe role-{role} sur <body> et le CSS masque les sections non autorisées.

Variables d'environnement

VariableRequisDescriptionDefault
DBouiBinding D1 (auto via wrangler.toml)
LANGFLOW_CHAT_FLOW_IDnonFlow ID pour ChatbotFAQchatbot-faq
LANGFLOW_CV_FLOW_IDnonFlow ID pour ExtractionCVextraction-cv
LANGFLOW_MATCHING_FLOW_IDnonFlow ID pour Matchingmatching-evolution
BRAVE_SEARCH_API_KEYoui*Clé API Brave Search
Important
Les variables sont configurées dans Cloudflare Pages → Settings → Environment variables. Le binding D1 est défini dans wrangler.toml.

Déploiement

wrangler.toml

name = "sodexo"
compatibility_date = "2024-01-01"
pages_build_output_dir = "."

[[d1_databases]]
binding = "DB"
database_name = "sodexo-talent"
database_id = "<ID>"

Commandes

# Déploiement via GitHub (auto)
git add . && git commit -m "deploy" && git push

# Ou déploiement direct
npx wrangler pages deploy .

# Migration DB
npx wrangler d1 execute sodexo-talent --file=schema.sql
npx wrangler d1 execute sodexo-talent --file=seed.sql
CI/CD
Le déploiement est automatique via GitHub → Cloudflare Pages. Chaque push sur main déclenche un build et un déploiement. Les Pages Functions dans /functions/ sont détectées automatiquement.

TalentVision Documentation — Sodexo Ma Carrière — Généré par Claude Code