Proporio — SaaS Angular & Google Cloud

Gestion locative assistée par IA pour propriétaires belges : baux, quittances, interventions, prestataires et calculateurs de rentabilité.

Proporio — SaaS Angular & Google Cloud
Rôle
CTO
Stack
Angular 22 · Firebase · Cloud Functions
Marché
Belgique, trois régions
Statut
En ligne

Contexte

Un bailleur belge reçoit son travail de partout : e-mails de locataires, messages WhatsApp, mouvements bancaires, échéances de bail, indexations et obligations légales qui changent selon la région. C’est à lui d’aller chercher ce qu’il doit faire. Proporio part du principe inverse : le bailleur ne devrait jamais avoir à chercher le travail.

Défi métier

Donner aux propriétaires un cockpit unique là où cohabitaient tableurs, e-mails et courriers.

Solution

Chaque entrée — un e-mail, un message, un paiement, une échéance — devient une carte d’action dans un fil unique, le Cockpit. Un modèle de langage classe le message, retrouve le bien et le bail concernés et rédige l’action ; le bailleur relit, corrige si besoin et valide. Le produit est multi-espaces : bailleur, locataire, prestataire, syndic et agence ont chacun le leur, et les données passent d’un espace à l’autre par projection, jamais par des droits croisés.

Résultat

En production depuis juin 2026, en quatre langues, avec 96 scénarios de cartes, 17 exécuteurs d’effets, un rapprochement bancaire en open banking et un assistant qui dispose de 63 outils. Le droit belge est modélisé : 14 types de bail, règles par région, indexation sur l’indice santé.

Mon rôle

CTO

Architecture

Utilisateurs

  • SPA / PWA Angular
  • E-mails entrants
  • WhatsApp
  • Banques (open banking)

Application

  • Firebase Hosting · Auth · App Check
  • Cloud Firestore
  • Cloud Functions Gen2 · europe-west1
  • Cloud Scheduler : 38 tâches
  • Cloud Storage · KMS · Secret Manager
  • BigQuery

Services externes

  • OpenRouter (Claude, GPT, Gemini, Mistral…)
  • SendGrid · MJML
  • WhatsApp Cloud API
  • Bridge · Exthand (open banking)
  • Stripe · Stripe Tax
  • Sentry · PostHog

Le parcours, étape par étape

  1. Réception

    Un e-mail arrive sur l’adresse de l’espace. SendGrid Inbound Parse le transmet à une fonction HTTP protégée par un secret de chemin et une liste d’adresses autorisées.

  2. Classement

    Le message est enregistré ; un trigger Firestore lance la classification en deux niveaux — domaine, puis sous-type — via la passerelle OpenRouter.

  3. Rattachement

    L’expéditeur est identifié, le bien et le bail sont retrouvés, et le registre de scénarios choisit le traitement le plus adapté.

  4. Carte d’action

    Le résumé est traduit en quatre langues, une réponse est rédigée, et la carte rejoint le Cockpit, en attente ou planifiée.

  5. Validation

    Le bailleur édite et valide. Le registre d’exécuteurs applique chaque effet : réponse, intervention, rappel de paiement…

  6. Envoi et audit

    Toutes les cinq minutes, les brouillons planifiés partent par SendGrid ; chaque action laisse une trace d’audit.

Modèle de données

Les entités principales, leurs champs clés et leurs relations.

Workspace

  • type (8 types d’espace)
  • members{uid: role}
  • subscription
  • onboarding
  • 1—n Property
  • 1—n Tenant
  • 1—n ActionCard

Property

  • buildingUID
  • keys (sous-collection)
  • meters (sous-collection)
  • 1—n Contract
  • 1—n Intervention
  • 1—n Loan · Expense

Contract

  • propertyUID
  • tenantIds[]
  • type de bail belge
  • loyer · garantie
  • n—n Tenant
  • 1—n PlannedPayment
  • 1—n PlannedIndexation

Tenant

  • identité
  • coordonnées
  • langue
  • n—n Contract

InboundMessage

  • source (e-mail, WhatsApp)
  • expéditeur
  • contenu
  • 1—n ActionCard

ActionCard

  • source · intent · domain
  • priority · status
  • trustTier
  • résumé en 4 langues
  • 1—0..1 MailDraft

BankTransaction

  • connexion bancaire
  • montant · communication
  • statut de rapprochement
  • n—0..1 PlannedPayment

Fiche technique complète

