Greg Gargiulo
M’écrire
Retour

ERP Circul’Egg.

Année : 2026

L’atelier trace chaque lot sur téléphone, de la réception des coquilles à l’expédition

Trois écrans d’opérateur : le parcours d’un lot de la réception à l’expédition, un séchage en cours, l’état des cuves.

Fiche

Rôle
Conception et développement, seul côté technique
Équipe
Le dirigeant pour les arbitrages, les responsables qualité et production pour la recette
Période
Mai à octobre 2026, puis évolutions
Statut
En production depuis le 5 octobre 2026
Code
Privé, dépôt de l’entreprise
Captures
Écrans des guides utilisateurs, réalisés sur des comptes de test ; codes de lots neutralisés, paramètres machine et cibles qualité masqués.

En bref

Circul’Egg, biotech lauréate du Grand Prix 2023 de l’Académie des technologies, transforme les coquilles d’œufs en ingrédients pour l’industrie. J’ai conçu et développé seul son ERP de production, une application web qui s’installe sur les téléphones de l’atelier et continue de fonctionner sans réseau. Depuis le 5 octobre 2026, les opérateurs y saisissent chaque étape de la fabrication, et la qualité y libère les lots.

Point de départ

La production se suivait sur papier et dans des fichiers Excel. Pour savoir de quel lot de coquilles venait une expédition, il fallait recouper des fiches à la main. Et aucun lot ne pouvait partir sans une décision de la qualité, consignée elle aussi sur papier.

Contraintes

  • Un atelier où l’on travaille avec des gants, et où le réseau ne passe pas partout.
  • Garder Airtable, déjà en place, comme base de données, et n’ajouter aucun serveur à maintenir.
  • Des quotas à respecter : appels à l’API Airtable, fonctions Vercel, minutes d’intégration continue.
  • Un seul développeur, et une mise en service planifiée avec la direction.

Livrables

  • Les parcours de chaque poste : réception, séchage, broyage, libération qualité, ensachage, expédition, arrêts machine.
  • Quatre espaces selon le rôle : opérateur, production, qualité et direction ; des tableaux de bord et des exports mensuels pour les trois derniers.
  • Une base Airtable de 30 tables, documentée table par table.
  • Une file de synchronisation hors ligne, et trois fonctions serverless qui gardent la clé d’accès à la base.
  • Le calcul du verdict qualité et le classement couleur des poudres.
  • Une sauvegarde nocturne des données, du schéma et des photos, avec une procédure de restauration testée.
  • Des tests unitaires et de bout en bout, lancés à chaque envoi de code.
  • Quatre guides utilisateurs en PDF et des feuilles de poste imprimables.

Architecture

Une application web progressive en React et TypeScript, installée sur les téléphones de l’atelier. Chaque saisie est d’abord écrite dans IndexedDB, sur le téléphone, puis envoyée par une file de synchronisation à des fonctions serverless sur Vercel, seules à détenir la clé Airtable. Airtable sert de base de données, et d’outil de consultation pour la direction.

Trois fonctions partagent le même cœur de proxy : l’accès aux tables, l’envoi des photos et l’authentification par code PIN. Le service worker installe les mises à jour de lui-même, mais seulement sur l’accueil ou sur l’écran de connexion, jamais pendant une saisie en cours.

Les plafonds d’abonnement sont traités comme une contrainte technique. Pendant le développement, le mois le plus chargé a consommé 5 716 appels à l’API Airtable, soit 5,7 % du plafond ; une mise en cache de deux minutes des indicateurs de l’accueil a ensuite divisé par sept environ les requêtes envoyées à chaque retour sur cet écran. Fin septembre, le plus sollicité des compteurs d’usage Vercel restait à 2 % de son plafond.

Stack technique

Langages
  • TypeScript
Interface
  • React
  • React Router
  • Tailwind CSS
  • PWA (vite-plugin-pwa)
Serveur
  • Fonctions serverless Vercel (Node.js)
Bases de données
  • Airtable
  • IndexedDB (Dexie)
Documents générés
  • jsPDF
  • write-excel-file
Infrastructure
  • Vite
  • Vercel
  • GitHub Actions
Tests
  • Vitest
  • Playwright
  • ESLint

