Return to projects
Project deep dive· Active development·

DayBoard

WhatsApp-first multi-tenant operations platform for service businesses

An actively developed service-business platform combining secure owner authentication, tenant-isolated .NET APIs, a durable WhatsApp booking engine, operational dashboards, scheduling, POS, reminders, analytics, payroll, waitlists, and inventory.

ASP.NET Core
Next.js
React
TypeScript
PostgreSQL
Meta WhatsApp
Docker
ASP.NET CoreNext.jsReactTypeScriptPostgreSQL
DayBoard project cover
Project frame

DayBoard began as a salon booking idea and evolved into a broader question: how can one platform support the operational workflow of different appointment-based businesses without weakening tenant isolation or filling the backend with niche-specific concepts?

The current repository is an active, end-to-end platform rather than only an interface prototype. It includes secure owner accounts, business setup, service and staff management, a durable WhatsApp booking flow, customer conversations, calendar operations, point-of-sale closeout, reminders, payroll reporting, analytics, waitlists, inventory, and an intentionally honest billing foundation.

The first product language is still salon-specific—clients, stylists, services, and appointments—but the persisted domain uses reusable service-business vocabulary.

Current implementation

The implemented product surface now includes:

  • verified-email registration, Google sign-in, secure cookie sessions, and owner membership resolution;
  • business settings, weekly hours, scheduling defaults, services, staff skills, staff schedules, and client CRM records;
  • encrypted tenant-specific Meta credentials and WhatsApp automation readiness checks;
  • a signed, durable, idempotent Meta webhook ingestion pipeline with retry processing;
  • a persisted booking state machine that selects services and staff, validates working hours, prevents conflicts, and creates appointments;
  • a live WhatsApp inbox using server-sent events, bot-to-owner handoff, owner replies, and linked booking context;
  • a timezone-aware staff calendar with conflict-checked manual appointment creation;
  • a real-data daily overview covering appointments, revenue, utilization, automation, reminders, and owner exceptions;
  • POS closeout with durable payment records and WhatsApp receipt templates;
  • configurable reminder scheduling with delivery and read reconciliation;
  • weekly commission payroll, historical analytics, waitlists, inventory, and a read-only billing overview;
  • backend tests and CI gates for audit, formatting, tests, linting, type checking, production builds, and container verification.

The project remains under active development. Employee accounts, production Row Level Security, full billing subscriptions, broad calendar rescheduling, and several premium workflows remain planned rather than presented as complete.

Architecture

The backend follows a compact Clean Architecture split:

LayerResponsibility
SalonSaaS.ApiHTTP routing, authenticated controllers, middleware, webhooks, rate limits, and dependency registration
SalonSaaS.CoreProvider-independent entities, contracts, normalization, and business rules
SalonSaaS.InfrastructureEF Core, PostgreSQL migrations, tenant filters, background processing, and external provider implementations
Next.js operations dashboard
          |
authenticated API client
          |
ASP.NET Core policies + tenant resolver
          |
domain workflows + background workers
          |
PlatformDbContext + PostgreSQL
          |
Meta WhatsApp Cloud API

The Next.js App Router frontend uses configurable industry labels. It can say Stylist in the salon experience while the API and database continue to reason about a StaffMember.

As orchestration grows, the design reserves a dedicated Application layer for complex use cases. The goal is to prevent controllers from becoming the booking, payment, reminder, or availability engines.

A reusable domain with a specific product experience

The domain deliberately separates presentation language from persisted meaning:

Generic recordSalon presentation
BusinessSalon
CustomerClient
Staff memberStylist
ServiceHaircut, facial, colouring, or another offering
AppointmentConfirmed calendar slot
BookingRequest or in-progress conversational flow

Booking and Appointment are separate because a WhatsApp conversation is incomplete for much of its life. A request may still be collecting a service, preferred staff member, date, or confirmation. Keeping that state out of the confirmed calendar prevents partial conversations from becoming operational commitments.

The model also leaves room for clinics, barbershops, repair centres, and other appointment-led businesses to reuse the same infrastructure with different labels and strategies.

Tenant isolation and owner identity

The browser never chooses the tenant for a protected request. ASP.NET Core Identity owns password hashes, confirmation and reset tokens, Google logins, lockout state, and the secure HttpOnly session cookie. The API resolves the active business through the authenticated owner membership.

Tenant isolation is reinforced at several boundaries:

  1. authenticated owner capability policies protect management routes;
  2. request middleware resolves the business from server-side membership;
  3. EF Core global query filters constrain tenant-owned records;
  4. database indexes and uniqueness rules include tenant scope where required;
  5. unsafe cookie-authenticated requests require antiforgery protection;
  6. Meta Phone Number IDs map inbound traffic to one business before workflow processing.

This is stronger than trusting an X-Tenant-Id supplied by a dashboard, but production still needs PostgreSQL Row Level Security and composite tenant foreign keys as defence in depth.

Durable WhatsApp booking engine

The webhook boundary treats provider delivery as an asynchronous distributed workflow rather than a controller callback.

