Tiago Fortunato
ProjectsOdysWhatsApp

WhatsApp Message Templates

Overview of the 19 message template functions and their formatting strategy in Odys

WhatsApp Message Templates

Odys leverages WhatsApp as a core communication channel between professionals and clients, automating transactional notifications while preserving conversational context. This system ensures timely, consistent messaging for bookings, reminders, payments, and follow-ups — all while maintaining brand identity and routing context through a shared WhatsApp number.

Overview

The messaging layer is built around 19 template functions defined in src/lib/whatsapp.ts, each generating a structured WhatsApp message for a specific event in the appointment lifecycle. These templates serve both clients and professionals, with distinct formatting strategies: client-facing messages use a branded header and footer for visual consistency, while internal notifications to professionals are concise and action-oriented. All messages are sent via the Evolution API, abstracted behind a unified sendWhatsApp function that handles normalization, delivery, and Redis-based context tracking for inbound replies.

Template Structure and Formatting Strategy

Client messages follow a strict visual hierarchy using divider lines (━━━━━━━━━━━━━━━━━), emoji prefixes, and bold labels to distinguish automated notifications from free-form chat. This is critical because Odys uses the same WhatsApp number for both AI conversations and system alerts. The transactionalHeader utility ensures every client notification begins with a professional-specific banner, followed by personalized content and ends with the TRANSACTIONAL_FOOTER linking back to Odys.

In contrast, messages to professionals (e.g., msgBookingConfirmedReceipt, msgNewMessageToPro) are plain and direct, optimized for quick scanning in a dashboard-like flow. They omit decorative elements but retain key details like client name, date, and time using bold formatting for scannability.

All templates accept typed parameters (e.g., professionalName, clientName, date, time) and avoid hardcoded strings, enabling safe reuse across workflows. URLs are constructed using APP_URL and dynamic slugs (like opts.slug in msgCancelledByProToClient), ensuring correct deep linking.

Design decisions

The separation between client and professional messaging reflects a deliberate UX split: clients receive polished, reassuring notifications that reinforce trust, while professionals get lean, actionable updates. The use of Redis context via setOutboundContext ties outbound messages to specific appointments, enabling reply routing without requiring a dedicated number per professional — a cost and complexity saver.

Template functions are pure and synchronous, making them easy to test and compose. For example, msgRegistrationInvite can be appended to other messages conditionally, allowing onboarding nudges to be injected into confirmation flows dynamically.

Potential improvements

  1. Centralize footer/header logic — The transactionalHeader and TRANSACTIONAL_FOOTER are used across multiple templates in src/lib/whatsapp.ts. These could be extracted into a dedicated formatting module to avoid duplication and enable consistent updates.

  2. Add i18n support — All message strings in src/lib/whatsapp.ts (e.g., Olá, Data, Horário) are hardcoded in Portuguese. Introducing a minimal translation layer would allow future multilingual support without rewriting templates.

  3. Validate template inputs — Functions like msgReminder24h assume date and time are pre-formatted strings. Adding runtime validation or using structured Date objects with formatting inside the template would reduce the risk of inconsistent or malformed output.

References

  • src/lib/whatsapp.ts: Main implementation of all 19 message templates and sendWhatsApp
  • src/lib/conversation.ts: Contains setOutboundContext used for reply routing
  • src/lib/constants.ts: Exports APP_URL used in link generation

On this page