How serkanfidanci/rastamanlonge works
1. Overall shape
- This is a two-tier business system: a React/Vite frontend in the browser and a Node.js/Express backend API, backed by a single PostgreSQL 16 database.
- Deployment is containerized with Docker Compose: one app container and one Postgres container. There is no Supabase or external app server.
2. Client layer
- The frontend is a TypeScript React SPA (src/) with PWA support (sw.js, InstallPrompt.tsx, pwa.tsx), so users can install it like an app.
- The browser client handles customer booking flows, admin screens, and employee views, but all authoritative business actions are validated by the backend.
3. API / application layer
- The backend lives under server/ and is the main orchestration layer for all business rules.
- Key modules are split by concern: auth.js for JWT/bcrypt auth, db.js for Postgres access, whatsapp.js for notification transport, migrate.js and seed.js for startup database setup, and index.js as the server entrypoint.
- The backend is the boundary for booking validation, role checks, reporting, notification sending, and config management.
4. Authentication and role boundaries
- Auth is JWT-based with password hashing via bcrypt.
- The system distinguishes at least three access patterns:
- public/customer flows for booking and phone verification,
- admin flows for configuration, approvals, campaigns, and reporting,
- employee flows for seeing their own appointments and financial entries.
- The README makes clear that employees are restricted to their own records, while admins have system-wide visibility.
5. Core booking workflow
- Customers create appointments by selecting service, employee, date, and time.
- New appointments are stored as pending and later moved by admin to approved, rejected, cancelled, or completed states.
- Completion is a business event: completed appointments automatically generate revenue records in the finance ledger.
6. Finance and reporting
- Financial data is stored separately from appointments in finance_entries.
- The admin side can report on income, expenses, net profit, and employee-based performance.
- Employees can also add their own extra income/transaction records, so finance is not derived only from appointments.
7. Notification subsystem
- WhatsApp messaging is a first-class subsystem, not just a side effect.
- server/whatsapp.js abstracts provider delivery, supporting Meta WhatsApp Cloud API, a generic webhook provider, or a disabled mode.
- Every send attempt and failure is written to notification_logs, which makes notifications observable and auditable.
8. OTP and phone verification
- There is a dedicated public API for WhatsApp OTP request/verify and phone-verification checks.
- Verified phone state is remembered client-side for 180 days, but the server keeps only a hash of the verification key.
- This verification gate sits in front of the customer booking flow, so a booking cannot be created without a valid phone verification.
9. Campaign / discount engine
- Campaigns are stored and validated server-side, with rules for date, service, usage limits, and discount amount.
- Active campaigns are shown on the homepage, and booking can apply a campaign code.
- The backend re-validates the campaign at appointment creation time, so the discount used for booking is authoritative and reflected in finance records.
10. Employee scheduling and time off
- The schema includes employee_schedules, employee_timeoff, and employee_services, so availability is modeled explicitly rather than inferred.
- Hourly appointment slot logic and time-off constraints are handled in later migrations, which means scheduling is a backend-owned availability problem.
11. Persistence and schema evolution
- Database schema lives in db/migrations/ as numbered SQL migrations, starting with core tables and then adding feature slices like WhatsApp OTP, phone verification, campaigns, reminders, and campaign engine logic.
- Startup applies migrations automatically, and an initial admin account is seeded from environment variables.
- This indicates the database is the single source of truth for both operational data and system configuration.
12. Files, config, and deployment
- Employee profile photos are uploaded as files and persisted in a Docker volume, so they are separate from relational data.
- Sensitive settings such as JWT secret, encrypted WhatsApp token storage key, and provider credentials come from .env.
- The app is designed for local development and production Docker deployment, with the frontend and backend packaged together in the app container and PostgreSQL isolated in its own container.
Main entry points: db PostgreSQL · index.js API entry · App.tsx React SPA · Dockerfile App container
Components 19
Client
Browser SPA and PWA entrypoints
- React SPA · TypeScript browser app for customer, admin, and employee screens
src/App.tsx - API client · Client-side calls into the backend
src/api.ts - PWA shell · Service worker, install prompt, and PWA bootstrapping
public/sw.js - Client entry · Main frontend startup and rendering path
src/main.tsx
Server
Node.js API and business logic
- API entry · Main backend process and route orchestration
server/index.js - Auth · Login, token handling, and role checks
server/auth.js - DB access · Database connection and query access
server/db.js - WhatsApp · Provider abstraction for Cloud API, webhook, or disabled mode
server/whatsapp.js - Migrations · Applies database migrations on startup
server/migrate.js - Seed data · Creates initial admin and bootstrap data
server/seed.js
Data & Deploy
Database schema, files, and containerization
- Core schema · Appointments, users, services, finance, and notification tables
db/migrations/001_initial.sql - Scheduling schema · Service VIP, hourly slots, time off, and employee service rules
db/migrations/002_service_vip.sql - Verification schema · WhatsApp OTP and phone verification persistence
db/migrations/004_whatsapp_otp.sql - Campaign schema · Campaign storage and campaign engine rules
db/migrations/006_campaigns.sql - Reminder schema · Appointment reminder support
db/migrations/008_appointment_reminders.sql - Uploaded files · Employee profile photos stored outside the relational database
- PostgreSQL · Single source of truth for operational data and config
db - App container · Builds and runs frontend plus backend in one container
Dockerfile - DB container · Isolated PostgreSQL service in Docker Compose
docker-compose.yml
Connections 23
- Client entry → React SPA: render · Bootstraps the SPA
- React SPA → API client: calls · Uses backend endpoints for business actions
- React SPA → PWA shell: installs · Enables app-like offline/install behavior
- API client → API entry: HTTP · Sends client requests to the API
- API entry → Auth: guards · Applies authentication and role boundaries
- API entry → DB access: queries · Reads and writes application data
- API entry → WhatsApp: sends · Triggers WhatsApp delivery for OTP and business events
- API entry → Migrations: starts · Runs schema migrations during startup
- API entry → Seed data: starts · Seeds initial admin configuration
- Migrations → PostgreSQL: applies · Executes SQL migrations against PostgreSQL
- Seed data → PostgreSQL: writes · Creates initial records in PostgreSQL
- DB access → PostgreSQL: uses · Primary persistence backend
- Auth → PostgreSQL: reads · Checks users and hashes from the database
- WhatsApp → PostgreSQL: logs · Writes send attempts and failures to notification_logs
- Core schema → PostgreSQL: defines · Base relational model
- Scheduling schema → PostgreSQL: extends · Adds scheduling and availability tables
- Verification schema → PostgreSQL: extends · Adds OTP and phone verification tables
- Campaign schema → PostgreSQL: extends · Adds campaign and discount tables
- Reminder schema → PostgreSQL: extends · Adds reminder support tables
- App container → API entry: runs · Packages the application stack
- App container → React SPA: serves · Includes the browser app build
- DB container → PostgreSQL: hosts · Runs the database service
- Uploaded files → App container: mounted in · Persisted in a Docker volume attached to the app container