01PRODUIT MOBILE · PRÉ-LANCEMENT · GESTION LOCATIVE

ImmoZen

Application mobile pour propriétaires bailleurs : gestion des biens, des locataires et des loyers, et génération des documents officiels français — quittances, attestations, états des lieux signés.

RÔLE
seul développeur
MARQUE
domaine réservé
COMMITS
~82
SURFACES
mobile + API
ÉTAT
◐ pré-lancement
CONTEXTE

Un bailleur particulier gère deux ou trois lots. Les quittances se tapent à la main chaque mois, les états des lieux se remplissent au stylo sur un formulaire acheté en ligne, et les photos restent dans la pellicule du téléphone.

Le jour où le locataire part, il faut comparer deux documents papier séparés par trois ans. C'est là que naissent les litiges.

LE PROBLÈME À RÉSOUDRE
  • Produire des documents conformes au droit français, opposables, depuis un téléphone.
  • Rendre l'état des lieux exhaustif sans le rendre décourageant.
  • Faire signer le locataire sur place, sans imprimante.
  • Tenir des données sensibles — identités, RIB, documents — sans être une équipe.
L'ÉTAT DES LIEUX EN CINQ ÉTAPES

Le parcours suit la visite : on avance pièce par pièce, on ne revient pas en arrière pour chercher un champ oublié.

  1. 01type, date, présents, nombre de pièces
  2. 02pièce par pièce : état, remarques, photos
  3. 03équipements — chauffage, électricité, plomberie
  4. 04photos générales du logement
  5. 05signature locataire puis bailleur, PDF généré
Étape 2 — état d'une pièce
Étape 5 — signature
DÉCISIONS TECHNIQUES
DÉCISION
Découper l'état des lieux par pièce plutôt qu'en un formulaire unique
POURQUOI
Un formulaire de quatre-vingts champs se remplit à moitié. Découpé par pièce, le parcours suit la visite réelle et chaque photo trouve son emplacement naturel.
CONSÉQUENCE
Le brouillon est reprenable, l'état des lieux se termine sur la signature, et le PDF final reprend exactement ce que le locataire a vu à l'écran.
DÉCISION
Supabase pour l'auth et le stockage, API Express 5 + Prisma pour le métier
POURQUOI
Google OAuth, Apple Sign-in et le stockage de pièces jointes sont des problèmes résolus. Les règles de génération documentaire, non : elles doivent rester sous mon contrôle et côté serveur.
CONSÉQUENCE
Deux surfaces serveur à tenir au lieu d'une, mais aucune règle métier dans l'app mobile — donc rien à corriger par une mise à jour de store en urgence.
DÉCISION
PDF produits sur l'appareil (expo-print), signature manuscrite sur canvas
POURQUOI
Un état des lieux se signe dans un appartement vide, parfois sans réseau. Attendre un aller-retour serveur pour imprimer un document, c'est perdre la signature.
CONSÉQUENCE
Le document part par mail dès que le réseau revient, et l'archive serveur est identique à la copie locale.
DÉCISION
Rapport de pentest interne avant l'ouverture au public
POURQUOI
L'app stocke des identités, des coordonnées bancaires et des photos de logements occupés. Une fuite ici n'est pas un incident technique, c'est un problème pour des tiers.
CONSÉQUENCE
Correctifs livrés avant le lancement, et un document que je peux montrer à un client ou à un recruteur.
STACK COMPLÈTE
mobile
React Native 0.81, Expo 54, Expo Router, TypeScript
données
Supabase — Postgres, Auth, Storage, Edge Functions
api
Express 5, Prisma
identité
Google OAuth, Apple Sign-in
documents
expo-print, signature canvas
achats
RevenueCat
tests · infra
Jest, Docker Compose
LIENS
02PLATEFORME · 3 SURFACES · BÊTA TEST

The Squirrel

Un produit complet pour restaurateurs : catalogue, inventaire, calcul automatique des quantités à commander selon les stocks cibles, envoi des commandes par email depuis la vraie boîte du restaurateur, scan OCR des bons de livraison, facturation.

RÔLE
développeur produit
SOCIÉTÉ
TAAG
DEPUIS
mars 2026
COMMITS
~167
SURFACES
3 apps + packages
ÉTAT
◐ bêta test
CONTEXTE

