Aller au contenu principal
Références

UltraMesure

L'application métier que nous avons conçue et développée, du relevé en sous-sol jusqu'au rapport PDF.

  • Web application
Plan du niveau -1 d'un bâtiment, annoté dans l'application : dix points de mesure numérotés, neuf verts et un orange, avec la légende des niveaux de corrosion.
Un plan annoté par l'app, extrait d'un rapport réel anonymisé.

Au départ, un diagnostiqueur qui mesure des tuyaux dans des sous-sols sans réseau, puis monte ses rapports sous Word. À l'arrivée, une app qui marche sous terre et écrit le rapport avec lui.

Client
UltraMesure, diagnostic de corrosion par ultrasons
Notre part
Conception UX/UI, développement, hébergement
Application
React 19, Vite, API Hono, PostgreSQL
Hors ligne
IndexedDB et service worker

Changer de socle, quand le premier ne tenait pas hors ligne.

Nous avions démarré sur Next.js. Sur le terrain, l'app devait fonctionner sans réseau, et elle n'y arrivait pas : une page jamais ouverte ne s'affichait pas en mode avion. Deux jours de réglages du cache n'y ont rien changé. Plutôt que d'empiler les contournements, nous avons changé de socle.

« RSC bloque la navigation offline vers les pages non visitées. »

Notre note de migration

Avant

  • Next.js App Router
  • Rendu côté serveur
  • Session par cookie

Après

  • React 19 et Vite, toute l'app mise en cache
  • API Hono, servie à côté
  • Jeton JWT à la place du cookie

18 routes d'API et 16 pages portées une à une, en production dès le lendemain.

Tenir sans réseau, parce qu'un sous-sol n'en a pas.

Le parcours terrain, sur la maquette animée de l'app. Données anonymisées.

Nous avons écrit notre propre moteur de synchronisation. Il se déclenche toutes les cinq minutes et au retour du réseau, et alerte si rien n'est parti depuis 48 heures. Son ordre n'a rien d'arbitraire.

client/src/core/offline/sync-engine.ts (extrait)
await pushDeletions();  // suppressions faites hors ligne
await pullFromServer();  // ce qui a changé ailleurs
await pullPhotos();
await syncPlanBlobs();   // les plans, avant ce qui les cite
await syncData();        // les mesures
await syncPhotos();      // les photos, par lots
Le téléphone d'abord
Chaque saisie s'écrit dans le navigateur avant tout. Le serveur sert de sauvegarde et de relais entre les appareils.
Rien d'écrasé en silence
Une modification pas encore envoyée n'est jamais remplacée par la version du serveur, même plus récente.
Le mode avion prévu
Un appel réseau sans réponse est coupé au bout de trois secondes : l'app ne reste jamais suspendue à une connexion fantôme.
Une connexion qui marche sous terre
Les identifiants se vérifient sur l'appareil, hachés en PBKDF2 avec 210 000 itérations et un sel propre au téléphone.
Un filet quand iOS fait le ménage
Si le système vide les données locales, l'app s'en aperçoit et recharge tout depuis le serveur au lieu de repartir de zéro.

Mettre le plan dans la poche, avec les photos et les points.

Le diagnostic se fait sur le plan réel du bâtiment. Il fallait qu'il s'ouvre, se manipule et s'annote au doigt, sur un téléphone, sans réseau.

Détail agrandi du plan : dix points de mesure serrés autour d'un local technique, écartés les uns des autres et reliés par un trait fin à leur position réelle.
Détail : les points écartés restent reliés à leur position réelle.
  • Le PDF devient une image sur place

    Le plan du bâtiment est converti dans le navigateur, jusqu'à 3 000 pixels, sans aller-retour serveur.

  • Pincer, tourner, déplacer

    Zoom à deux doigts, rotation au quart de tour mémorisée, points déplaçables au doigt.

  • Des photos dix fois plus légères

    Compressées sur le téléphone, de 3 à 5 Mo vers 200 à 400 Ko, pour partir même avec une barre de réseau.

  • Des points qui restent lisibles

    À l'export, un algorithme écarte les points qui se chevauchent et les relie à leur position d'origine.

