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

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. »
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.
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.

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
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é.
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.
Image construite
Une seule image Docker, étiquetée par commit, jamais écrasée.
Feu vert humain
Rien ne part en production sans une validation manuelle.
Mise en ligne
Migrations de base rejouables sans effet de bord, puis démarrage.
Contrôle de santé
L'app doit répondre dans les trois minutes qui suivent.
Retour arrière
Sinon, la version précédente revient toute seule.