Un restaurateur commande chez huit à quinze fournisseurs. Les stocks sont dans sa tête, les commandes partent par téléphone ou par mail depuis le fond de la cuisine, les bons de livraison s'empilent près de la caisse et la facturation se rattrape en fin de mois.

Les outils existants supposent une équipe administrative. Ici il n'y en a pas : c'est le chef, entre deux services, sur un téléphone.

LE PROBLÈME À RÉSOUDRE
  • Calculer quoi commander, et en quelle quantité, sans que l'utilisateur ait à raisonner.
  • Envoyer la commande de sorte que le fournisseur reconnaisse l'expéditeur : sa vraie adresse, pas une adresse de plateforme.
  • Reprendre les bons de livraison papier sans saisie manuelle.
  • Tenir trois surfaces — cuisine, web, back-office — sans tripler le code.
LES TROIS SURFACES

Un seul monorepo Turborepo + pnpm, des packages partagés pour les types, le client API et la logique de calcul.

App mobile — commandes groupées par date de livraison

App mobile

cuisine

Inventaire, quantités calculées, envoi de commande, scan des bons de livraison.

React Native · Expo · Zustand · EAS Build
Site vitrine The Squirrel — page d'accueil

Site & espace client

web

Vitrine, inscription, paiement, compte, invitation d'employés, CGU / CGV / mentions légales.

Next.js · Stripe · RevenueCat
Console d'administration TAAG — écran de connexion

Back-office

admin

Suivi des comptes restaurants, abonnements, support et supervision des envois.

NestJS · Prisma · PostgreSQL
DÉCISIONS TECHNIQUES

Chaque décision porte sa raison et sa conséquence. C'est la section que je lirais en premier si je recrutais.

DÉCISION
Envoi via la boîte mail du client : Gmail API en OAuth2 et SMTP universel
POURQUOI
Un fournisseur qui reçoit une commande depuis une adresse inconnue ne la traite pas. Les restaurateurs sont sur Gmail, Outlook, OVH, Infomaniak, Yahoo, Free ou IONOS — il fallait couvrir les deux mondes.
CONSÉQUENCE
Presets par fournisseur, configuration chiffrée AES-256 côté serveur, connexion testée avant enregistrement. Zéro paramétrage visible pour l'utilisateur.
DÉCISION
Monorepo Turborepo, trois apps, packages partagés
POURQUOI
Le calcul des quantités et les types de commande doivent être identiques dans l'app, sur le web et dans l'admin. Trois dépôts auraient produit trois vérités.
CONSÉQUENCE
Un changement de règle métier se fait à un seul endroit ; la CI construit les trois surfaces ensemble. Coût : une configuration de build plus exigeante.
DÉCISION
Hetzner Cloud, datacenter allemand, MinIO auto-hébergé
POURQUOI
Données de facturation de PME françaises : RGPD, hébergement européen, et un stockage objet dont je maîtrise le coût comme l'emplacement.
CONSÉQUENCE
Docker Compose aujourd'hui, chemin de montée en charge documenté jusqu'à K3s. L'exploitation est à ma charge : sauvegardes, mises à jour, supervision.
DÉCISION
OCR des bons de livraison par Google Vision, relu par l'utilisateur
POURQUOI
Les bons sont froissés, tamponnés, parfois manuscrits. Une extraction automatique acceptée sans contrôle fausserait les stocks et la facturation.
CONSÉQUENCE
L'OCR propose, l'humain valide. Deux secondes de plus par bon, et aucune écriture erronée en base.
STACK COMPLÈTE
API — MODULES
authorderssuppliersdelivery-notesinvoicesemployeessubscriptionsnotificationsstorage
outillage
Turborepo, pnpm, TypeScript
données
PostgreSQL, Prisma
état client
Zustand
intégrations
Gmail API, SMTP, Google Vision, Stripe, RevenueCat
stockage
MinIO (S3-compatible)
EXPLOITATION
Hetzner Cloud · Allemagne
RGPD, latence européenne, coût maîtrisé.
Docker Compose
API, Postgres, MinIO, reverse proxy.
Changelog tenu · EAS Build
Livraisons mobiles tracées, versions documentées.
→ K3s (documenté, non déployé)
Le palier suivant est écrit avant d'être nécessaire.
LIENS
03PWA · EN PRODUCTION · GESTION DE CLUB SPORTIF

Les Archers de Beauchamp

Une PWA qui remplace les fichiers Excel du comité directeur d'un club de tir à l'arc du Val-d'Oise, fondé en 1990. Utilisateurs réels, non techniques, sur téléphone.

RÔLE
seul développeur
UTILISATEURS
bénévoles du club
COMMITS
~121
HÉBERGEMENT
serveur du club
ÉTAT
● en production
CONTEXTE

Un club associatif fonctionne au bénévolat : le trésorier tient un classeur, le secrétaire un autre, et l'inscription aux concours départementaux se recopie à la main depuis le site de la fédération.

Le public visé n'a pas d'appétence informatique et consulte tout depuis un téléphone, souvent sur le pas de tir.

CE QUE L'OUTIL COUVRE
import des concoursinscriptionspaiementsremboursementsrelances mail journaliséesprêt de matérielbudgetRBAC 3 rôles
DÉCISIONS TECHNIQUES
Parsing du site fédéral, validation humaine obligatoire
Le texte publié par la fédération départementale est irrégulier d'un concours à l'autre. Le parseur propose, un membre du bureau relit, et rien n'entre en base sans cette relecture. Un import silencieux aurait suffi à fausser une saison d'inscriptions.
Montants en centimes entiers, jamais en flottants
Sur un budget de club, un écart d'un centime au bilan coûte une réunion. Toute la couche paiements et remboursements travaille en entiers.
Auth maison JWT (jose) + bcrypt, aucune inscription publique
Un club n'a pas besoin d'un fournisseur d'identité externe, et la liste de ses membres n'a rien à faire sur un formulaire ouvert. Les comptes sont créés par le bureau, avec trois rôles : admin, bureau, archer.
SQLite + Prisma 7, Docker sur le serveur du club
Une seule machine, un seul fichier de base : la sauvegarde est une copie, la restauration aussi. Aucun service à payer sur un budget associatif.
CAPTURE & CHARTE
Import relu puis validé avant écriture
charte du club reprise · #2a68af
STACK
web
Next.js 16 App Router, React 19, Tailwind 4
données
Prisma 7, SQLite
divers
Three.js, unpdf, nodemailer, zod
infra
Docker
04CONTRIBUTION À DEUX · BÊTA TEST · SÉCURITÉ PRÉ-PRODUCTION

Hotel Planning

Webapp de gestion du ménage pour un groupe de 10 hôtels : 12 rôles métier distincts, managers sur desktop en email / mot de passe, personnel de chambre sur mobile avec un code PIN à quatre chiffres. Projet client mené à deux développeurs.

RÔLE
sécurité + déploiement
ÉQUIPE
2 développeurs
PÉRIMÈTRE
10 hôtels · 12 rôles
CORRECTIFS
18 vulnérabilités
ÉTAT
◐ bêta test
CONTEXTE

L'application était fonctionnellement prête et sur le point d'ouvrir à des centaines de comptes répartis sur dix établissements. Deux populations très différentes s'y connectent : des managers derrière un bureau et du personnel de chambre qui ouvre l'app quinze fois par service.

Je suis intervenu sur la partie que personne ne voit dans une démo : ce qui se passe quand un utilisateur essaie d'atteindre les données d'un autre hôtel.

MON APPORT
  • Audit et durcissement avant mise en production, puis re-audit validé GO.
  • Déploiement auto-hébergé Docker + Caddy sur VPS.
  • Remise à niveau de la CI GitHub Actions.
JOURNAL DES CORRECTIFS

Pour une contribution, ce tableau remplace la section « décisions » : la vulnérabilité, la correction, la vérification.

FaiblesseCorrectionVérification
Accès aux données d'un autre hôtel (IDOR)RLS Postgres + contrôle d'appartenance côté serveurrejoué au re-audit
Rôles contournables depuis le clientRBAC vérifié à chaque requête, plus jamais à l'affichagetests e2e par rôle
Tokens PIN devinables et rejouablesTokens signés, durée de vie courte, tentatives limitéessmoke tests
Uploads non contrôlésType et taille validés, stockage privé, URL signéesrejoué au re-audit
= 18 vulnérabilités corrigéesdurcissement complet avant ouverturere-audit validé GO
CONTEXTE TECHNIQUE
web
Next.js, Supabase (RLS)
tests
Vitest, Playwright — e2e, smoke, accessibilité
i18n
personnel multilingue
infra
Docker + Caddy sur VPS, GitHub Actions
LIENS
05OUTIL BACK-END · BÊTA TEST · SANS INTERFACE À MONTRER

