← Retour aux projets

Bizleen Orbit

En ligne · app.bizleen.com

Bizleen Orbit (anciennement StaffClock) est l'espace de travail connecté de Bizleen : pointage, pourboires, salaires estimés, congés, planning, événements, notifications et documents, servi sur la tablette partagée de l'établissement et sur le téléphone de chaque salarié. Né pour un restaurant, il sert aujourd'hui onze verticales avec neuf modules livrés, un moteur de réservation par couverts, et un moteur de rendez-vous en construction. Un Worker Cloudflare unique : Hono 4, React 19, Drizzle, D1, R2, trois Durable Objects. En ligne sur app.bizleen.com ; le domaine historique staffclock.app reste servi.

FR EN
9 Modules livrés
11 Verticales servies
11 948 Cas de test
84 Tables en base
99 Migrations SQL
522 Points d'entrée API

Pourquoi j'ai construit ça

Un restaurant comptait ses heures sur une application lente, avec un sélecteur d'heure impossible à manier en plein coup de feu ; les pourboires par carte étaient répartis à la main et les salaires estimés au doigt mouillé. J'ai construit l'outil le 3 juin 2026 pour ce besoin précis, sous son premier nom : pointage à gros boutons, répartition automatique au centime près, salaires estimés, clôtures formelles. Une fois l'outil en place pour un établissement, je l'ai ouvert à plusieurs (superadmin, établissements, administrateurs invités par courriel), puis à onze verticales servies par des axes de comportement plutôt que par le nom du métier. Par-dessus le pointage sont venus les congés, le planning de quarts, l'événementiel, les notifications, les documents et la paie estimée : neuf modules livrés. En août 2026, le raccordement au site public Bizleen a commencé, parce qu'un mini-site sait afficher une grille de prestations mais pas dire si le créneau de mardi 15 heures est libre, et que cette information vit dans l'outil qui tient déjà le planning. L'outil est devenu Bizleen Orbit sur toutes les surfaces que le client voit : application, manifeste, courriels, logos, et le domaine app.bizleen.com. Le pont entre le site public et l'espace connecté est construit et testé des deux côtés ; sa mise en service commerciale est en cours. Le tout tourne dans un Worker Cloudflare unique, avec 252 814 lignes de test pour 211 451 lignes de production.

Décisions techniques structurantes

01
Une tablette partagée en salle, et des rôles qui la modélisent

Dans un restaurant, l'appareil qui pointe n'appartient à personne : c'est une tablette posée au passe, que tout le monde touche. Les rôles d'Orbit partent de cette réalité au lieu de la contourner. La tablette est un poste de consultation partagé ; un PIN serveur ou manager élève les droits le temps d'un geste, et cette élévation est tracée. Le téléphone de chaque salarié est son espace privé : ses heures, ses pourboires, ses congés, rien d'autre. Côté données, 74 tables sur 84 sont cloisonnées par établissement, et l'entrée du superadmin dans un établissement est tracée dans l'audit.

02
Onze verticales servies par des axes de comportement, pas par le nom du métier

Orbit ne teste jamais « si restaurant alors ». Chaque métier est décrit par des axes purs : traceur privé, primes médicales, pourboires, relevé solo, organisateur d'événements. Une verticale est une combinaison de ces axes, et ouvrir un douzième métier est un travail de configuration, pas une duplication de code. C'est ce qui a permis de passer d'un restaurant à onze verticales sans forker le moteur.

03
Des couches vérifiables et un domaine sans effet de bord

Le serveur est découpé pour que la séparation se vérifie, pas seulement se déclare : 45 fichiers de routes (21 304 lignes) qui ne portent que la validation et l'autorisation, 85 fichiers de services (47 303 lignes), 79 fichiers de domaine pur sans effet de bord, 53 repositories, et aucun repository n'importe un service. Sous cette pile, un socle d'intégration : outbox transactionnel avec bail et lettre morte, inbox de consommation, registre d'idempotence capable de rejouer la réponse d'origine, projections en lecture du catalogue publié par Bizleen. Et 52 fichiers de test rejouent les migrations SQL jusqu'à vérifier la présence des déclencheurs dans sqlite_master.

04
Trois Durable Objects, chacun pour une seule raison

Un coordinateur de réservation par établissement, qui sérialise les demandes sur une date ; un debounce des notifications de pourboires, qui regroupe les rafales avant l'envoi push ; et une garde qui refuse toute commande adressée à la mauvaise instance. Le fan-out des notifications est borné par établissement et par fenêtre de temps, pour qu'une rafale de saisies ne devienne jamais une rafale de push.