Décisions

  1. Des écrans faits pour des mains gantées

    Les écrans sont conçus pour 375 px de large. Les boutons d’action mesurent 56 px, parce qu’avec des gants ils doivent répondre du premier coup ; les filtres, qui servent à consulter, descendent à 48 px pour tenir sur une seule ligne. Un test de bout en bout mesure ces tailles à l’écran. Chaque rôle a son propre accueil et son guide.

    Après chaque validation, un récapitulatif remplace le formulaire : le bouton retour ramène à l’accueil du module, jamais sur un formulaire déjà validé. Si l’opération a déjà été enregistrée, depuis ce téléphone ou un autre, l’écran le dit au lieu de l’enregistrer une seconde fois.

    Fin de séchage : la cuve, l’heure d’arrêt et les quantités, puis un seul bouton.
  2. Une application qui continue sans réseau

    Hors réseau, l’opérateur continue de travailler : ses saisies attendent dans la file du téléphone et partent dès que le réseau revient. Chacune porte un identifiant unique, créé sur le téléphone. Si une réponse se perd et que la saisie repart, l’application retrouve dans la base la fiche déjà créée au lieu d’en créer une seconde ; si elle ne peut pas vérifier, elle n’écrit rien plutôt que de créer à l’aveugle.

    La file respecte l’ordre des saisies, si bien qu’une erreur passagère, réseau ou serveur, la retient. Une saisie refusée pour de bon, par exemple une donnée invalide, est en revanche mise de côté : les suivantes continuent de partir, et l’erreur reste affichée jusqu’à ce qu’elle soit traitée.

  3. Un bandeau qui dit la vérité sur la synchronisation

    En haut de chaque écran, un bandeau a quatre états : rouge quand des saisies sont en échec, orange hors ligne ou quand la connexion est instable, gris pendant l’envoi, vert quand tout est à jour. Le 6 août, pendant une panne de routage, il est resté vert alors que toutes les requêtes échouaient, parce qu’il tenait tout code 200 pour un succès, même quand la réponse était une page web. Depuis, seule une réponse lisible compte, ce qui écarte aussi les portails Wi-Fi, et le vert est daté, par exemple « À jour · 12:48 ».

  4. Un stock calculé, jamais saisi

    Chaque transformation enregistre une sortie du lot transformé et une entrée dans le lot qui en naît. Le stock est la somme de ces mouvements ; en les remontant, on retrouve de quelles coquilles vient n’importe quel sac.

    Les mouvements de stock n’admettent pas d’échec partiel : ils sont tous écrits, ou l’opération entière échoue, car un mouvement manquant fausserait le stock. Les changements d’état secondaires, comme le statut d’une cuve, peuvent échouer sans annuler la saisie principale ; ils sont rattrapés à la tentative suivante ou corrigés à la main.

  5. La qualité garde le dernier mot sur chaque lot

    À la libération, l’application calcule un verdict à partir des cibles fixées par la qualité. Les mesures chiffrées (granulométrie, extrait sec, couleur) sont comparées à leurs bornes, les analyses microbiologiques sont conformes ou non, et une analyse non renseignée n’est jamais comptée comme conforme. La couleur sert déjà plus tôt : au broyage, ses écarts colorimétriques classent la poudre dans l’une de trois qualités.

    Si la responsable qualité contredit le verdict, elle doit écrire pourquoi ; si elle libère un lot dont des analyses manquent, l’application le lui signale sans la bloquer. Un lot refusé garde la liste des familles de paramètres en cause, parce que cette cause ne pourrait plus être reconstituée après coup.

    La libération d’un lot : la fiche de contrôle, puis l’écran de décision.
  6. Des tests qui rejouent l’atelier, hors ligne compris

    À chaque envoi de code, l’intégration continue enchaîne le lint, la vérification des types, les tests unitaires (Vitest) et les tests de bout en bout (Playwright), qui rejouent les parcours dans un navigateur. Une partie tourne sur le build de production, service worker actif et réseau coupé, car le mode développement n’installe pas de service worker et ne prouve rien sur le hors-ligne réel. Un test instable n’est jamais déclaré réparé parce qu’il est repassé au vert : la correction doit expliquer pourquoi l’échec est devenu impossible, et dire ce qu’elle ne couvre pas.

  7. Des accès protégés et des sauvegardes déjà restaurées

    Le code PIN n’est vérifié que côté serveur, où il est haché avec un sel et une clé secrète (HMAC-SHA256) : le téléphone ne détient donc aucun secret, pas plus que la clé de la base. Chaque nuit, les données, le schéma et les photos sont sauvegardés. La restauration a été testée deux fois, la seconde sur une base créée de zéro et suivie d’un parcours complet dans l’application ; un nouveau test est prévu chaque trimestre.

Résultats

5 oct. 2026
mise en service à l’usine de Janzé
1 673
tests unitaires qui passent, et 138 fichiers de tests de bout en bout
189
décisions métier et techniques, écrites et datées
982
commits entre le 18 mai et le 29 octobre 2026

Chaque fonctionnalité est partie d’une note de cadrage, 43 au total. La première semaine d’utilisation à l’atelier a donné lieu à trois séries de correctifs, tirées de l’usage réel : un bouton « La machine est arrêtée », lu comme un état, faisait déclarer des arrêts par erreur plusieurs fois par jour ; il est devenu « Déclarer un arrêt machine ».