Appearance
Platform email inventory
This inventory covers every platform-authored email body as of August 31, 2026. It excludes campaign content written by a tenant, but includes the platform campaign shell, footer, unsubscribe controls, and tracking. Platform-authored entries provide HTML and plain text. A tenant may intentionally omit a campaign's optional plain-text body, in which case only the HTML campaign and its platform controls are delivered.
Default automation hooks
These hooks are stored per brand. Contact mail uses the customer account destination when available. Staff alerts use an authenticated CRM destination. The delivery pipeline adds a destination-specific fallback action only when the saved HTML has no concrete link.
| Group | Event | Audience | Purpose |
|---|---|---|---|
| Customer | customer_signed_up_via_widget | Customer | Confirm account creation |
| Customer | customer_birthday | Customer | Birthday greeting and booking prompt |
| Customer | lead_birthday | Lead | Birthday greeting and session prompt |
| Customer | contact_added_by_staff | Customer | Explain a staff-created account |
| Customer | lead_converted_to_customer | Customer | Confirm the first purchase |
| Customer | post_visit_review_request | Customer | Request a review when a review URL exists |
| Booking | class_booked_via_widget | Customer | Confirm a widget booking |
| Booking | waitlist_promoted_to_booked | Customer | Confirm promotion into a session |
| Booking | waitlist_joined_via_widget | Customer | Confirm a widget waitlist entry |
| Booking | class_booked_by_staff | Customer | Confirm a staff-created booking |
| Booking | booking_changed_by_staff | Customer | Explain a staff booking change |
| Booking | reservation_rescheduled_by_customer | Customer | Confirm a customer reschedule |
| Booking | waitlist_added_by_staff | Customer | Confirm a staff-created waitlist entry |
| Booking | reservation_cancelled | Customer | Confirm a customer cancellation |
| Booking | booking_requested | Customer | Confirm a pending booking request |
| Booking | booking_approved | Customer | Confirm booking approval |
| Booking | booking_declined | Customer | Explain a declined booking request |
| Booking | class_cancelled_by_staff | Customer | Explain a cancelled session |
| Booking | booking_cancelled_membership_lapsed | Customer | Explain a booking cancelled because the membership covering it stopped renewing |
| Booking | class_slot_available | Customer | Invite a waitlisted customer to claim a spot |
| Membership | membership_purchased | Customer | Confirm a membership purchase |
| Membership | membership_activated | Customer | Confirm membership activation |
| Membership | membership_active_from_upcoming | Customer | Confirm an upcoming membership is active |
| Membership | membership_paused | Customer | Confirm a membership pause |
| Membership | membership_resumed | Customer | Confirm membership resumption |
| Membership | membership_cancelled_by_staff | Customer | Explain a staff cancellation |
| Membership | membership_cancelled_by_customer | Customer | Confirm a customer cancellation |
| Membership | membership_cancel_scheduled | Customer | Confirm cancellation at period end |
| Membership | membership_plan_changed_by_customer | Customer | Confirm a plan change |
| Membership | membership_expired | Customer | Explain membership expiry |
| Membership | membership_expiring_reminder | Customer | Warn before membership expiry |
| Membership | membership_credits_exhausted | Customer | Explain exhausted visit credits |
| Payment | payment_received | Customer | Deliver an itemized receipt and billing-history link |
| Payment | refund_issued_by_staff | Customer | Confirm a staff-issued refund |
| Payment | refund_issued_automatic | Customer | Confirm an automatic refund |
| Payment | payment_plan_failed | Customer | Explain a failed scheduled payment |
| Payment | payment_authentication_required | Customer | Link a challenged membership renewal to Stripe's payment page |
| Payment | chargeback_opened | Staff | Alert staff to respond to a dispute |
| Payment | chargeback_resolved | Staff | Alert staff to review a dispute outcome |
| Payment | gift_card_received | Customer | Deliver gift-card value, code, and use guidance |
| Waiver | customer_booked_without_waiver | Staff | Alert staff to a missing waiver |
Direct transactional templates
These templates intentionally use layout: false. Credential-bearing messages must not enter the branded click-rewriting shell. Other full-document transactional messages keep this mode to preserve the unbranded delivery contract from issue #2291. They now share the standalone document and action primitives in layout.ts.
| Template | Audience | Purpose | Action |
|---|---|---|---|
| Admin invite | Invited staff | Join a studio team | Accept invite |
| Admin password reset | Staff | Reset a password and explain global sign-out | Reset password |
| Admin sign-in | Staff | Authenticate with a link or code | Sign in |
| Device approval | Customer | Approve a named mobile device | Approve sign-in |
| Email verification | Customer or staff | Verify mailbox ownership | Verify email |
| Customer magic link | Customer | Authenticate into the customer widget | Sign in |
| Email change confirmation | Customer at new address | Confirm the proposed address | Confirm this address |
| Email change approval | Customer at current address | Approve the address change | Approve this change |
| Friend booking invite | Invited friend | Review a booking and required waivers | Open your account |
| Shift notification | Assigned staff | Explain an assignment, change, or cancellation | View schedule |
| Waiver welcome | Customer | Name the purchased membership and required waivers | Open your account |
| Waiver reminder | Customer | Name outstanding waivers | Review and sign |
| Support ticket created | Tenant author and support staff | Confirm the ticket and its diagnostics | View ticket |
| Support ticket status changed | Tenant author and support staff | Report the ticket status | View ticket |
| Support ticket comment added | Tenant author and support staff | Report a new comment | View ticket |
Worker-owned platform mail
| Template | Audience | Purpose |
|---|---|---|
| Trial expiration sequence | Studio owner | Explain trial milestones and available account action |
| Campaign delivery | Tenant-selected contacts | Deliver tenant-authored content inside the platform shell with unsubscribe and notification controls |
Preservation rule for stored tenant hooks
Migration 0229_platform_email_defaults.sql updates a row only when its complete subject, HTML body, and plain-text body are byte-for-byte equal to a known platform default. The rule deliberately does not trust is_default: migration 0096 could not reliably distinguish historical duplicate defaults from custom rows and left some untouched defaults marked false. A one-character tenant edit breaks the fingerprint and preserves the row. This upgrades legacy receipt and destination-label variants without overwriting deliberate tenant copy.
Receipt delivery contract
Every receipt sender supplies raw merge tags for compatibility and derived locale-aware display tags for platform copy. Membership receipt senders include the plan name, payment method, and a non-secret local payment reference. POS receipts include order number, line items, subtotal, discount, tax, total, and tender. The HTML presentation is built from text and table markup, so it remains understandable when remote images are blocked. The plain-text body carries the same purchase, order, amount, payment, and billing-history facts.