Case study di architettura / Booka

Booka: cinque applicazioni, un solo modello dati.

Booka è una piattaforma multi-tenant per le attività che lavorano su appuntamento, a partire da saloni e barbieri. Non è un marketplace: nessuna attività viene mostrata accanto ai concorrenti. È il sistema su cui un'attività gestisce la giornata, con un sito pubblico dove i clienti prenotano, un gestionale web, una console superadmin e due app mobile, una per lo staff e una per i clienti.

Il mio contributo
Le tre applicazioni web e, insieme a Giulio, il database
Proprietà
Venture condivisa con Giulio
Forma
Turborepo con tre app Next.js e due Expo, repository separato per il database
Stato
In produzione
01

Il requisito architetturale

Le cinque applicazioni non hanno la stessa velocità né gli stessi utenti. Il sito pubblico cambia con il marketing e il lancio. Il gestionale segue le richieste dei saloni: agenda, clienti, staff, cassa, magazzino, report, campagne, abbonamento. La console superadmin cambia di rado e non deve mai rompersi. Le app mobile passano dalla revisione degli store, quindi un rilascio lì richiede giorni, non minuti.

Descrivono però tutte lo stesso mondo: la stessa attività, la stessa sede, lo stesso cliente, lo stesso appuntamento. Un cliente può appartenere a più sedi della stessa attività, le note sono per sede, i consensi per attività. Separare le applicazioni era necessario. Separare i dati avrebbe voluto dire cinque versioni di ogni regola.

L'obiettivo era quindi uno: lasciare che cinque prodotti evolvano con i loro tempi, mantenendo una sola verità su attività, persone e appuntamenti.

02

Le opzioni architetturali

Abbiamo confrontato tre configurazioni rispetto a indipendenza dei rilasci, coerenza dei dati, sicurezza e costo di manutenzione.

  1. Un repository per app

    Ogni applicazione ha il suo codice e la sua pipeline, e tutte parlano con lo stesso database.

    Autenticazione, accesso ai dati, tipi di dominio e design system verrebbero scritti cinque volte e divergerebbero in pochi mesi. Ogni modifica allo schema diventerebbe un rilascio da coordinare in cinque punti, senza sapere quale copia di una regola è quella giusta.

    Scartata: massima indipendenza, pagata con l'unica cosa che doveva restare condivisa.

  2. Un'unica applicazione web

    Un solo deploy che mostra un'interfaccia diversa a seconda di chi ha fatto accesso, con le app mobile a parte.

    Sito pubblico e console superadmin condividerebbero bundle, ciclo di rilascio e raggio di impatto: una modifica di marketing potrebbe fermare lo strumento che serve a ripararla, e le pagine pubbliche conterrebbero codice riservato agli amministratori.

    Scartata: utenti con profili di rischio diversi non stanno nello stesso rilascio.

  3. Monorepo e repository canonico del database

    Un repository per le cinque applicazioni e i pacchetti condivisi, ciascuna rilasciata separatamente. Un repository separato che possiede il database: migration, RLS, RPC ed Edge Function.

    I confini vanno fatti rispettare, non dati per scontati. I pacchetti condivisi hanno bisogno di un proprietario, la pipeline deve sapere quale app è cambiata, e ogni modifica che tocca i dati aspetta la migration nell'altro repository.

    Scelta: i dati restano unici, i rilasci no.

03

Architettura implementata

Un unico Turborepo contiene le tre applicazioni Next.js che ho costruito io, cioè sito pubblico, gestionale e console superadmin, e le due app Expo realizzate da Giulio. Condividono pacchetti per tipi di dominio, autenticazione, client API, design system, feature flag e traduzioni, così un concetto si definisce una volta e ogni app lo legge allo stesso modo.

Il database vive in un repository separato, che è la fonte canonica per migration, policy RLS, RPC, trigger ed Edge Function. L'abbiamo progettato insieme. È uno schema condiviso con l'identificativo dell'attività su ogni riga e le RLS sopra, e le operazioni più delicate non si fidano del client: creare e modificare un appuntamento passa da RPC, e lo staff raggiunge i dati dei clienti tramite funzioni operative che rispettano ruolo e sedi assegnate, mai con una lettura diretta della tabella.

Alcune parti sono pronte ma tenute volutamente fuori dalla promessa. I documenti fiscali, per esempio, esistono nello schema dietro un flag e restano fuori dall'MVP finché non sono validati.

04

Benefici operativi

Un rilascio web non aspetta la revisione degli store, e un rilascio mobile non si porta dietro il gestionale, perché sono unità di deploy diverse.

Una modifica allo schema si scrive una volta, in un solo repository, e i tipi generati arrivano a ogni app dallo stesso pacchetto. C'è un database, non cinque che vanno d'accordo nei giorni buoni.

Le regole su chi può vedere cosa sono applicate dove stanno i dati. Un'app con un bug può mostrare la schermata sbagliata, ma non può leggere un cliente che il database non le darebbe.

Serve una decisione architetturale simile?

Lavoro su prodotti che devono separare applicazioni, utenti o cicli di rilascio senza perdere coerenza nei dati e nella gestione operativa.

hello@robertodrago.dev