← retour aux projets

CS.03, CASE STUDY · CÔTÉ SYSTÈME

Le Boudoir d'Alice

Freelance · en production

voir le site en ligne
|←BOUDOIR-ALICE.FR · ACCUEIL · EN PRODUCTION→|
|←HUB SANTÉ · 19 PATHOLOGIES PAR FAMILLE→|
|←LANDING PATHOLOGIE · DIABÈTE TYPE 2→|

CONTEXTE

Marmiton, Jow ou Yuka ne savent rien de vos pathologies. Hypertension (17 M de Français), diabète (3,8 M traités), insuffisance rénale, SOPK : cuisiner avec une maladie chronique reste un casse-tête quotidien. Et un créneau vide en francophonie.

MON RÔLE

Le projet le plus complet du portfolio : positionnement, identité visuelle, UX, développement full-stack et mise en production, seul de bout en bout.

RÉALISATIONS

  • Base CIQUAL 2025 de l'ANSES intégrée : 3 484 aliments, ~74 composants nutritionnels chacun, import XML officiel
  • 19 pathologies avec restrictions sourcées (HAS, ANSES, sociétés savantes) et moteur de compatibilité par seuils
  • Fonctionnalités complètes : frigo virtuel, batch cooking, planning de repas, listes de courses, IA culinaire avec OCR
  • Laravel 12 + React 19/Inertia SSR : 52 modèles, 68 migrations, 83 pages, Meilisearch, monitoring Sentry

CHIFFRES

CIQUAL : 3 484 aliments · 74 nutriments · 19 pathologies sourcées · 52 modèles · 83 pages · OCR vision

OUTILS

  • Laravel 12
  • PHP 8.2
  • React 19
  • Inertia v2
  • Tailwind 4
  • Meilisearch
  • Sentry
  • Docker

CS.03.M, LES MODULES, PIÈCE PAR PIÈCE

Sous le capot

01 · La base santé : CIQUAL 2025

Le socle du projet est la table de composition nutritionnelle officielle française, publiée par l'ANSES : 3 484 aliments décrits par une soixantaine de colonnes (énergie, macronutriments, 10 minéraux, 13 vitamines, acides gras détaillés). L'import parse les XML officiels, et un service de correspondance floue relie chaque ingrédient de recette à son aliment CIQUAL, avec un taux de couverture calculé par recette.

Hub Santé & Nutrition du Boudoir d'AliceLanding SEO pour le diabète de type 21 / 2
|←LA PROMESSE PRODUIT · /SANTE→|
database/seeders/PathologySeeder.phpphp
$pathology->nutrientRestrictions()->createMany([
    [
        'nutrient_code' => 'sugars',
        'nutrient_name_fr' => 'Sucres',
        'restriction_type' => 'limit',
        'max_daily' => 25,
        'unit' => 'g',
        'advice_fr' => 'Éviter les sucres ajoutés, sodas, jus de fruits, pâtisseries',
        'severity' => 'danger',
        'display_order' => 1,
    ],
    [
        'nutrient_code' => 'fiber',
        'nutrient_name_fr' => 'Fibres',
        'restriction_type' => 'increase',
        'min_daily' => 30,
        'unit' => 'g',
        'advice_fr' => 'Augmenter les légumes, légumineuses, céréales complètes',
        'severity' => 'info',
        'display_order' => 2,
    ],
]);
Chaque pathologie est décrite en données sourcées : seuils, sens de la restriction, sévérité, conseil.

02 · Le moteur de compatibilité

Pour chaque recette et chaque pathologie du profil, le moteur évalue les valeurs nutritionnelles par portion contre des seuils typés (limiter, éviter, augmenter, surveiller) et gradue la sévérité. Une portion qui dépasse la moitié de l'apport journalier maximal déclenche l'alerte, le dépassement complet passe au rouge. En sortie : un feu tricolore et des messages explicites.

app/Services/RecipeCompatibilityService.phpphp
case 'limit':
    // Vérifier par portion d'abord
    if ($restriction->max_per_portion !== null && $perServingValue > $restriction->max_per_portion) {
        return [
            'message' => "{$nutrientName}: {$this->formatValue($perServingValue)}{$unit}/portion",
            'severity' => $restriction->severity,
            'value' => $perServingValue,
            'threshold' => $restriction->max_per_portion,
        ];
    }

    // Vérifier si la recette entière dépasse la limite journalière
    if ($restriction->max_daily !== null) {
        $percentDaily = ($perServingValue / $restriction->max_daily) * 100;
        if ($percentDaily > 50) {
            $severityLevel = $percentDaily > 100 ? 'danger'
                : ($percentDaily > 75 ? 'warning' : 'info');
            return [
                'message' => "{$nutrientName}: {$this->formatValue($percentDaily)}% de l'apport max quotidien",
                'severity' => $severityLevel,
                'value' => $perServingValue,
                'threshold' => $restriction->max_daily,
            ];
        }
    }
    break;
Évaluation d'une restriction « limit » : seuil par portion d'abord, puis pourcentage de l'apport journalier.

03 · L'assistant IA et l'OCR

Trois fournisseurs de modèles en cascade avec quotas par utilisateur, prompts versionnés en base. La saisie d'une recette peut partir d'une simple photo : un modèle de vision extrait ingrédients et étapes, prêts à éditer. Génération d'images de recettes intégrée au même pipeline.

app/Services/GrokService.phpphp
$payload = [
    'model' => 'grok-2-vision-1212',
    'max_tokens' => 4096,
    'temperature' => 0.1,
    'messages' => [
        [
            'role' => 'user',
            'content' => [
                [
                    'type' => 'image_url',
                    'image_url' => ['url' => $imageUrl],
                ],
                [
                    'type' => 'text',
                    'text' => $prompt,
                ],
            ],
        ],
    ],
];

$response = Http::withHeaders([
    'Authorization' => 'Bearer ' . $this->apiKey,
    'Content-Type' => 'application/json',
])->timeout(60)->post("{$this->apiUrl}/chat/completions", $payload);
Extraction de recette depuis une photo : payload vision, température basse, timeout court.

04 · Un produit complet, étudié comme tel

Au-delà du code : frigo virtuel multi-frigos avec péremption, batch cooking en kanban, planning hebdomadaire, listes de courses générées, prix collaboratifs validés par votes, profils sociaux. Et un audit produit complet (marché, concurrence, SEO, monétisation) qui a établi le positionnement : personne en francophonie ne croise multi-pathologies et base officielle, et le persona le plus solvable est l'aidant qui cuisine pour un proche malade.

LA FACE VISIBLE, CÔTÉ STUDIO