Odys Overview
An introduction to Odys, a scheduling platform for independent professionals, detailing its purpose, features, and underlying architecture.
Odys Overview
Odys is a specialized SaaS platform designed to streamline operations for independent professionals in Brazil. It addresses the common challenges faced by individuals like psychologists, personal trainers, and beauticians who often manage their client interactions and scheduling manually, typically through WhatsApp. This document provides a deep dive into Odys's core functionality, its technical architecture, and the design decisions that shaped its current implementation, drawing insights from the application's landing page and overall project structure.
Overview
At its heart, Odys aims to replace the "chaos of WhatsApp" with an organized, automated system for managing appointments, reducing no-shows, and handling payments. The platform is explicitly "WhatsApp-first," meaning it integrates deeply with WhatsApp for client communication, but crucially, it does so through a single, Odys-managed corporate WhatsApp number rather than requiring professionals to connect their personal accounts. This approach, detailed in the README.md, allows for automated reminders, booking confirmations, and even conversational AI interactions without cluttering a professional's personal communication channels.
The application is built on a modern web stack, primarily using Next.js 16 (App Router) with TypeScript for its frontend and API routes, and Supabase as its PostgreSQL database backend. Drizzle ORM provides a type-safe interface to the database, which comprises 10 distinct tables. The landing page, found in src/app/page.tsx, serves as the primary entry point, showcasing the platform's value proposition and key features to potential users.
Odys targets a diverse range of independent professionals, with examples like "Psicólogo", "Personal Trainer", "Cabeleireiro", and "Nutricionista" displayed on the landing page. A comprehensive list of 30+ professions is defined in src/lib/professions.ts, categorized into areas like "Saúde & Clínica" and "Beleza & Estética", indicating the breadth of its intended user base. To ensure legal compliance and transparency, Odys includes dedicated pages for its privacy policy and terms of service, adhering to LGPD regulations.
Core Functionality
Odys provides a suite of features tailored for both professionals and their clients, all orchestrated through a unified platform.
Scheduling and Availability
Professionals define their working hours using the availability table, which stores dayOfWeek, startTime, and endTime for each professionalId. Clients can then visit a public booking page (e.g., /p/[slug]) to view available time slots and schedule appointments. The appointments table tracks each booked session, including startsAt, endsAt, status, and paymentStatus. Professionals can configure whether appointments require manual confirmation or are automatically confirmed upon booking. Appointment statuses include pending_confirmation, confirmed, completed, rejected, cancelled, and no_show. Payment statuses include none, authorized, captured, and refunded. For recurring clients, the recurringSchedules table allows professionals to set up automated, repeating appointments, which are then generated by the system. The /api/booking API route handles the logic for fetching available slots and creating new appointments.
Client Management and Communication
Each professional maintains a list of clients in the clients table, which links to the professionalId. This table stores essential client details like name, phone, and email. Professionals can keep private notes about their clients in the clientNotes table, accessible via the /api/clients/notes endpoint. A direct messaging system, managed through the messages table and exposed by the /api/messages API route, enables professionals and clients to communicate within the platform, centralizing all interactions.
Automated WhatsApp Integration
A cornerstone of Odys is its deep integration with WhatsApp, powered by the Evolution API v2. The system uses approximately 20 distinct WhatsApp message templates, defined in src/lib/whatsapp.ts, to handle various communications. These include automated 24-hour and 1-hour reminders before sessions, booking confirmations, rejections, and cancellations. These messages are sent via cron jobs, specifically GET /api/cron/reminders, which runs daily at 8 AM. Additionally, a GET /api/cron/whatsapp-watchdog cron job runs daily at 9 AM to perform a health check on the Evolution API. The system also implements conversation-aware delivery, where the reminder cron job skips sending a message if the client is actively conversing with the AI agent, deferring the reminder to avoid interrupting the dialogue. Inbound messages from clients are processed by the POST /api/whatsapp/webhook endpoint, which routes them to an AI intake agent for conversational scheduling and context resolution. This ensures that even replies to transactional messages are handled intelligently, by looking up last_outbound:{phone} in Redis to link them back to the relevant professional or appointment. In addition to WhatsApp, Resend is used for transactional emails, such as confirmations and notifications, as managed by src/lib/email.ts.
Payments and Subscriptions
Odys facilitates payment collection for professionals and manages subscriptions for the platform itself. Professionals can configure their PIX key (pixKeyType, pixKey columns in the professionals table) to receive payments directly from clients. For platform subscriptions, Odys uses Stripe, integrating with its API via routes like /api/stripe/checkout and handling webhook events (e.g., checkout.session.completed, customer.subscription.updated) through POST /api/stripe/webhook. The platform offers four distinct plans: free, basic, pro, and premium, each with different pricing and feature limits, as defined in the PLANS constant in src/lib/stripe. For Pro plan users, the platform also provides financial reports, detailing revenue by period, completed sessions, and no-shows.
User Engagement and Discovery
Clients can discover professionals through the /explore page and "follow" their favorites, recorded in the follows table. After an appointment, clients can submit ratings and comments via the reviews table, linked to a specific appointmentId. Notifications, stored in the notifications table, keep both professionals and clients informed of important events, with the /api/notifications route allowing users to fetch and mark them as read. Clients also have access to a dedicated client portal (/c) where they can view their appointment history, check statuses, and manage cancellations. The platform supports both dark and light modes, allowing users to customize their interface preference.
Design Decisions
The architectural choices in Odys reflect a pragmatic approach to building a feature-rich SaaS application with a lean team, prioritizing developer experience and rapid iteration.
Next.js App Router for Unified Development
The decision to use Next.js App Router allows for a single codebase to manage both server-side rendered pages (like the landing page src/app/page.tsx and public booking pages src/app/p/[slug]/page.tsx) and backend API routes (e.g., /api/booking). This eliminates the need for a separate backend project, simplifying deployment and development workflows. Server Components contribute to faster initial page loads and improved SEO, which is crucial for professional discovery.
Drizzle ORM for Type Safety and Simplicity
Drizzle ORM was chosen over alternatives like Prisma for its lightweight nature and strong TypeScript integration. By defining the entire database schema in src/lib/db/schema.ts, Drizzle ensures that all database interactions are fully typed. This means that any change to the schema immediately surfaces type errors in related code, preventing common runtime bugs and improving code maintainability.
Evolution API for WhatsApp Integration
The use of Evolution API v2 for WhatsApp integration is a strategic decision to provide a "WhatsApp-first" experience without the complexities and restrictions of Meta's official WhatsApp Business Cloud API for smaller-scale operations. Evolution API acts as a shim over WhatsApp Web, allowing Odys to manage a single corporate WhatsApp number that handles all client and professional communications. This abstracts away the need for individual professionals to configure their own WhatsApp accounts, simplifying onboarding and support. The architecture is designed with a clear abstraction layer (sendWhatsApp() in src/lib/whatsapp.ts) to allow for a future transition to Meta's official API as the platform scales, minimizing changes to call sites.
Supabase as a Managed Backend
Supabase provides a managed PostgreSQL database, authentication, and storage services, significantly reducing operational overhead. This choice allows the development team to focus on application features rather than database administration. Supabase Auth handles user registration and login, including email/password and Google OAuth, integrating seamlessly with the professionals and clients tables.
Operational Infrastructure
To ensure reliability and performance, Odys integrates several key operational services. Upstash Redis provides robust rate limiting for API endpoints, preventing abuse and ensuring fair usage (see src/lib/ratelimit.ts). For production error tracking, Sentry is utilized, offering real-time insights into application issues. User behavior and platform engagement are monitored using PostHog analytics, informing product development and improvements.
Potential Improvements
While the current implementation serves its purpose effectively, several areas present opportunities for refinement and enhancement:
-
Dynamic Profession Display on Landing Page: The
PROFESSIONSarray used insrc/app/page.tsxfor the "Profession pills" section is a hardcoded subset of the more comprehensivePROFESSIONSobject defined insrc/lib/professions.ts. To maintain consistency and reduce duplication, the landing page could dynamically fetch or derive this list fromsrc/lib/professions.ts, perhaps by filtering for the most popular or representative professions. This would ensure that updates to the master list of professions are automatically reflected on the landing page without manual synchronization. -
Centralized Feature Definition for Plans and Landing Page: The
FEATURESarray insrc/app/page.tsxdescribes the platform's core functionalities, while thePLAN_FEATURES(implicitly used in the pricing section of the landing page, likely fromsrc/lib/stripe) defines features tied to subscription plans. These two lists, though serving different display purposes, describe overlapping sets of features. Consolidating these feature definitions into a single source of truth, perhaps with metadata indicating visibility on the landing page or inclusion in specific plans, could prevent inconsistencies and simplify feature management. -
Automated JSON-LD Generation: The
jsonLdobject insrc/app/page.tsxis statically defined. While functional for SEO, itsdescriptionandoffers.descriptionfields could be dynamically generated or pulled from a content management system. This would allow for easier updates to SEO metadata without requiring code changes and redeployments, especially for marketing-driven text.
References
src/app/page.tsxREADME.mdsrc/lib/db/schema.tssrc/lib/professions.tssrc/lib/whatsapp.tssrc/lib/stripe/index.ts