Frequently Asked Questions
You'll need Node.js, npm/yarn, NestJS CLI, Docker, Docker Compose, a Vonage API account with a Vonage phone number, and ngrok for local webhook testing.
Use the Vonage Messages API integrated with a NestJS service. The Vonage Node.js SDK simplifies sending SMS messages by providing methods to manage API requests and responses. Make sure to configure the Vonage service with your API credentials from the Vonage dashboard and inject this service into your NestJS campaign service or controller where you'll handle sending logic.
The Vonage Messages API is a service that allows you to send and receive SMS messages programmatically. It's a key component for building SMS marketing campaigns, and you interact with it using the Vonage Node.js SDK within your NestJS application. It also handles message status updates and inbound messages via webhooks.
TypeORM is used for database interaction with PostgreSQL. It provides an object-relational mapper (ORM) simplifying database operations in NestJS. TypeORM defines entities (Campaign, Subscriber, MessageLog) to represent database tables, allowing interaction using JavaScript/TypeScript objects and methods.
Ngrok is useful for testing webhooks locally during development when your local server isn't publicly accessible. It creates a temporary public URL that forwards requests to your local machine. For production, you'll need a stable public URL on a server or platform-as-a-service (PaaS).
Yes, TypeORM supports various databases like MySQL, MongoDB, and more. While the guide uses PostgreSQL, you can adapt the TypeORM configuration in your AppModule to connect to your preferred database. Remember to install the appropriate database driver and adjust connection details accordingly.
Access your Vonage API Dashboard, ensure 'Messages API' is selected under Default SMS settings. Create a new Vonage Application, enabling the 'Messages' capability. Save the private key file securely and note the Application ID. Link your Vonage number to this application so incoming messages are routed to your app's webhook.
The guide recommends a modular structure with separate modules for campaigns, subscribers, Vonage API integration, webhooks, and database operations. This keeps the code organized, maintainable, and easy to test. Create modules using the NestJS CLI and organize related code within each module.
Use the `@nestjs/config` module to load environment variables from a `.env` file. Store API keys, database credentials, and other sensitive information in `.env` and ensure it's added to your `.gitignore` file. Never commit `.env` to version control.
The Vonage service provides a `verifyWebhookJwt` method. You should implement this method by retrieving the Vonage public key or signature secret from your config and using it to verify the webhook signature using the Vonage SDK method or appropriate JWT libraries. This ensures the webhook request is indeed from Vonage.
The guide suggests creating a subscribers module with a service and controller to manage subscriber data. You'll need to implement endpoints and methods to store and retrieve subscribers from the database using TypeORM. Ensure you collect necessary subscriber data like phone numbers.
Consider techniques such as asynchronous message sending with queues or message batching instead of the simple sequential sending in the example. Rate limiting should be carefully managed, potentially with external tools or libraries, if higher throughput is needed.
The private.key file contains your Vonage application's private key, used to authenticate with the Vonage API. It is crucial for security, and should never be committed to version control. Store it securely in your project directory and add it to your `.gitignore` file.
DTOs provide a structured way to define and validate data coming from external sources like API requests. By using class-validator decorators in DTOs, you can easily apply validation rules ensuring data integrity and security.
Building Production-Ready SMS Marketing Campaigns with NestJS and Vonage
This guide provides a step-by-step walkthrough for building a robust SMS marketing campaign application using NestJS, TypeScript, TypeORM, PostgreSQL, and the Vonage Messages API. We will cover everything from initial project setup and Vonage configuration to implementing core features, handling webhooks, ensuring security, and deploying the application.
By the end of this tutorial, you will have a functional NestJS application capable of:
This guide aims to be a complete reference, enabling developers to build and deploy a production-ready system, following the specified guidelines and structure.
Prerequisites:
npm install -g @nestjs/cli
1. Setting Up the NestJS Project
Let's initialize our NestJS project and install the necessary dependencies.
Create a New NestJS Project: Open your terminal and run:
Choose your preferred package manager (npm or yarn).
Install Dependencies: We need modules for configuration, database interaction (TypeORM with PostgreSQL), validation, the Vonage SDK, rate limiting, and health checks.
@nestjs/config
: Manages environment variables.@nestjs/typeorm
,typeorm
,pg
: For PostgreSQL database integration using TypeORM.class-validator
,class-transformer
: For request data validation using DTOs.dotenv
: Loads environment variables from a.env
file.@vonage/server-sdk
: The official Vonage Node.js SDK.@nestjs/terminus
: Implements health check endpoints.nestjs-rate-limiter
: Adds rate limiting to protect endpoints.helmet
: Sets various HTTP headers for security.Project Structure (Conceptual): NestJS promotes a modular structure. We'll organize our code logically:
2. Vonage Account and Application Setup
Before writing code, configure your Vonage account and application correctly. This is critical for authentication and receiving webhooks.
API settings
in the left-hand menu.SMS settings
section.Default SMS Setting
, ensureMessages API
is selected. This determines the webhook format and authentication method we'll use. Save changes if necessary.Applications
->Create a new application
.NestJS SMS Campaigns
).Messages
capability.http://example.com/webhooks/inbound
for the Inbound URL andhttp://example.com/webhooks/status
for the Status URL. We will update these later with our ngrok URL or public deployment URL.Generate public and private key
. Save theprivate.key
file securely within your project directory (e.g., at the root). Do not commit this file to Git. Addprivate.key
to your.gitignore
file.Numbers
->Your numbers
.Manage
orLink
next to the number.NestJS SMS Campaigns
) from the dropdown and save. This directs incoming messages for this number to your application's webhooks.3. Environment Configuration (
.env
andConfigModule
)Securely manage API keys and other configuration settings using environment variables.
Create
.env
and.env.example
files: In the project root, create.env
(for your local values) and.env.example
(as a template). Add.env
to your.gitignore
.File:
.env.example
File:
.env
Integrate
ConfigModule
: Configure theConfigModule
in your rootAppModule
to load these variables globally.File:
src/app.module.ts
4. Database Schema and Data Layer (TypeORM & PostgreSQL)
We'll use TypeORM to define our entities and interact with a PostgreSQL database.
Docker Compose for PostgreSQL: Create a
docker-compose.yml
file in the project root for easy local database setup.File:
docker-compose.yml
Run
docker-compose up -d
to start the PostgreSQL container.Define Entities: Create entity files for
Campaign
,Subscriber
, andMessageLog
.File:
src/database/entities/subscriber.entity.ts
File:
src/database/entities/campaign.entity.ts
File:
src/database/entities/message-log.entity.ts
Configure TypeORM Connection: Update
AppModule
to configure the database connection usingConfigService
.File:
src/app.module.ts
Note: For production, set
synchronize: false
and use TypeORM migrations. Refer to the NestJS TypeORM documentation for migration setup. For this guide,synchronize: true
simplifies local development.Create Modules for Entities: Generate modules and services for
Campaigns
andSubscribers
.Import
TypeOrmModule.forFeature([...])
intoCampaignsModule
andSubscribersModule
to inject repositories.File:
src/campaigns/campaigns.module.ts
File:
src/subscribers/subscribers.module.ts
5. Implementing Core Functionality (Vonage Service & Campaign Sending)
Now, let's integrate the Vonage SDK and implement the logic to send campaign messages.
Create Vonage Module & Service: Encapsulate Vonage SDK initialization and interaction.
File:
src/vonage/vonage.service.ts
File:
src/vonage/vonage.module.ts
Make sure
VonageModule
is imported intoAppModule
's imports array (done in step 4.3).Implement Campaign Sending Logic: Add a method in
CampaignsService
to fetch subscribers and send messages usingVonageService
.File:
src/campaigns/campaigns.service.ts
6. Building the API Layer (Controllers and DTOs)
Expose endpoints to manage campaigns and subscribers.
Define Data Transfer Objects (DTOs) with Validation: Use
class-validator
decorators for robust input validation.File:
src/subscribers/dto/create-subscriber.dto.ts
File:
src/campaigns/dto/create-campaign.dto.ts
Implement Controllers: Create endpoints using the services and DTOs. Ensure
ValidationPipe
is enabled globally.File:
src/main.ts
(Note: The
main.ts
example above shows how to handlerawBody
for webhooks. Ensure your final implementation correctly provides the raw body to your webhook verification logic, potentially usingNestFactory.create(AppModule, { rawBody: true })
and accessingreq.rawBody
in the controller, or using middleware as shown.)(Implement
SubscribersController
andCampaignsController
with appropriate methods using@Get
,@Post
,@Param
,@Body
, etc., calling the respective service methods and using the DTOs.)