In plain terms

StyleDesk is what a hair, beauty and barber business uses to stay open for bookings while the back office keeps up. Clients browse services and packages on a branded site, drop what they want into a booking bag, choose a stylist and slot, and confirm — without a phone tag chain. Staff manage appointments, clients, inventory, invoices, attendance and payroll from an admin workspace on the same backend.

An optional AI assistant on the public site answers questions about services and policies using retrieval-augmented generation: admins maintain curated knowledge, the system embeds it into PostgreSQL with pgvector, and Gemini answers with those excerpts — streamed to the browser through a Next.js proxy so provider keys never reach the client.

Why it matters commercially: salons lose money when chairs sit empty because booking is friction, and they lose trust when front desk and website disagree on availability or price. One system for discovery, scheduling and operations removes both failure modes.

The problem

A salon is not a single queue of appointments. It is services with different durations, packages that bundle them, stylists with different skills, branch or sister-concern branding, retail inventory sold at the chair, and payroll rules tied to attendance — often with biometric clocks that speak vendor protocols, not HTTP.

Bolt-on booking widgets rarely connect to inventory or payroll. Spreadsheets for hours and commissions break the moment someone works at two locations or takes leave mid-cycle. And bolting a generic chatbot onto marketing copy without grounding creates confident wrong answers — worse than no bot at all.

StyleDesk treats booking, operations and finance as one product, with AI added only where retrieval and server-side guardrails can keep answers tied to approved content.

One backend, two experiences

The NestJS API owns auth, RBAC, appointments, clients, services, packages, finance, payroll, leave, inventory, notifications, mail, reports and device integrations. The Next.js 16 frontend serves the customer-facing marketing and booking flow and a separate admin dashboard (/admin), calling the API from the browser and from server components via distinct base URLs in Docker so SSR never confuses internal and public hostnames.

That split matters for performance and security: public pages can be cached and polished while admin screens stay authoritative against live data.

Booking that matches how clients think

The public site is organised around services, packages and people, not around database tables. Clients can add multiple line items to a booking bag, adjust quantities, and only then pick stylist and time — mirroring how people actually plan a visit (cut plus colour, or a package plus an add-on).

Signed-in clients use My appointments to see upcoming visits. FAQs and footer navigation keep policy questions out of the reception phone line where possible.

Operations beyond the chair

Modules on the backend reflect a real salon operator’s week:

  • Appointments and settings — configurable rules for how booking behaves on the floor.
  • Clients and employees — roles and permissions for who sees what.
  • Finance and invoices — invoice settings and billing aligned with services sold.
  • Inventory — stock tied to retail sold during visits.
  • Attendance, leave and payroll — biometric and iClock paths ingest punches; payroll consumes the result.
  • Reports and dashboards — management visibility without exporting to spreadsheets.

The codebase documents its current shape honestly: production today is a single-business installation (one salon organisation per deploy), while AI tables carry tenant identifiers as scaffolding for a possible future hosted product — with namespace selection fixed on the server so a public chat client cannot point retrieval at someone else’s knowledge base.

Grounded AI, not a gimmick

The AI path is deliberately narrow and production-minded:

  1. Admins maintain HTML knowledge entries in /admin/ai-knowledge.
  2. The backend strips HTML to text, chunks it, batch-embeds with Gemini, and stores vectors in PostgreSQL (768 dimensions, matching the chosen embedding model).
  3. A user question embeds the same way; cosine search pulls the closest chunks within the server-resolved namespace.
  4. ChatService combines recent session history with those excerpts, labels them as untrusted reference text in the system prompt, and streams Gemini output as server-sent events.
  5. The PublicChatWidget mounts only when enabled in client env; throttling, message limits, session validation and disconnect cancellation protect the public route.

If GEMINI_API_KEY is missing, the rest of StyleDesk continues to run — AI endpoints return a clear unavailable state rather than breaking unrelated pages.

The result

  • Clients book online through a flow built for multi-service visits, not single-slot widgets.
  • Staff run the business from one admin surface tied to the same appointments and clients.
  • Attendance and payroll connect through integrations salons already use on the LAN.
  • AI answers stay tied to curated knowledge, with server-side namespace control and streaming UX.

What it demonstrates

StyleDesk is a full-stack product in TypeScript: NestJS modular boundaries, Next.js public and admin UX, PostgreSQL with pgvector for semantic search, Redis for cache and sessions, Dockerised local and production compose files, and an AI feature designed like a production subsystem — optional provider, explicit dimensionality, migration-backed vectors, and security thinking on the public chat path — rather than a demo glued onto a CRUD app.