Amazon FBA

Un scraper de rentabilité et son extension navigateur : l'outil surveille les promos de la grande distribution et les croise avec les prix Amazon pour calculer la marge réelle d'un achat-revente, tous frais inclus.

RÔLE
seul développeur
SITES
09 couverts
EXTENSION
Firefox + Safari
COMMITS
~76
ÉTAT
◐ bêta test
CONTEXTE

L'achat-revente sur Amazon se joue à quelques euros par référence. La marge dépend de frais que personne ne calcule de tête : commission, frais FBA, emballage, expédition, imposition.

Le projet n'a rien à montrer d'esthétique. Sa valeur tient à la fiabilité de la collecte et à l'exactitude du calcul.

FRAIS MODÉLISÉS
commission
frais FBA
emballage
expédition
imposition

9 sites couverts : parapharmacie, culture et loisirs, grandes surfaces.

DÉCISIONS TECHNIQUES
DÉCISION
Extraction par attachement CDP à la session Chrome réelle de l'utilisateur
POURQUOI
DataDome et Cloudflare bloquaient le scraping statique. Plutôt que d'entrer dans une course aux proxies, l'outil travaille dans le navigateur que l'utilisateur utilise déjà, avec sa session.
CONSÉQUENCE
Collecte fiable là où l'approche précédente échouait, au prix d'une exécution locale : l'outil n'est pas un service distant, c'est un poste de travail.
DÉCISION
Découpe d'image en cellules produit avec sharp, lecture par Claude vision
POURQUOI
Une partie des promos n'existe qu'en image de prospectus : pas de DOM à lire. Découper la page en cellules donne au modèle une tâche courte et vérifiable plutôt qu'une planche entière.
CONSÉQUENCE
Un LLM en production, avec un coût par cellule connu et un contrôle de cohérence des prix avant enregistrement.
DÉCISION
Un adaptateur par site, une extension pour deux navigateurs
POURQUOI
Neuf sites, neuf structures de page. Et le calcul doit s'afficher là où l'utilisateur regarde la fiche produit, pas dans un onglet séparé.
CONSÉQUENCE
Ajouter un site coûte un adaptateur, pas une refonte. Deux chaînes de build : web-ext pour Firefox, script dédié pour Safari.
STACK
api
Node.js, Express 5, better-sqlite3
collecte
Playwright, attachement CDP, adaptateurs par site
images · ia
sharp, Claude vision
données
API Keepa
divers
Stripe, Jest, web-ext
LIENS
06PRODUIT MOBILE · PUBLIÉ SUR L'APP STORE · ACHATS IN-APP

IceBreakers

Application mobile de cartes questions pour rendez-vous amoureux : trois packs vendus en achat in-app. Publiée sur l'App Store, portage Play Store en attente.

RÔLE
seul développeur
PACKS
03 en achat in-app
COMMITS
~114
BUILDS
iOS + Android, EAS
ÉTAT
● v1.0.4 sur l'App Store
CONTEXTE & DÉCISIONS

Un jeu de cartes n'a pas de difficulté technique visible. La difficulté est ailleurs : monétiser sans serveur de paiement, et passer deux comités de validation avec un contenu pour adultes.

Achats in-app par RevenueCat plutôt qu'un backend de paiement
Un seul catalogue pour iOS et Android, restauration d'achat et gestion des reçus incluses. Aucun serveur de paiement à tenir pour une app à trois packs.
Contenu segmenté en trois packs
La classification des stores et les attentes des joueurs ne sont pas les mêmes selon l'intensité des questions. Trois packs, trois dossiers de soumission, une seule base de contenu.
Publicité limitée au pack gratuit
Google Mobile Ads finance l'acquisition sans mur payant à l'entrée ; l'achat d'un pack supprime les annonces, ce qui rend la conversion lisible.
CAPTURES
Tirage d'une carte
Choix du pack
STACK & LIENS
mobile
React Native 0.81, Expo 54, EAS Build
services
Supabase, RevenueCat, Google Mobile Ads
identité
Apple Sign-in, expo-notifications
LE GABARIT

Quatre blocs sont obligatoires — en-tête chiffré, contexte, décisions, liens. Les autres s’allument selon la matière : surfaces pour une plateforme, parcours pour un produit mobile, journal des correctifs pour une contribution, frais et couverture pour un outil sans interface.