Royal Glow internal docs · now fully interactive — Steps, API tables, file trees & live status
Royal Glow Docs
Features

Notifications

How Royal Glow keeps customers and staff informed — browser push notifications, transactional and marketing email, the admin notification bell, and customer preferences.

Notifications

Notifications are how Royal Glow tells people what's happening — a customer that their booking is confirmed, a staff member that their leave was approved, an owner that the day's summary is ready. There are two channels: browser push notifications and email. This page explains both, what gets sent, and how customers control what reaches them.

Push and email are separate channels with separate switches. A customer can turn off push reminders but still receive their invoice by email, because some emails are transactional and always sent.

What it is

Two delivery channels working together:

  • Web Push — native browser notifications that work even when the site isn't open, delivered through a service worker.
  • Email — sent through two services: Resend for transactional mail (confirmations, invoices, reminders) and Brevo for marketing mail (follow-ups, promotions, re-engagement).

How it works — web push

Push notifications follow a four-stage flow:

Permission

The browser's permission prompt is shown at a considered moment (after the customer's first successful booking, not on first load). The customer can grant, deny, or dismiss it.

Subscribe

Once granted, the service worker subscribes with the VAPID public key and produces a subscription object.

Store

The subscription (endpoint and keys) is saved to the push_subscription table against the user via POST /api/push/subscribe.

Send

When an event occurs, the server looks up the user's subscription(s) and sends the notification through the push service, which the service worker displays.

What gets pushed

TypeSent whenOpens
booking_confirmedA receptionist approves a bookingThe booking detail
reminder_24h24 hours before the appointmentThe booking detail
reminder_1h1 hour before the appointmentGoogle Maps directions
booking_rescheduledA booking is movedThe booking detail
booking_rejectedA booking is rejectedA new booking
gems_earnedAn invoice awards gemsThe gems catalogue
staff_changedA booking is reassigned to new staffThe booking detail

How it works — email

Email is split across two services for good reasons — instant one-to-one delivery and bulk sending are different problems.

  • Use for: welcome emails, booking confirmations, invoices, reminders.
  • Why: built for instant, reliable one-to-one delivery, with first-class PDF attachment support for invoices.
  • Always sent: transactional emails are essential records and cannot be fully disabled.
  • From: [email protected].
  • Use for: post-service follow-ups, promotions, seasonal offers, re-engagement, renewal nudges.
  • Why: built for bulk sending, with automatic unsubscribe management.
  • Consent required: only customers who ticked the marketing consent box at onboarding are added to Brevo lists.
  • Legally bound: every marketing email carries an unsubscribe link (CAN-SPAM, GDPR, India DPDP Act).

Because sign-in is Google OAuth only, the salon sends zero auth emails — no password resets, no magic links. Every email is a business event handled by application code.

Email triggers

A sample of the transactional emails and what fires them:

TriggerTemplateRecipient
Booking confirmedbooking-approved.tsxCustomer
Booking rejectedbooking-rejected.tsxCustomer
Appointment reminder (24h / 1h)appointment-reminder.tsxCustomer
Invoice generatedinvoice-service.tsxCustomer (+ PDF)
Membership createdinvoice-membership-purchase.tsxCustomer (+ PDF)
Membership session recordedinvoice-membership-session.tsxCustomer (+ PDF)
Membership expiry (30d / 7d / 1d)membership-expiry-reminder.tsxCustomer
Leave approved / rejectedleave-approved.tsx / leave-rejected.tsxStaff member
Daily summarydaily-summary.tsxOwner / Manager

How it works — the notification bell

Inside the admin portal, a bell icon in the header shows unread notifications with a count badge (capped at "9+"). Clicking it opens a dropdown listing recent events — new bookings, stale leads, leave requests, completed bookings, the daily summary — with unread items marked. New notifications arrive live over the admin:notifications Ably channel, and the bell gives a small bounce as the count ticks up.

The bell and other live updates are powered by Ably channels. See Realtime for the full channel list and connection lifecycle.

Customer preferences

On /profile, a customer controls both channels independently. They can enable or disable browser push entirely, then fine-tune categories (booking confirmations, reminders, changes, gems, membership alerts, offers) for push and for email separately.

Invoice receipts and booking confirmations cannot be fully disabled by email — they are transactional. For those categories the toggle only controls the push notification, not the email record.

Reminder scheduling

When a booking is confirmed, reminders are scheduled with QStash based on how far away the appointment is:

When QStash fires the job, the server verifies the request signature, re-checks that the booking is still confirmed (skipping cancelled ones), checks the customer's preferences, and then sends the push and/or email accordingly.

OpenReport an issue

Was this page helpful?

On this page