@xenterprises/fastify-xrcs
v1.1.1
Published
Fastify plugin for building and sending RCS rich cards and carousels via Twilio
Readme
xRCS
A Fastify plugin for building and sending RCS rich cards and carousels via Twilio's Content API.
Features
- Card Builder: Fluent API for creating RCS rich cards with media, buttons, and actions
- Carousel Builder: Build horizontally scrolling card carousels
- Content Template Builder: Create complete Twilio Content API payloads
- Validation Helpers: Validate cards and carousels before sending
- Builder-Only Mode: Use builders without Twilio credentials for testing/preview
- Full API Integration: Send messages directly when credentials are provided
Installation
npm install xrcsQuick Start
import Fastify from "fastify";
import xRCS from "xrcs";
const fastify = Fastify();
// Register with Twilio credentials for full API access
await fastify.register(xRCS, {
accountSid: process.env.TWILIO_ACCOUNT_SID,
authToken: process.env.TWILIO_AUTH_TOKEN,
messagingServiceSid: process.env.TWILIO_MESSAGING_SERVICE_SID,
});
// Build and send a product card
const card = fastify.xrcs
.card()
.title("iPhone 15 Pro")
.body("Starting at $999")
.media("https://example.com/iphone.jpg")
.quickReply("Buy Now", "buy_iphone")
.urlButton("Learn More", "https://example.com/iphone");
await fastify.xrcs.sendCard("+15551234567", card);Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| active | boolean | true | Enable/disable the plugin |
| accountSid | string | - | Twilio Account SID |
| authToken | string | - | Twilio Auth Token |
| messagingServiceSid | string | - | Twilio Messaging Service SID |
Card Builder
Create rich cards with media, text, and interactive buttons.
const card = fastify.xrcs
.card()
.title("Product Name") // Max 200 characters
.body("Product description")
.media("https://example.com/image.jpg", "tall") // short, medium, tall
.quickReply("Buy", "action_buy") // Quick reply button
.urlButton("Details", "https://...") // URL button
.phoneButton("Call", "+15551234567"); // Phone button
// Build the card object
const cardData = card.build();Button Constraints
- Maximum 2 buttons per card
- Button titles max 25 characters
- Button types:
QUICK_REPLY,URL,PHONE_NUMBER
Carousel Builder
Create horizontally scrolling card collections.
const carousel = fastify.xrcs
.carousel()
.body("Choose a product") // Note: RCS drops body text
.addCard(
fastify.xrcs
.card()
.title("Laptop Pro")
.body("$999")
.media("https://example.com/laptop.jpg")
.quickReply("Buy", "buy_laptop")
)
.addCard(
fastify.xrcs
.card()
.title("Tablet Plus")
.body("$499")
.media("https://example.com/tablet.jpg")
.quickReply("Buy", "buy_tablet")
);
await fastify.xrcs.sendCarousel("+15551234567", carousel);Carousel Constraints
- Minimum 2 cards, maximum 10 cards
- Button order must be consistent across all cards
- RCS drops body text (WhatsApp displays it)
Content Template Builder
Create complete Twilio Content API payloads for any content type.
// Text message
const textTemplate = fastify.xrcs
.template("Welcome Message")
.language("en")
.variables({ "1": "John" })
.text("Hello {{1}}, welcome to our service!")
.build();
// Card template
const cardTemplate = fastify.xrcs
.template("Product Card")
.card(fastify.xrcs.card().title("Product").body("Description"))
.build();
// Quick reply template
const quickReplyTemplate = fastify.xrcs
.template("Survey")
.quickReply("How was your experience?", [
{ title: "Great", id: "great" },
{ title: "Poor", id: "poor" },
])
.build();
// Register the template with Twilio
const registered = await fastify.xrcs.createTemplate(cardTemplate);
console.log("Template SID:", registered.sid);Supported Content Types
| Type | Description | RCS | WhatsApp |
|------|-------------|-----|----------|
| twilio/text | Plain text | Yes | Yes |
| twilio/media | Images, video, documents | Yes | Yes |
| twilio/card | Rich card with media & buttons | Yes | Yes |
| twilio/carousel | Multiple scrolling cards | Yes | Yes |
| twilio/quick-reply | Quick reply buttons | Yes | Yes |
| twilio/call-to-action | URL/Phone buttons | No | Yes |
| twilio/list-picker | Selection list | No | Yes |
Validation
Validate cards and carousels before sending.
const card = {
title: "A".repeat(250), // Too long!
actions: [
{ type: "QUICK_REPLY", title: "This title is way too long for a button" },
{ type: "URL", title: "Two" },
{ type: "PHONE_NUMBER", title: "Three" }, // Too many buttons!
],
};
const result = fastify.xrcs.validate.card(card);
// {
// valid: false,
// errors: [
// "Title exceeds 200 characters",
// "Card cannot have more than 2 buttons",
// "Button 1 title exceeds 25 characters"
// ]
// }API Reference
Decorators
| Method | Description |
|--------|-------------|
| fastify.xrcs.card() | Create a new CardBuilder |
| fastify.xrcs.carousel() | Create a new CarouselBuilder |
| fastify.xrcs.template(name) | Create a new ContentTemplateBuilder |
| fastify.xrcs.createTemplate(builder, register) | Create/register a content template |
| fastify.xrcs.sendMessage(to, contentSid, vars) | Send message using template SID |
| fastify.xrcs.sendCard(to, card, name) | Create template and send card |
| fastify.xrcs.sendCarousel(to, carousel, name) | Create template and send carousel |
| fastify.xrcs.getTemplate(sid) | Get template by SID |
| fastify.xrcs.listTemplates(limit) | List all templates |
| fastify.xrcs.deleteTemplate(sid) | Delete a template |
| fastify.xrcs.getMessageStatus(sid) | Get message delivery status |
| fastify.xrcs.validate.card(card) | Validate card structure |
| fastify.xrcs.validate.carousel(carousel) | Validate carousel structure |
Constants
import { CONTENT_TYPES, ACTION_TYPES, MEDIA_HEIGHT } from "xrcs";
// Content types
CONTENT_TYPES.TEXT // "twilio/text"
CONTENT_TYPES.MEDIA // "twilio/media"
CONTENT_TYPES.CARD // "twilio/card"
CONTENT_TYPES.CAROUSEL // "twilio/carousel"
// Action types
ACTION_TYPES.QUICK_REPLY // "QUICK_REPLY"
ACTION_TYPES.URL // "URL"
ACTION_TYPES.PHONE_NUMBER // "PHONE_NUMBER"
// Media heights
MEDIA_HEIGHT.SHORT // "short"
MEDIA_HEIGHT.MEDIUM // "medium"
MEDIA_HEIGHT.TALL // "tall"Builder-Only Mode
Use the builders without Twilio credentials for testing or preview.
// Register without credentials
await fastify.register(xRCS, {});
// Builders still work
const card = fastify.xrcs.card().title("Test").body("Preview").build();
// Get template payload without registering
const payload = await fastify.xrcs.createTemplate(
fastify.xrcs.template("Test").card(card),
false // Don't register with Twilio
);
console.log(JSON.stringify(payload, null, 2));Error Handling
try {
await fastify.xrcs.sendCard("+15551234567", card);
} catch (error) {
if (error.message.includes("credentials required")) {
// Missing Twilio credentials
}
// Handle other errors
}Testing
npm testLicense
MIT
