LSCApp Docs
Developers & Integrations

Extending the Platform

Adding a new product type or notification.

General principle

New business logic belongs in packages/shared, used identically by apps/web, apps/mobile, and apps/customer — never duplicated per app. If you find yourself writing the same pricing or validation logic twice, that's a sign it belongs in packages/shared instead.

Adding a new notification

  1. Write the send function in packages/shared/src/email.ts (or the relevant file), following the existing pattern: accept plain data (not an entity ID to look up, where reasonably avoidable), call sendTemplatedEmail.
  2. Register the template in packages/shared/src/emailTemplates.ts — this is what makes it appear in /admin/email-templates as owner-editable.
  3. If it's a customer-facing notification, make sure whatever triggers it respects Customer.notificationsSuppressed (this is handled centrally by sendTemplatedEmail already — you don't need to check it yourself).
  4. If it's a staff alert rather than a customer email, use the existing sendStaffAlertEmail/resolveStaffByRole pattern instead of building a new one.

Adding an approval gate to a new action

Reuse shouldRequireApproval/createPendingApproval from packages/shared/src/approvals.ts if the action fits the existing role-based or threshold-based shape. If it doesn't cleanly fit (for example, no staff member is available to "propose" it, or it needs to affect more than one record), a hold-and-alert pattern — complete the action but withhold the risky part and notify staff — is the established alternative; see how the reschedule-refund gate does this.

Adding a new product type

Look at how an existing similar feature is structured end to end — a Prisma model, a shared business-logic file in packages/shared, a public page if it needs one, an admin page for staff management, and its own notification templates — rather than starting from a blank pattern. Real money and (often) real compliance concerns mean a new product type should follow the same rigor as an existing one, not a lighter-weight shortcut.

Testing

packages/shared's test suite (npm run test:shared) covers pricing, approval logic, and other shared business rules — add to it when you change any of that, not just when you add something brand new.

On this page