Komvos Connect
Lead Developer
Self-hosted πλατφόρμα κρατήσεων: ένα script tag σε οποιοδήποτε website και έχεις διαθεσιμότητα, calendar sync και επιβεβαιώσεις. Αντικαθιστά το Calendly και παρόμοια SaaS για ιατρεία, κομμωτήρια και service providers.
Αποτελέσματα
- script tag για κρατήσεις σε οποιοδήποτε site
- 1
- αρχεία ελέγχων πριν από κάθε αλλαγή
- 385
- ημερολόγια που μένουν συγχρονισμένα, Google και Outlook
- 2

Η κατάσταση
Οι μικρές επιχειρήσεις που δουλεύουν με ραντεβού, ιατρεία, κομμωτήρια και γραφεία υπηρεσιών, πληρώνουν συνήθως ανά χρήστη τον μήνα για ένα ημερολόγιο σε ξένο μηχάνημα. Ήθελα να δω αν η ίδια δουλειά γίνεται με ένα σύστημα που τρέχει σε δικό μου server και μπαίνει σε οποιοδήποτε site, χωρίς να ξαναχτιστεί το site. Το Komvos Connect είναι αυτό: το σχεδίασα και το έχτισα μόνος μου και είναι σε παραγωγή.
Κρατήσεις πάνω στο site που έχουν ήδη
Η επιχείρηση δεν αλλάζει site και δεν στέλνει τον πελάτη της αλλού. Βάζει μία γραμμή στη σελίδα της και εμφανίζεται το ημερολόγιο με τις ελεύθερες ώρες, στα δικά της χρώματα.
Ο επισκέπτης διαλέγει υπηρεσία, μέρα και ώρα και παίρνει επιβεβαίωση με email, χωρίς λογαριασμό και χωρίς να φύγει από τη σελίδα.

Πώς λειτουργεί
- Widget: ένα bundle σε vanilla JavaScript που μπαίνει με ένα μόνο
<script>tag, γιατί οι tenants το βάζουν σε sites τρίτων όπου δεν μπορώ να υποθέσω React ή Vue. - Ρύθμιση από το markup: προσκολλάται σε ένα κενό
divκαι διαβάζει από τα data attributes του τον tenant, το δημόσιο κλειδί και το χρώμα τόνου, οπότε κανένα μυστικό δεν φτάνει στον περιηγητή. - API: Fastify 5 σε Node 22, με Zod validation σε κάθε είσοδο και Turnstile στο widget πίσω από έλεγχο συναίνεσης.
- Ουρές: ξεχωριστός worker με BullMQ σε Redis για τα emails επιβεβαίωσης και τη λήξη των προσωρινών κρατήσεων, ώστε το HTTP request να μη περιμένει ποτέ mail server.
Ένα ημερολόγιο, όχι δύο
Το προσωπικό δεν κρατάει δεύτερο ημερολόγιο για τις κρατήσεις. Συνδέει μία φορά το Google ή το Outlook του, και οι ώρες που είναι ήδη πιασμένες εκεί παύουν να εμφανίζονται ως ελεύθερες.
Κάθε επαγγελματίας έχει δικό του ωράριο, δικές του εξαιρέσεις και δικές του υπηρεσίες, οπότε δύο συνάδελφοι στον ίδιο χώρο δεν δουλεύουν αναγκαστικά τις ίδιες ώρες.

Πώς λειτουργεί
- OAuth ανά επαγγελματία: Google και Outlook, με τα διαπιστευτήρια αποθηκευμένα ανά provider και ανά tenant.
- Ένας μόνο loader για τις πιασμένες ώρες: κάθε αναγνώστης και κάθε εγγραφή περνάει από την ίδια συνάρτηση, ώστε μια νέα πηγή απασχόλησης να έχει ακριβώς ένα σημείο εισαγωγής.
- Admin SPA: React 19 με TanStack Router, Query και Table, και Better Auth για τη σύνδεση.
- Ρυθμίσεις ανά πελάτη: SMTP, γλώσσα, ζώνη ώρας και branding ζουν στη γραμμή του tenant, όχι σε μεταβλητές περιβάλλοντος. Το admin, τα emails και οι σελίδες διαχείρισης κράτησης έχουν ξεχωριστό λεξικό ανά γλώσσα.
Η ώρα που βλέπει ο πελάτης είναι η σωστή

Η κράτηση γίνεται με τον ίδιο τρόπο στο κινητό και στον υπολογιστή: υπηρεσία, μέρα, ώρα, επιβεβαίωση. Ο επισκέπτης μπορεί να βρίσκεται σε άλλη χώρα από το ιατρείο, και η αλλαγή της θερινής ώρας μπορεί να πέσει ανάμεσα στη στιγμή της κράτησης και στη μέρα του ραντεβού.
Πώς λειτουργεί
- Αποθήκευση σε UTC, αλλά ο υπολογισμός της διαθεσιμότητας γίνεται πάντα στη ζώνη ώρας του επαγγελματία με date-fns/tz, όχι του επισκέπτη, και μετατρέπεται πίσω για την εμφάνιση.
- Δοκιμές με πραγματικές ημερομηνίες αλλαγής ώρας για
Europe/AthensκαιEurope/London, ώστε το σφάλμα να πιάνεται στο CI και όχι τον Οκτώβριο. - Προσωρινό κράτημα: η ώρα δεσμεύεται όσο ο επισκέπτης συμπληρώνει τα στοιχεία του και ελευθερώνεται από τον worker αν δεν ολοκληρώσει.
- Πώς χωρίζονται τα 385 αρχεία ελέγχων: 219 unit για τη λογική και τα components του admin, 159 integration που ανεβάζουν πραγματική PostgreSQL σε container με Testcontainers αντί για mocks, και 7 Playwright specs.
Τα δεδομένα κάθε επιχείρησης μένουν δικά της
Στο ίδιο σύστημα ζουν πολλές επιχειρήσεις, και καμία δεν πρέπει να μπορεί να δει τα ραντεβού μιας άλλης. Αυτό δεν είναι θέμα προσοχής, είναι θέμα κατασκευής.
Πώς λειτουργεί
- Απομόνωση σε επίπεδο γραμμής:
tenant_idσε κάθε πίνακα δεδομένων, και 24 από τα 31 αρχεία του σχήματος το φέρουν. - Πρόσβαση μέσω scoped accessors αντί από ελεύθερα ερωτήματα που θα μπορούσαν να ξεχάσουν το φίλτρο.
- Αναγνωριστικά με πρόθεμα: nanoid με πρόθεμα ανά τύπο, ώστε στα logs ένα
booking_7kRt3mνα διαβάζεται αμέσως ως κράτηση. - Βάση και deployment: PostgreSQL 16 με Drizzle και 34 migrations ως σήμερα, με deploy μέσω Coolify και multi-stage Docker build.
Σύνδεσμοι
- Repo:
jimrarras/multi-tenant-calendar(private)
Παρόμοια έργα
- TaskFlow: άλλο multi-tenant SaaS με real-time και offline-first, αλλά για task dispatch αντί για bookings
- Heartbeat Pharmacy PIM: άλλο production system με Better Auth και Coolify deployment