Coder le métier, avec les règles de l'expert, pas les nôtres.

La perte d'épaisseur, les seuils de couleur, les tables de diamètres par matériau : tout vient d'UltraMesure. Notre travail a été de l'écrire sans trahir, puis de le vérifier par des tests.

  • Six matériaux, de l'acier noir à la fonte. Le diamètre relevé est rapproché de la table à 5 % ou 1 mm près, et l'épaisseur d'origine s'en déduit.
  • Pas de faux vert. Une épaisseur relevée plus forte que l'origine signale une erreur de saisie : la mesure reste sans couleur au lieu de passer en bon état.
  • Une couleur, trois supports. Écran, PDF et Excel partent d'une seule palette, et le PDF reprend les teintes des rapports Word d'UltraMesure.

Acier noir, DN 40épaisseur d'origine 2,90 mm, déduite de la table

9,7 %Bon état

Faites varier l'épaisseur : même formule et mêmes seuils que dans l'app.

Écrire le rapport avec lui, pas à sa place.

Avant d'écrire une ligne, nous avons décortiqué douze rapports d'UltraMesure. Leurs paragraphes récurrents sont devenus une bibliothèque de vingt blocs, repris au mot près. Le rapport se monte ensuite dans le navigateur, hors ligne compris.

Des variables, pas du copier-coller

Les blocs de texte contiennent des variables, remplacées au moment de générer le PDF.

  • {{site}}
  • {{adresse}}
  • {{date}}
  • {{nb_mesures}}

Une suggestion, jamais une décision

L'app propose une conclusion d'après la pire mesure relevée. C'est le diagnostiqueur qui choisit de l'insérer : rien n'entre seul dans le rapport.

Des annexes à la bonne page

Les PDF de laboratoire s'insèrent n'importe où. Le rapport est rendu deux fois pour que la pagination tombe juste, puis tout est fusionné.

Un rapport réel, sorti de l'app puis anonymisé.

  • Couverture du rapport : titre, numéro de rapport, destinataire et site, anonymisés.
  • Pages Mission et Méthodologie, avec le code couleur d'interprétation des résultats.
  • Résultats du sous-sol : le plan annoté avec les points de mesure colorés.
  • Fiches de mesure : diamètre, matériau, épaisseurs, pourcentage de perte et photo pour chaque point.
  • Conclusions rédigées pour le réseau d'eau glacée.
  • Tableau de synthèse des mesures par étage, lignes colorées selon le niveau de corrosion.

UltraMesure estime gagner environ six heures de travail par chantier.

Tenir en production, avec une relecture et un filet.

Une fois l'app en service, nous l'avons relue de bout en bout : 31 constats, dont 6 critiques, traités par lots. Et nous avons posé un déploiement qui sait revenir en arrière tout seul.

  • Chaque requête vérifie que les données appartiennent bien au compte qui les demande.
  • Les noms de fichiers reçus sont filtrés : impossible de sortir du dossier prévu.
  • Politique de sécurité stricte côté navigateur, conteneur qui tourne sans droits root.
  • Une seule campagne de mesure active par site, garantie par la base elle-même.
  • Le serveur de développement refuse de démarrer s'il pointe sur la base de production.
  1. Image construite

    Une seule image Docker, étiquetée par commit, jamais écrasée.

  2. Feu vert humain

    Rien ne part en production sans une validation manuelle.

  3. Mise en ligne

    Migrations de base rejouables sans effet de bord, puis démarrage.

  4. Contrôle de santé

    L'app doit répondre dans les trois minutes qui suivent.

  5. Retour arrière

    Sinon, la version précédente revient toute seule.