Langages
TypeScript 6 (front), TypeScript 5.7 (fonctions)
Front
Angular 22, Angular Material et CDK, Tailwind 3
Back-end
Cloud Functions Gen2 sur Node 24, région europe-west1, validation zod 4
Base de données
Cloud Firestore, données rangées par espace (workspaces/{id}/…)
Authentification
Firebase Auth (e-mail, Google), custom claims, App Check reCAPTCHA v3
Paiement
Stripe : abonnements par bien, par siège et par lot, Stripe Tax
Tâches planifiées
38 jobs Cloud Scheduler, fuseau Europe/Brussels
Temps réel
Écouteurs Firestore onSnapshot
IA
Passerelle unique OpenRouter : classification, rédaction, traduction, import de contrats, assistant à 63 outils
Messagerie
SendGrid et MJML, WhatsApp Cloud API, notifications push FCM
Banque
Open banking via Bridge et Exthand, sessions scellées par Cloud KMS
CI/CD
21 workflows GitHub Actions, déploiement automatique de l’environnement de développement
Tests
Karma et Jasmine (820 specs), Jest 30 (506 tests), règles Firestore testées, Playwright
Qualité
ESLint 10, Prettier, « ratchets » de qualité, CodeQL, Gitleaks
Observabilité
Sentry (front et fonctions), PostHog, export BigQuery, événements de santé système
Langues
Français, néerlandais, allemand et anglais (ngx-translate)
Sécurité et RGPD
Règles Firestore en refus par défaut, webhooks signés HMAC, scan DAST, journal des consentements, suppression en cascade, rétention planifiée

Fonctionnalités clés

  • Cockpit

    96 scénarios et 17 exécuteurs d’effets ; un balayage quotidien fait remonter les échéances.

  • Cycle de vie du bail

    Création guidée ou import par IA, indexation sur l’indice santé, état des lieux, résiliation.

  • Rapprochement bancaire

    Correspondance automatique au-delà d’une confiance de 0,9 ; en dessous, une carte de revue.

  • Interventions

    Réparations, entretiens, devis et prestataires.

  • Portails dédiés

    Locataire (PWA), prestataire, syndic avec assemblées générales, agence avec CRM et mandats.

  • Assistant

    63 outils ; ceux qui modifient des données demandent une confirmation explicite.

Problèmes résolus

  1. Mémoire au démarrage à froid

    ProblèmeChaque fonction chargeait tout le bundle, environ 243 Mio en mémoire : plus de 500 requêtes ont été coupées par la limite de 256 Mio.

    SolutionPlancher mémoire global à 512 Mio, documenté à l’endroit où les fonctions sont exportées.

  2. Trigger rejoué

    ProblèmeLes triggers Gen2 sont livrés « au moins une fois » : une demande de réparation créait parfois deux interventions.

    SolutionIdentifiant de carte dérivé de l’identifiant d’événement, et create() au lieu de set() : le second passage échoue proprement.

  3. Jour UTC contre jour bruxellois

    ProblèmeLes clés d’idempotence étaient calculées en jour UTC alors que les crons tournent à l’heure de Bruxelles.

    SolutionCalcul de la date en Europe/Brussels avec Intl.DateTimeFormat, tests sur les changements d’heure.

  4. Course d’état côté front

    ProblèmeLe rechargement d’une liste écrasait une modification locale pas encore confirmée par Firestore.

    SolutionSuivi des écritures en attente avec une durée de vie de 30 secondes.

  5. Webhook entrant durci

    ProblèmeLa liste d’adresses autorisées de SendGrid ne faisait que journaliser les appels inconnus.

    SolutionAprès six mois de journaux sans faux positif, les appels inconnus sont rejetés (403).

Choix techniques

Choix Pourquoi
Une seule passerelle LLM Changer de modèle par tâche sans redéployer, suivre les coûts dans un registre et typer les erreurs.
Projections plutôt que droits croisés Un tiers ne lit jamais les documents d’un autre espace ; révoquer le lien coupe la projection.
Secrets bancaires à part, scellés par KMS Les règles Firestore s’appliquent au document entier : les secrets vivent dans une collection séparée.
Preuve de possession du numéro WhatsApp Une faute de frappe ne doit jamais envoyer les arriérés d’un locataire à un inconnu.

Chronologie

  1. Août 2024 Premier commit
  2. Octobre 2025 Modèle multi-espaces et Stripe
  3. Avril 2026 Cockpit, première version
  4. Juin 2026 Version stable en production
  5. Juillet 2026 WhatsApp Cloud API
  6. Août 2026 Open banking pour les quatre profils

En chiffres

2 821
commits, dont 1 835 de ma main
659
Cloud Functions
1 326
fichiers de tests
4
langues

Relevé dans le code source et l’historique Git du projet le 8 octobre 2026. Aucun chiffre d’usage ou de revenu n’est publié.

Projets similaires

SaaS
janv. 2024 — présent
StreamCrea — tableau de bord des créateurs
Synchro Twitch, YouTube et Kick, publication multi-réseaux et blog pour abonnés.
PHP, Laravel, Livewire, Stripe
Voir le projet
SaaS
sept. 2023 — présent
Egonix Cards — cartes de visite NFC
Des cartes de visite NFC : on touche la carte, le contact arrive dans un espace où il s’exporte, se segmente et se relance.
Laravel, Livewire, Filament, Stripe, TailwindCSS
Voir le projet
SaaS
janv. 2024 — présent
Finnexus — projet Laravel Finance
SaaS finance entreprise : analytics, prévisions et trésorerie.
Laravel, Livewire, TailwindCSS, Stripe
Voir le projet
SaaS
janv. 2024 — présent
Discobot — la plateforme de bot Discord
Un bot Discord, six plugins configurés par serveur depuis un tableau de bord web.
Laravel, Node.js, Discord.js, Stripe
Voir le projet

Disponible pour missions PHP / Laravel / WordPress / Silverstripe en Belgique et remote EU.