Frequently Asked Questions
Create a new RedwoodJS project, install required dependencies like MessageBird and Prisma, define the database schema for appointments, and implement the API logic to handle bookings and scheduling. Then, build a frontend form for users to book appointments and connect it to the backend API. Finally, configure the SMS integration with MessageBird to send automated reminders.
RedwoodJS is the core framework for building the web application. It provides a full-stack, serverless-first environment based on React, GraphQL, and Prisma, enabling rapid development of both frontend and backend components.
MessageBird is a communications platform offering a reliable SMS API and phone number lookup capabilities. This integration allows for automated SMS reminders to be sent to users, minimizing no-shows and improving appointment management.
While this tutorial uses Moment.js for date/time manipulation, it's in maintenance mode. For new projects or significant updates, consider modern alternatives like date-fns, Luxon, or native JavaScript Date/Intl methods for better performance and maintainability. This is especially crucial for production-level applications
Yes, RedwoodJS supports authentication features. You can use Redwood's built-in authentication generators to easily add user accounts, enabling users to manage their own appointments and access personalized features. After generating authentication you can add the `@requireAuth` directive to the relevant services.
The guide provides examples for PostgreSQL and SQLite. PostgreSQL is generally recommended for production environments, while SQLite is suitable for simpler development and testing purposes. The Prisma ORM handles database interactions.
The application uses the MessageBird Lookup API to validate phone numbers. This API verifies the number's format and identifies the number type (e.g., mobile, landline), ensuring only valid mobile numbers are used for SMS reminders.
The application enforces a minimum booking time of 3 hours and 5 minutes in the future. This time constraint is implemented in the backend service logic, ensuring adequate time for reminder scheduling.
The tutorial implementation uses date-time parsing that depends on the server's time zone, which can be problematic. Ideally, you should implement robust timezone handling using specialized libraries like `date-fns-tz` or Luxon, storing all dates and times in UTC format.
While not covered in the initial setup, implementing MessageBird webhooks allows receiving real-time status updates for SMS messages. This provides feedback on delivery success or failure and enables more advanced features like retry mechanisms or notifications.
Appointment data is stored in a relational database (PostgreSQL or SQLite). The application uses Prisma, a next-generation ORM, to define the database schema, manage migrations, and interact with the database seamlessly from the API side.
RedwoodJS utilizes GraphQL for communication between the frontend and the backend API. The frontend uses GraphQL queries and mutations to request and modify data, while the backend defines the GraphQL schema and resolvers that handle these requests.
The optional `messageBirdId` field stores the unique identifier assigned to the scheduled SMS message by MessageBird. This allows for tracking the message status and potentially canceling or rescheduling it later.
RedwoodJS offers deployment options for various platforms like Vercel, Netlify, and Render. Consult the RedwoodJS deployment documentation for specific instructions. Make sure to properly configure your environment variables (DATABASE_URL, MESSAGEBIRD_API_KEY, etc.) in your production environment.
This guide provides a step-by-step walkthrough for building a web application using RedwoodJS that allows users to book appointments and receive automated SMS reminders via MessageBird. We'll cover everything from project setup and core logic implementation to deployment and verification.
Modern applications often require timely communication to reduce friction and improve user experience. For appointment-based services, automated reminders are crucial for minimizing no-shows and ensuring smooth operations. This guide demonstrates how to leverage the power of RedwoodJS's full-stack capabilities combined with MessageBird's robust SMS API to create a production-ready appointment reminder system.
Project Overview and Goals
What We'll Build:
We will create a RedwoodJS application with the following features:
Problem Solved:
This application directly addresses the common business problem of customer no-shows for scheduled appointments, which leads to lost revenue and inefficient resource allocation. By sending timely SMS reminders, we aim to significantly reduce the no-show rate.
Technologies Used:
date-fns
, Luxon, or nativeIntl
/Date
methods where possible. This guide retains Moment.js for consistency with the example, but replacements are recommended for production codebases.System Architecture:
Prerequisites:
Final Outcome:
By the end of this guide, you will have a fully functional RedwoodJS application capable of accepting appointment bookings and scheduling SMS reminders via MessageBird. You will also have the foundational knowledge to extend this application with more features like authentication, cancellation flows, or administrative dashboards.
1. Setting Up the RedwoodJS Project
Let's start by creating a new RedwoodJS project and installing the necessary dependencies. We'll use TypeScript for enhanced type safety.
Create RedwoodJS App: Open your terminal and run the RedwoodJS create command:
This command scaffolds a new RedwoodJS project with TypeScript configured in a directory named
redwood-messagebird-reminders
.Navigate to Project Directory:
Install Initial Dependencies: RedwoodJS automatically runs
yarn install
after creation. If you need to run it manually:Configure Environment Variables: RedwoodJS uses a
.env
file for environment variables. Create this file in the project root:Open
.env
and add the following variables. You'll get the values in subsequent steps..env
? Storing sensitive information like API keys and database URLs directly in code is insecure. Environment variables provide a standard, secure way to manage configuration across different environments (development, staging, production). Redwood automatically loads variables from.env
intoprocess.env
.Install Additional API Dependencies: We need the MessageBird Node.js SDK and Moment.js for date manipulation within our API service. Navigate to the
api
workspace to install them:yarn workspace api add
? Redwood uses Yarn Workspaces to manage dependencies for theweb
andapi
sides separately. This command ensures these packages are added only to theapi
side where they are needed.Initial Git Commit (Recommended): Initialize a Git repository and make your first commit:
You now have a basic RedwoodJS project structure with the necessary configurations and dependencies ready for development.
2. Implementing Core Functionality (API & Database)
Now, let's define the database schema, create the API service logic for handling bookings and scheduling reminders, and set up the GraphQL endpoint.
Define Database Schema (Prisma): Open the Prisma schema file located at
api/db/schema.prisma
. Replace the default example model with ourAppointment
model:appointmentDt
) and the scheduled reminder time (reminderDt
). Storing themessageBirdId
allows tracking the scheduled message status later if needed. Storing dates in UTC is best practice.Apply Database Migrations: Use Prisma Migrate to create the
Appointment
table in your database based on the schema changes.create appointment model
is suitable.migrate dev
? This command compares yourschema.prisma
with the database state, generates SQL migration files, applies them to your development database, and regenerates the Prisma Client. It's essential for keeping your database schema in sync with your application model.Generate GraphQL SDL and Service: Redwood's generators can scaffold the basic GraphQL schema definition language (SDL) files and service implementations for CRUD operations.
This command creates/updates:
api/src/graphql/appointments.sdl.ts
: Defines the GraphQL types (Appointment
,CreateAppointmentInput
,UpdateAppointmentInput
) and operations (queries/mutations).api/src/services/appointments/appointments.ts
: Contains the business logic (resolvers) for interacting with theAppointment
model.api/src/services/appointments/appointments.scenarios.ts
: For defining seed data for tests.api/src/services/appointments/appointments.test.ts
: Basic test file structure.Customize GraphQL SDL: Open
api/src/graphql/appointments.sdl.ts
. We need to adjust theCreateAppointmentInput
to match the fields we'll collect from the user form (excluding fields generated by the backend likereminderDt
,messageBirdId
,createdAt
).CreateAppointmentInput
to acceptnumber
,date
, andtime
as strings, reflecting typical HTML form input. Added comment suggesting ISO 8601.@skipAuth
tocreateAppointment
mutation to allow unauthenticated users to book. Keep@requireAuth
for other operations.Implement Service Logic: This is where the core booking and scheduling logic resides. Open
api/src/services/appointments/appointments.ts
and modify thecreateAppointment
function significantly.validateAppointmentDateTime
warning about server-local time zone parsing and recommending UTC/ISO 8601.messagebird.lookup.read
asynchronously using Promises. Handles errors and checks if the number is mobile. Throws specific, user-friendly errors. Stores the E.164 formattednormalizedPhoneNumber
.messagebird.messages.create
, ensuringscheduledDatetime
is formatted as ISO 8601 (UTC recommended). Uses Promises for async handling.try...catch
blocks. Logs detailed errors using Redwood's logger and throws user-friendly error messages.You've now implemented the core backend logic. The API can accept booking requests, validate data and phone numbers, schedule SMS reminders via MessageBird, and save appointments to the database.
3. Building the Frontend Interface
Let's create the React components and page for users to interact with the booking system.
Generate Page and Component: Use Redwood generators to create the page and a reusable form component.
web/src/pages/BookingPage/BookingPage.tsx
(and related files) accessible at the/booking
route.web/src/components/BookingForm/BookingForm.tsx
(and related files).Implement the Booking Form Component: Open
web/src/components/BookingForm/BookingForm.tsx
. We'll use Redwood's form helpers for easier state management and validation handling.@redwoodjs/forms
,@redwoodjs/router
,@redwoodjs/web
, and@redwoodjs/web/toast
. Added logger import. Commented outdate-fns
import but noted its recommendation.CREATE_APPOINTMENT_MUTATION
matching the backend SDL.useMutation
Hook: Sets up the mutation call, includingonCompleted
(for success toast, logging, navigation, form reset) andonError
(for error toast and logging) handlers.useForm
Hook: Initializes Redwood's form handling, setting validation mode toonBlur
.onSubmit
Handler:datetime-local
input string (data.appointmentDateTime
) into aDate
object. Includes a warning about potential nativeDate
parsing issues and recommends a library.Date
object intoYYYY-MM-DD
andHH:mm
strings as required by the backend mutation input. Includes a note about the fragility of string manipulation and preference for date library functions.input
object for the mutation.create
function fromuseMutation
.try...catch
block for errors during date/time processing before the mutation is sent.getMinDateTime
Helper: Calculates the earliest selectable date/time for theDatetimeLocalField
based on the backend rule (3 hours) plus a buffer (15 minutes) to prevent validation failures due to timing differences. Formats the date correctly for themin
attribute ofdatetime-local
.<Form>
,<FormError>
,<Label>
,<TextField>
,<DatetimeLocalField>
,<FieldError>
, and<Submit>
components.DatetimeLocalField
for combined date and time input, simplifying the UI.required
validation. Commented out a basic phone number pattern, emphasizing backend validation is primary.min
attribute onDatetimeLocalField
usinggetMinDateTime
.<Submit>
button is disabled during loading.Implement the Booking Page: Open
web/src/pages/BookingPage/BookingPage.tsx
. This page will simply render theBookingForm
component.MetaTags
for SEO and theBookingForm
. Renders a heading, some descriptive text, and the form component.Add Routes: Ensure the routes are defined in
web/src/Routes.tsx
. Thegenerate page
command should have added the/booking
route. You might also want a success page route.bookingSuccess
which theBookingForm
attempts to navigate to. You would need to generate and implementBookingSuccessPage
for this to work fully.Add Toaster: To display the success/error messages from
toast
, you need to add the<Toaster />
component, typically in your main layout file (e.g.,web/src/layouts/MainLayout/MainLayout.tsx
).The frontend is now set up. Users can navigate to
/booking
, fill out the form, and submit it to trigger the backend logic. Feedback is provided via toasts.4. Running and Testing
Start the Development Server: Run the Redwood development server which starts both the API and web sides with hot-reloading.
Access the Application: Open your browser and navigate to
http://localhost:8910/booking
(or the port specified in yourredwood.toml
).Test Booking:
yarn rw prisma studio
).Test Validation:
Conclusion and Next Steps
You have successfully built a RedwoodJS application that integrates with MessageBird to accept appointment bookings and schedule automated SMS reminders. This setup leverages Redwood's conventions for rapid development, Prisma for database management, GraphQL for API communication, and MessageBird for crucial communication features.
Potential Enhancements:
BookingSuccessPage
component and route.messageBirdId
.yarn rw generate auth ...
) so users can manage their own appointments.date-fns-tz
or Luxon) to ensure appointment and reminder times are correct regardless of user or server location. Store dates in UTC.DATABASE_URL
,MESSAGEBIRD_API_KEY
, etc.) are configured correctly in the deployment environment.