05
Un client React sans gestionnaire d'état ni bibliothèque de composants

48 écrans chargés à la demande le long des frontières de rôle, aucun gestionnaire d'état, aucune bibliothèque de composants, et un seul appel à fetch dans tout le client : toutes les requêtes passent par la même porte. Le SPA est servi en Static Assets à côté de l'API, dans le même Worker.

Le challenge non-trivial

Le moteur de rendez-vous : trois moteurs empilés, encore en construction

C'est le plus gros bloc du parc : 45 657 lignes serveur, 14 807 lignes client, 20 tables dédiées, 167 contraintes CHECK nommées, 69 déclencheurs SQL. Il empile trois moteurs. Un moteur de règles décrit une prestation en étapes ordonnées, avec des marges et, pour chaque étape, des exigences de ressource (nature, compétence, niveau, quantité). Un moteur d'allocation pose des retenues dont la durée de vie est lue à l'horloge de la base, et les résout par un solveur déterministe et borné. Un orchestrateur de commandes tourne sous un Durable Object coordinateur, une instance par établissement, et une garde refuse toute commande adressée à la mauvaise instance. Le moteur couverts, plus simple (capacité par service), est livré et sert déjà les réservations de restaurant. Le moteur de rendez-vous, lui, reste un chantier : il se présente comme tel, sans date.

Leçon retenue

Un outil construit pour un seul restaurant peut devenir l'espace connecté de onze métiers, à deux conditions que j'ai apprises ici. D'abord, les moteurs ne doivent jamais connaître le nom du métier : chaque verticale est une combinaison d'axes de comportement, et un métier de plus est de la configuration. Ensuite, une architecture en couches ne vaut que si elle se vérifie : des routes qui ne font que valider et autoriser, un domaine sans effet de bord, des repositories qui n'importent jamais un service, et des tests qui rejouent les migrations jusqu'aux déclencheurs. C'est ce qui permet d'écrire plus de lignes de test que de lignes de production (252 814 contre 211 451). Dernière leçon, plus simple : un chantier se dit comme un chantier. Le moteur de rendez-vous est en construction, et cette fiche le dit.

Fonctionnalités

⏱️
Pointage en un geste

Tablette de consultation partagée en salle, PIN serveur et PIN manager, entrées journalières, lieux de travail. Les gros boutons viennent du premier restaurant : il faut pouvoir pointer en plein coup de feu.

💶
Pourboires en 3 modes

Trois modes de répartition mémorisés jour par jour, un axe distinct pour les espèces, règlements hebdomadaires idempotents : un règlement rejoué ne paie jamais deux fois.

🧾
Salaires estimés

Calcul, exports, envois de paie programmés, clôtures mensuelles : chaque salarié voit son estimation, l'établissement clôture son mois.

🌴
Congés

Demandes, validateurs désignés par établissement, rappels automatiques quand une demande attend.

📅
Planning de quarts

Disponibilités, échanges de quarts entre salariés, patrons de repos : 7 465 lignes pour ce seul module.

🎟️
Événementiel

34 points d'entrée, pointage par QR à secret régénérable, facturation au taux horaire ou au forfait.

🔔
Notifications

Push web, Durable Object de debounce, abonnements d'appareils ; fan-out borné par établissement et par fenêtre de temps.

📄
Documents, exports, RGPD

Registre déclaratif, audit métier opposable, purge de compte à la demande.

🛠️
Superadmin

33 points d'entrée, impersonation tracée, 74 tables sur 84 cloisonnées par établissement.

🍽️
Moteur couverts

Capacité par service, sérialisation par établissement et par date : c'est lui que sert le widget de réservation partenaire de Bizleen.

🧭
Moteur de rendez-vous (en construction)

45 657 lignes serveur, 20 tables, trois moteurs empilés (règles, allocation, orchestration). Un chantier ouvert, présenté comme tel, sans date.

Stack technique

Runtime
Cloudflare Workers (Worker unique)Static Assets3 Durable Objects
Backend
Hono 4TypeScript strictZod522 points d'entrée
Données
Cloudflare D1 (SQLite)Drizzle ORM84 tables99 migrationsR2
Frontend
React 1948 écrans chargés à la demandeTailwind CSS 4Vite 8
Environnements
ProductionDémonstration isolée (base, bucket, sous-domaine et secrets propres)
Tests
252 814 lignes de test11 948 cas52 fichiers rejouant les migrations SQL