Meta delivery
  -> transport-size limit
  -> signature verification before JSON parsing
  -> durable idempotent receipt
  -> tenant routing by receiving Phone Number ID
  -> bounded background processing with retries
  -> persisted conversation and booking transition
  -> conflict-checked appointment creation
  -> outbound confirmation and status reconciliation

Batched deliveries are split by receiving Phone Number ID so one tenant's messages cannot be processed inside another tenant's scope. Automatic customer creation, durable delivery states, retry recovery, and conversation persistence allow a temporary failure to be retried without replaying successful work blindly.

The bot selects an industry strategy from the business type. Terms such as stylist, provider, technician, visit, and service slot can change while services, assignments, and availability remain database-driven.

Daily operations beyond the chatbot

The platform does not stop after creating an appointment. Confirmed bookings flow into operational tools:

  • the daily overview calculates booked and collected revenue, utilization, bot resolution, reminder outcomes, and owner actions;
  • the calendar renders business-local dates in staff columns and enforces hours, assignments, and overlap rules;
  • POS records one durable payment closeout per appointment and can initiate a utility-template receipt;
  • reminders use tenant-configured timing, durable dispatch records, retry recovery, and provider delivery updates;
  • the inbox streams conversation changes and allows an owner to pause automation, reply, and return control to the bot.

Conflict prevention is enforced transactionally rather than only through disabled calendar buttons. This matters because appointments can enter through both the dashboard and concurrent WhatsApp conversations.

Business operations and growth foundations

Later slices expanded the same tenant-aware foundation:

Payroll and analytics

Weekly commission payroll uses per-staff rates, immutable closeout snapshots, exception review, and spreadsheet-safe CSV exports. Historical analytics use business-local date ranges and comparison periods for revenue, outcomes, sources, services, staff, and operational rates.

Waitlist and inventory

Waitlists track customer demand and support time-limited slot offers when cancellations create availability. Inventory handles retail and operational supplies, CSV onboarding, low-stock signals, sales, and an append-only stock ledger.

Billing boundary

The Billing page currently reports business-local WhatsApp activity and clearly states that subscriptions are not configured. There is no fabricated plan, allowance, charge, Stripe session, or entitlement state. A complete hosted Customer Portal and webhook projection architecture is documented, but it will remain disabled until package, pricing, tax, lifecycle, usage, and grace-period decisions are approved.

Security and delivery work

The current security review covers more than authentication:

  • Meta signatures are verified before payload parsing and webhook bodies have explicit limits;
  • redirect paths reject external, credential-bearing, control-character, and backslash-normalized values;
  • containers run as non-root users and exclude local settings, source files, build caches, and secrets;
  • frontend responses set clickjacking, MIME-sniffing, referrer, permission, HSTS, and baseline CSP protections;
  • SSE reconnections use capped exponential backoff with jitter;
  • CI uses least-privilege permissions, immutable action references, audit gates, timeouts, and container checks.

The reviewed build reported clean dependency audits, passing backend tests, frontend security tests, linting, type checking, and production builds. Remaining scale risks—such as database-backed worker leasing, PostgreSQL integration tests, payload retention, and large-list virtualization—are documented instead of being hidden.

Engineering challenges

Making tenant mistakes difficult

Tenant isolation cannot depend on every query author remembering a Where clause. Moving scope into membership resolution, EF query filters, provider routing, and database constraints makes the safe path the normal path.

Preventing concurrent double-booking

Availability shown to a user can become stale before confirmation. The workflow revalidates service, staff, business hours, and overlaps inside the write path, using serializable conflict checks where the appointment becomes durable.

Keeping asynchronous delivery idempotent

Meta can retry, batch, reorder, or delay events. Durable receipts, unique provider identifiers, persisted processing state, bounded retries, and delivery reconciliation are necessary to make repeated delivery safe.

Staying generic without losing product clarity

An abstract platform can become difficult to use, while a salon-only schema becomes difficult to reuse. Generic domain entities plus configurable interface labels and booking strategies allow the product to remain concrete for salon owners without encoding one niche into every table.

Being honest about implementation boundaries

The project contains ambitious plans for subscriptions, employee permissions, and premium automation. Keeping incomplete capabilities disabled—and documenting exactly what is missing—prevents a polished dashboard from being mistaken for a production guarantee.

What I learned

DayBoard has become my deepest exercise in connecting product decisions with system boundaries.

The project reinforced that multi-tenancy, identity, idempotency, time zones, and conflict prevention must be designed into the first trustworthy workflow. Adding them after automation begins writing customer and appointment data would be far more expensive.

It also showed why operational software cannot end at a successful API response. A real booking crosses conversations, provider delivery, background work, availability, appointments, reminders, payment closeout, reporting, and human intervention. Each transition needs an owner, a durable state, and a recovery path.

The next phase is less about adding visible pages and more about strengthening the production boundary: database-level isolation, integration coverage, worker leasing, employee authorization, deployment observability, and a billing model grounded in approved product rules.