Frequently Asked Questions
Use RedwoodJS's full-stack framework along with Infobip's SMS API and Node.js for scheduling. The application allows users to schedule appointments through a web interface, and the system automatically sends SMS reminders at the designated times, handling time zones correctly.
RedwoodJS is the core framework for building both the frontend (using React) and the backend (GraphQL API) of the SMS scheduling application. It provides structure, conventions, and developer-friendly features like generators and cells.
Infobip is a CPaaS provider offering a robust SMS API and a convenient Node.js SDK, making it straightforward to integrate SMS sending functionality into the application. Their platform is designed for reliable message delivery.
Use date-fns-tz
for accurate timezone conversions, especially when scheduling tasks. It's crucial for ensuring that SMS reminders are sent at the correct local time for recipients in different time zones and for handling daylight saving time.
Install the Infobip Node.js SDK (@infobip-api/sdk
) and configure your API key and base URL in the .env
file. Then create a service to interact with the Infobip API using the SDK to send SMS messages.
PostgreSQL is used as the database to store appointment details, recipient information, and message status. Prisma, an ORM, simplifies database interactions within the RedwoodJS application.
node-cron
is a Node.js library that provides a simple way to schedule tasks using cron-like expressions. It's used to trigger SMS sending at the correct times, based on the scheduled time and the recipient's time zone.
Use date-fns-tz to calculate the correct cron expression based on the UTC scheduled time and the recipient's time zone. This will ensure that the SMS message is sent at the correct time for every user, regardless of their location.
Use the yarn create redwood-app
command. Initialize a TypeScript project, configure your database connection in the .env
file, and install necessary dependencies like the Infobip SDK, node-cron
, date-fns-tz
, and type definitions.
Prisma acts as an Object-Relational Mapper (ORM), simplifying database interactions. It allows you to define your data models and easily perform CRUD (Create, Read, Update, Delete) operations on your PostgreSQL database from your RedwoodJS backend.
Define your data model in the api/db/schema.prisma
file. This file uses the Prisma schema language. Then run yarn rw prisma migrate dev
to create and apply the migration to your development database.
Use the Infobip Node.js SDK in your API side. You will need your API key and base URL, available from your Infobip account dashboard. Provide the recipient's phone number and message text to the sendSms
function.
Yes, update the appointment's details using an appropriate API call, including the new scheduled time and timezone if needed. The application will cancel any existing job and reschedule the SMS reminder based on the updated information.
You will need Node.js (version 20 or higher recommended), Yarn, an Infobip account, access to a PostgreSQL database, and basic familiarity with JavaScript/TypeScript, React, GraphQL, and terminal commands.
This guide provides a complete walkthrough for building a robust application that schedules and sends SMS reminders using RedwoodJS for the full-stack framework, Infobip for SMS delivery, and Node.js features for scheduling. We'll cover everything from initial setup to deployment and monitoring.
By the end of this tutorial, you will have a functional web application where users can schedule appointments (or any event), and the system will automatically send an SMS reminder via Infobip at the specified time, respecting time zones. This solves the common business problem of needing automated, reliable communication for appointments, notifications, or alerts, helping reduce no-shows and improve user engagement.
Project Overview and Goals
We aim to build a full-stack application with the following capabilities:
node-cron
running on the Node.js backend to trigger SMS sending at the correct time, accounting for different time zones.Technologies:
node-cron
: A simple cron-like job scheduler for Node.js. Chosen for its simplicity in scheduling tasks within the Node.js process.System Architecture:
Prerequisites:
1. Setting up the Project
Let's initialize our RedwoodJS project and install necessary dependencies.
Verify Node/Yarn Versions: Open your terminal and check your versions:
If needed, update Node.js (using
nvm
is recommended:nvm install 20 && nvm use 20
) and Yarn (npm install -g yarn
).Create RedwoodJS App: Use the
create-redwood-app
command. We'll use TypeScript (default) and initialize a git repo.Follow the prompts (commit message, yarn install).
Navigate to Project Directory:
Configure Database Connection: Locate the
.env
file in the project root. Update theDATABASE_URL
variable to point to your PostgreSQL database. Ensure the quotes are correct. Example for a local setup:Replace
postgres
,password
,localhost
,5432
, andschedulerdb
with your actual database credentials and name.Install Dependencies: We need the Infobip SDK,
node-cron
for scheduling,date-fns-tz
for robust timezone handling, and type definitions.@infobip-api/sdk
: The official SDK for interacting with Infobip APIs.node-cron
: To schedule the SMS sending tasks.date-fns-tz
: For accurate timezone conversions, essential for reliable scheduling.@types/node-cron
: TypeScript definitions fornode-cron
.Configure Infobip Credentials: Add your Infobip API Key and Base URL to the
.env
file. You can find these in your Infobip account dashboard under API Keys. Also, define a sender ID (optional, but recommended).xxxxx.api.infobip.com
).Add the following lines to your
.env
file:Important: Replace
YOUR_INFOBIP_API_KEY
andYOUR_INFOBIP_BASE_URL
with the actual credentials obtained from your Infobip account. These are sensitive secrets. Security Note: Never commit your.env
file to version control. Ensure.env
is listed in your.gitignore
file (it should be by default in RedwoodJS).Initial Commit (if not done during setup):
2. Database Schema and Data Layer
We need a database table to store information about the appointments or scheduled messages.
Define Prisma Schema: Open
api/db/schema.prisma
and define theAppointment
model.recipientPhone
: The destination phone number. Using E.164 format is crucial for international compatibility.scheduledAt
: The date and time in UTC when the reminder should be sent.timeZone
: The recipient's local time zone (IANA format). This is critical for scheduling the job correctly.status
: Tracks the state of the reminder.infobipMessageId
: Useful for tracking delivery status via Infobip later.failureReason
: Optional field to store error messages if sending fails.@@index([status, scheduledAt])
for query performance.Create and Apply Migration: Run the following command to generate the SQL migration file and apply it to your development database:
When prompted, provide a name for the migration (e.g.,
create_appointment_model
). This command also generates/updates the Prisma Client based on your schema.3. Core Functionality - API Layer
Now, let's build the backend logic: API endpoints for managing appointments, integrating with Infobip, and setting up the scheduler.
Generate GraphQL SDL and Service: Redwood's generators make this easy.
This creates:
api/src/graphql/appointments.sdl.ts
: Defines the GraphQL schema (types, queries, mutations).api/src/services/appointments/appointments.ts
: Implements the resolvers (business logic) for the SDL.api/src/services/appointments/appointments.scenarios.ts
: For seeding test data.api/src/services/appointments/appointments.test.ts
: Unit test file.Implement CRUD Operations: Open
api/src/services/appointments/appointments.ts
and implement the basic CRUD functions.createAppointment
andupdateAppointment
.try...catch
aroundscheduleAppointmentJob
calls to handle potential scheduling errors during create/update.requireAuth()
comments as placeholders (uncomment/implement if auth is set up).failureReason
.Implement Infobip Integration: Create/update the utility file for Infobip interactions.
Implement Scheduling Logic: Create/update the file for the
node-cron
scheduler, incorporating robust timezone handling and clarifying persistence limitations.date-fns-tz
import and used it ingetCronPattern
for robust timezone handling.timezone
option fromcron.schedule
.scheduledJobs
map and its limitations, mentioning persistent queues earlier.initializeScheduler
must be called, strongly advising against the GraphQL context and recommendingapi/src/server.ts
or similar startup hooks. Added a conceptual example.initializeScheduler
loop.executeJob
now refetches the appointment for latest status.4. Building the Frontend
Let's create the UI for managing appointments using RedwoodJS Cells and Forms.
Generate Page and Cell:
This creates:
web/src/pages/AppointmentsPage/AppointmentsPage.tsx
web/src/components/AppointmentsCell/AppointmentsCell.{tsx,mock.ts,test.tsx}
Implement AppointmentsCell: Edit
web/src/components/AppointmentsCell/AppointmentsCell.tsx
.failureReason
andinfobipMessageId
to theQUERY
.Success
component for where the list/table and form would go.AppointmentForm
(which would need to be created separately, likely withyarn rw g component AppointmentForm
) is beyond the scope of this snippet but would be the next step here.