Frequently Asked Questions
You can schedule SMS reminders using Next.js by building an application that integrates with the Vonage Messages API. This involves creating a Next.js frontend for user subscriptions, API routes to handle requests and scheduled tasks, and a database to store subscription data. The application leverages serverless functions and cron jobs for automated reminder delivery.
The Vonage Messages API is a service that allows you to send and receive messages across multiple channels, including SMS. This is the core communication component of our reminder application, used to deliver messages to subscribers according to their schedule.
Prisma ORM simplifies database interactions within the Next.js application. It provides type safety, streamlines database access, and manages migrations, making it easier to work with PostgreSQL and ensuring data integrity.
The date-fns-tz
library is crucial for handling timezones correctly when scheduling SMS reminders. It ensures accurate calculation of reminder times across different time zones, converting between user local time and UTC for consistent scheduling.
While ngrok is useful for testing incoming Vonage webhooks (like delivery receipts), it's not required for the core outbound SMS scheduling functionality described in this guide.
Set up your project by creating a new Next.js app, installing required dependencies like the Vonage Server SDK and Prisma, configuring your .env file with Vonage credentials and database URL, and organizing your project structure for frontend, backend, and utility functions.
PostgreSQL is the recommended database for this SMS scheduler due to its reliability and open-source nature. It's well-suited for storing user subscription details and reminder schedules, and Prisma simplifies integration with Next.js.
Timezones are handled using the date-fns-tz
library, which ensures that reminders are sent at the correct local time for each user. The application stores all reminder times in UTC, converting them to the user's specified timezone for calculation and display.
The /api/cron
endpoint is a serverless function triggered by an external scheduler (like Vercel Cron Jobs). It contains the core reminder logic: querying the database for due reminders, sending SMS messages via the Vonage API, and updating reminder schedules for future execution, handling potential errors during the process.
Secure the cron job endpoint by verifying a secret key, ideally passed via a Bearer token in the Authorization header. The endpoint should check this secret against your environment variable (CRON_SECRET
) before executing any logic, preventing unauthorized access.
Create a subscription endpoint in your Next.js app by defining a new API route file (e.g., /pages/api/subscribe.ts
). This route handles POST requests containing user subscription data, validates input using a schema, and interacts with the database to store or update subscription details.
The Next.js frontend provides the user interface for subscribing to SMS reminders. Users input their phone number, desired frequency, and timezone, which are sent to the backend API endpoint for processing and storage in the database.
Vercel seamlessly integrates with Next.js for easy deployment. Configure your Vercel project to connect to your PostgreSQL database and set up scheduled Cron Jobs to trigger the /api/cron
endpoint at the desired frequency. This automates the reminder sending process.
Store your Vonage API credentials (API Key, API Secret, Application ID, Private Key) securely in environment variables within your deployment environment. Never commit these secrets to version control.
Build automated SMS appointment reminders using Next.js and Vonage Messages API that reliably deliver scheduled notifications to users at their chosen frequency. This comprehensive guide covers project setup, database design with Prisma and PostgreSQL, timezone handling, security best practices, and production deployment with Vercel Cron Jobs.
Learn how to create a system where users subscribe via a web interface, provide their phone number and reminder frequency, and receive automated SMS reminders via the Vonage Messages API according to their schedule. This tutorial addresses real-world notification needs including appointment reminders, subscription renewals, and habit tracking applications.
Project Overview and Goals
What You'll Build:
Technologies Used:
date-fns
&date-fns-tz
: Libraries for robust date and time zone manipulation. (date-fns-tz v3.x provides timezone support using the Intl API, which is natively supported in modern Node.js and browsers.)Deployment Alternatives:
System Architecture:
Prerequisites:
ngrok
only if you intend to test incoming Vonage webhooks (like delivery receipts or inbound SMS), which this guide doesn't focus on. It's not required for the core outbound scheduling functionality described here.1. Setting up the Next.js Project
Initialize your Next.js project and install the necessary dependencies for SMS scheduling.
Create Next.js App: Open your terminal and run the following command. Use the Pages Router (
--no-app
) for API routes in this guide for clarity in the examples.(Adjust Tailwind/ESLint preferences if needed. This guide assumes a
src/
directory).Install Dependencies:
@vonage/server-sdk
: The official Vonage SDK for Node.js (v3.24.1 as of late 2024). Alternatively, use@vonage/messages
(v1.20.3) for standalone Messages API access.@prisma/client
: The Prisma client library to interact with your database.prisma
: The Prisma CLI for migrations and generation (dev dependency).date-fns
,date-fns-tz
: For reliable date/time and time zone handling. date-fns-tz v3.x uses the Intl API for timezone support.dotenv
: To load environment variables from a.env
file during development.zod
: For robust input validation.typescript
and@types/*
: For TypeScript support and type definitions.Initialize Prisma:
This creates:
prisma
directory with aschema.prisma
file..env
file (add this to.gitignore
if not already present!).Configure
.env
: Open the.env
file created by Prisma and add your database connection URL and Vonage credentials. Never commit this file to version control. Create a.env.example
file to track needed variables. Quote all string values, especially multi-line ones or those containing special characters.DATABASE_URL
: Get this from your PostgreSQL provider.private.key
file will download. Save this file securely. Each time a new key is generated, the old key is no longer valid. Copy its content exactly intoVONAGE_PRIVATE_KEY
(ensuring newlines are represented as\n
within the quotes) or provide the path to the file inVONAGE_PRIVATE_KEY_PATH
. Note the Application ID shown.VONAGE_SMS_FROM_NUMBER
) to this specific application.VONAGE_SMS_FROM_NUMBER
: The Vonage number linked above.CRON_SECRET
: Generate a strong random string usingopenssl rand -base64 32
or a password generator. Vercel Cron Jobs automatically include this as a bearer token in the Authorization header for security.Project Structure: Your
src
directory will contain:pages/
: Frontend pages and API routes.index.tsx
: Your main subscription form UI.api/
: Backend API endpoints.subscribe.ts
: Handles new subscriptions.cron.ts
: Contains the logic for sending scheduled reminders.health.ts
: (Optional) Basic health check endpoint.lib/
: Utility functions/modules.prisma.ts
: Prisma client instance.vonageClient.ts
: Vonage SDK client instance.utils/
: Helper functions.timezones.ts
: Timezone validation helpers.scheduler.ts
: Logic for calculating reminder times.styles/
: Global styles.2. Creating a Database Schema and Data Layer
Define your database schema using Prisma and create the necessary database table for storing SMS reminder subscriptions.
Define Schema: Open
prisma/schema.prisma
and define theSubscription
model:phoneNumber
(uniquely),frequencyMinutes
, and the user'stimezone
.nextReminderAt
is crucial: store the exact UTC timestamp for the next reminder.isActive
allows disabling reminders without deleting data.nextReminderAt
andisActive
makes querying for due reminders efficient.Scaling Considerations for Indexes:
For applications with millions of subscriptions, consider these additional indexes:
@@index([phoneNumber, isActive])
@@index([createdAt])
@@index([timezone, isActive])
Run Database Migration: Apply the schema changes to your database:
This creates the
Subscription
table in your PostgreSQL database.Generate Prisma Client: Ensure the Prisma client is up-to-date with your schema:
Create Prisma Client Instance: Create a reusable Prisma client instance.
This pattern prevents creating multiple PrismaClient instances during development hot-reloading.
3. Integrating with Necessary Third-Party Services (Vonage)
Set up the Vonage SDK client for sending automated SMS reminders.
Create Vonage Client Instance: Create a file to initialize and export the Vonage client.
Vonage
client using credentials from environment variables.VONAGE_PRIVATE_KEY
(handling escaped newlines) or from a file path specified byVONAGE_PRIVATE_KEY_PATH
.sendSms
helper function simplifies sending SMS messages, including improved logging.Vonage Error Handling:
Common Vonage API errors and how to handle them:
1300
1320
1380
1440
1520
4. Building the API Layer (Subscription Endpoint)
Create the API endpoint for users to subscribe to automated SMS reminders.
Create Subscription API Route:
Create Utility Functions: Create helpers for time zone validation and calculating the next reminder time.
Timezone Conversion Flow:
DST Handling: The
date-fns-tz
library automatically handles Daylight Saving Time transitions. When DST occurs:Testing the API Endpoint: Test this endpoint using
curl
or Postman once your development server is running (npm run dev
):Expected Success Response (201 Created):
Expected Validation Error Response (400 Bad Request):
5. Implementing Core Functionality (Scheduled Job)
This section handles sending the reminders. Create an API route containing the job logic, designed to be triggered externally by a scheduler like Vercel Cron Jobs.
Create Cron Job API Route:
Retry Logic Decision Flow:
Related Resources
Learn more about SMS messaging and API integrations: