This example demonstrates how to use the meta-cloud-api package with Next.js 15's App Router to handle WhatsApp Cloud API webhooks and flows. All logic from the Page Router example has been migrated to showcase the full functionality.
- ✅ Next.js 15 App Router - Using the latest Next.js features with native Web APIs
- ✅ TypeScript - Full type safety throughout
- ✅ Complete Message Handlers - All message types supported
- ✅ Message Builders - Using builder pattern for all message types
- ✅ Flow Handler - Manages WhatsApp Flow interactions with dedicated route
- ✅ Clean Architecture - Organized message handlers with path aliases
- ✅ Event Logging - Comprehensive logging for debugging
- ✅ Tree-shakable Imports - Optimal bundle size with
meta-cloud-api/webhook/nextjs-app - ✅ Web Standard APIs - Uses native
RequestandResponseobjects - ✅ Performance Optimized - Leverages Next.js 15 runtime optimizations
The example includes comprehensive message handlers for all WhatsApp message types:
- Echoes back received text messages
- Uses
TextMessageBuilderwith URL preview support - Includes typing indicators and read receipts
- Responds with sample images using
ImageMessageBuilder - Supports captions and external image URLs
- Sends PDF documents using
DocumentMessageBuilder - Includes filename and caption support
- Responds with contact cards using
ContactMessageBuilder - Includes phone, email, organization, and URL details
- Sends location data using
LocationMessageBuilder - Supports coordinates, names, and addresses
- Creates list and button menus using
InteractiveMessageBuilder - Handles user interactions and selections
- Utility to send emoji reactions to messages
- Supports any emoji reaction
- Sends approved template messages using
TemplateMessageBuilder - Supports parameterized templates
Complete webhook handler with all message types registered:
import { webhookHandler } from 'meta-cloud-api/webhook/nextjs-app';
import {
handleTextMessage,
handleImageMessage,
handleDocumentMessage,
// ... other handlers
} from '@/lib/messageHandlers';
const Whatsapp = webhookHandler(config);
// Register all message handlers
Whatsapp.processor.onMessage(MessageTypesEnum.Text, handleTextMessage);
Whatsapp.processor.onMessage(MessageTypesEnum.Image, handleImageMessage);
// ... register other handlers
// Clean export pattern
export const { GET, POST } = Whatsapp.webhook;Manages WhatsApp Flow interactions with proper event handling:
import { webhookHandler } from 'meta-cloud-api/webhook/nextjs-app';
const WhatsappFlow = webhookHandler(config);
// Register flow handlers
WhatsappFlow.processor.onFlow(FlowTypeEnum.DataExchange, handler);
WhatsappFlow.processor.onFlow(FlowTypeEnum.Init, handler);
export const { GET, POST } = WhatsappFlow.flow;The example uses tree-shakable imports for optimal bundle size:
// Import only the Next.js App Router webhook handler
import { webhookHandler } from 'meta-cloud-api/webhook/nextjs-app';
// Import specific message types and enums
import { MessageTypesEnum, FlowTypeEnum } from 'meta-cloud-api/types/enums';
// Import builders for message construction
import {
TextMessageBuilder,
ImageMessageBuilder,
InteractiveMessageBuilder,
ContactMessageBuilder,
LocationMessageBuilder,
DocumentMessageBuilder
} from 'meta-cloud-api/api/messages/builders';src/
├── lib/
│ └── messageHandlers/
│ ├── index.ts # Barrel exports
│ ├── text.ts # Text message handler
│ ├── image.ts # Image message handler
│ ├── document.ts # Document message handler
│ ├── contact.ts # Contact message handler
│ ├── location.ts # Location message handler
│ ├── interactive.ts # Interactive message handler
│ ├── reaction.ts # Reaction utilities
│ └── template.ts # Template message utilities
app/
├── api/
│ ├── webhook/
│ │ └── route.ts # Main webhook handler
│ └── flow/
│ └── route.ts # Flow handler
- Native Web APIs: Uses standard
RequestandResponseobjects - Cleaner Exports: Direct export of HTTP method handlers
- Better Performance: Leverages Next.js 15 optimizations
- Path Aliases: Uses
@/*for clean imports - Modular Architecture: Organized handlers in separate files
WHATSAPP_ACCESS_TOKEN=your_access_token_here
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id_here
WHATSAPP_BUSINESS_ACCOUNT_ID=your_business_account_id_here
WHATSAPP_WEBHOOK_VERIFICATION_TOKEN=your_webhook_verification_token_here- Install dependencies:
pnpm install - Set up environment: Copy
.env.exampleto.env.local - Fill in WhatsApp credentials in
.env.local - Start development:
pnpm dev
Your webhook will be available at http://localhost:3000/api/webhook
Comment out handlers you don't need in app/api/webhook/route.ts:
// Text message handler (enabled by default)
Whatsapp.processor.onMessage(MessageTypesEnum.Text, handleTextMessage);
// Image message handler - uncomment to enable
// Whatsapp.processor.onMessage(MessageTypesEnum.Image, handleImageMessage);Each handler in src/lib/messageHandlers/ can be customized:
// Customize text responses in text.ts
const textMessage = new TextMessageBuilder()
.setBody(`Custom response: ${message.text?.body}`)
.setPreviewUrl(true)
.build();All message types use the builder pattern for clean, type-safe message construction:
// Text with preview
const text = new TextMessageBuilder()
.setBody('Check this link: https://example.com')
.setPreviewUrl(true)
.build();
// Image with caption
const image = new ImageMessageBuilder()
.setLink('https://example.com/image.jpg')
.setCaption('Beautiful image!')
.build();
// Interactive list
const interactive = new InteractiveMessageBuilder()
.setType(InteractiveTypesEnum.List)
.setTextHeader('Menu')
.setBody('Choose an option')
.setListButtonText('View Options')
.addListSections([...])
.build();- Connect your repository to Vercel
- Add environment variables in your Vercel dashboard:
WHATSAPP_ACCESS_TOKEN=your_access_token WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id WHATSAPP_WEBHOOK_VERIFICATION_TOKEN=your_verification_token - Deploy and use your Vercel domain for webhook configuration
Netlify:
- Configure environment variables in site settings
- Deploy using Git integration
Railway/Render:
- Set environment variables in dashboard
- Configure HTTPS domain for webhook
# Start development server
pnpm dev
# Expose locally with ngrok
ngrok http 3000
# Use the HTTPS ngrok URL for Meta webhook configuration- Web Standards: Native
Request/Responseobjects - Better Performance: Optimized runtime with App Router
- Cleaner Code: No custom req/res interfaces needed
- Future-proof: Built on web standards
- Zero Config: No server setup required
- Serverless Ready: Works with any serverless platform
- Next.js Integration: Seamless integration with Next.js features
- TypeScript: Built-in TypeScript support
-
Webhook verification failing
- Ensure environment variables are set in
.env.local - Check that your webhook URL uses HTTPS
- Verify the verification token matches Meta app settings
- Ensure environment variables are set in
-
Messages not processing
- Check browser network tab for POST request errors
- Verify all required environment variables are set
- Check console logs for handler errors
-
Build errors
- Ensure all dependencies are installed:
pnpm install - Check that TypeScript types are correct
- Verify import paths are correct with path aliases
- Ensure all dependencies are installed: