This execution plan covers everything needed to build, deploy, and scale the **Event Buzz Virtual Concierge SaaS Chatbot** as a decoupled microservice running alongside your primary Node.js and Managed MongoDB stack on DigitalOcean. --- ## ๐Ÿ› ๏ธ Step 1: System Infrastructure & Architecture Design Before writing any application logic, you must isolate this high-concurrency chatbot service from your main ticketing web platform so that peak event traffic doesn't degrade your core registration experience. ``` [ Meta WhatsApp Cloud API ] โ”‚ (HTTPS Post Webhooks) โ–ผ [ DigitalOcean Droplet ] โ”‚ [ Nginx Proxy ] โ”‚ [ PM2 Cluster Mode ] โ”‚ [ Node.js Webhook Server ] โ”‚ [ BullMQ / Redis Queue ] โ”‚ [ Background Worker ] / | \ / | \ โ–ผ โ–ผ โ–ผ [ OpenAI API ] [ DO Managed Mongo ] [ Ext. Location APIs ] (Embeddings/LLM) (Shared Cluster DB) (Google Places/Maps) ``` ### 1.1 Infrastructure Components * **Compute Layer:** Spin up a dedicated DigitalOcean Droplet (Ubuntu 24.04, minimum 2 vCPUs / 4GB RAM to comfortably process in-memory mathematical arrays). * **Process Manager:** Use **PM2** running in cluster mode (`pm2 start server.js -i max`) to natively scale across all available virtual CPU cores. * **Message Broker:** Install **Redis** directly on the droplet or use a managed instance. This acts as the backbone for your queue architecture (**BullMQ**) to prevent webhook timeouts. * **Reverse Proxy:** Configure **Nginx** to handle SSL termination (via Let's Encrypt Certbot) and proxy incoming WhatsApp webhooks from port `443` to your internal Node.js port. ### 1.2 Shared Database Connections Configure a dedicated, isolated database client instance connecting to your existing DigitalOcean Managed MongoDB cluster. * Add a strict connection pool parameter (`maxPoolSize: 50`) to handle rapid parallel worker queries. * Create a separate database name (e.g., `eventbuzz_whatsapp`) within the same cluster to logically isolate chatbot data from ticketing collections while retaining shared cluster resources. --- ## ๐Ÿ—„๏ธ Step 2: Exact MongoDB Data Schemas Implement these exact Mongoose schemas to track configuration, session routing states, and the multi-tenant knowledge chunks. ### 2.1 Knowledge Source Configuration Schema (`KnowledgeSource`) Tracks the individual assets uploaded by the organizer and controls the text verification states. ```javascript const mongoose = require('mongoose'); const KnowledgeSourceSchema = new mongoose.Schema({ eventId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, type: { type: String, enum: ['url', 'pdf'], required: true }, sourcePath: { type: String, required: true }, // URL string or S3/DO Spaces file key displayName: { type: String, required: true }, status: { type: String, enum: ['PENDING', 'PROCESSING', 'READY', 'FAILED'], default: 'PENDING' }, errorMessage: { type: String, default: null }, lastSyncedAt: { type: Date, default: Date.now } }, { timestamps: true }); module.exports = mongoose.model('KnowledgeSource', KnowledgeSourceSchema); ``` ### 2.2 Granular Vector Text Chunk Schema (`ContextChunk`) Stores individual text blocks alongside their mathematical representation array for localized context parsing. ```javascript const ContextChunkSchema = new mongoose.Schema({ eventId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, sourceId: { type: mongoose.Schema.Types.ObjectId, ref: 'KnowledgeSource', required: true, index: true }, rawText: { type: String, required: true }, embedding: { type: [Number], required: true }, // Storing 1536 float values natively isActive: { type: Boolean, default: false, index: true } // False until organizer explicitly approves via preview }); module.exports = mongoose.model('ContextChunk', ContextChunkSchema); ``` ### 2.3 Interactive User Session State Schema (`ChatSubscriber`) Manages the individual conversation paths, data access masks, and tracking rules for attendees. ```javascript const ChatSubscriberSchema = new mongoose.Schema({ eventId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, attendeeId: { type: mongoose.Schema.Types.ObjectId, default: null }, // Linked when ticket matches phoneNumber: { type: String, required: true, index: true }, // E.164 international format sessionState: { type: String, enum: ['WELCOME_FORK', 'AWAITING_TICKET', 'MAIN_MENU', 'LOCAL_GUIDE_MODE'], default: 'WELCOME_FORK' }, metaContext: { guestModeEnabled: { type: Boolean, default: false }, lastMenuInteraction: { type: Date, default: Date.now } } }, { timestamps: true }); // Ensures unique session footprint per phone number per event ChatSubscriberSchema.index({ eventId: 1, phoneNumber: 1 }, { unique: true }); module.exports = mongoose.model('ChatSubscriber', ChatSubscriberSchema); ``` --- ## โš™๏ธ Step 3: The Content Ingestion Pipeline (Scraping, Chunking & Verification) When an event organizer triggers a sync or uploads documents, the backend processes it asynchronously using an execution queue. ``` [ Dashboard Input ] โ”€โ”€> [ BullMQ Job ] โ”€โ”€> [ Text Extractor ] โ”€โ”€> [ Token Splitter ] โ”€โ”€> [ Vector Array Generation ] โ”€โ”€> [ Staging Database ] ``` ### 3.1 Text Extraction Rules * **For URLs:** Use a structured engine like `cheerio` or `playwright`. Inject a global sanitizer middleware to systematically drop `