Skip to main content

Overview

KAIU Natural Living V.2026 represents a complete migration from a spreadsheet-based system to a robust, scalable SaaS architecture. The platform combines modern web technologies with AI-powered customer service automation. KAIU Architecture Diagram

Technology Stack

Frontend Layer

{
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.30.1",
    "@tanstack/react-query": "^5.83.0",
    "framer-motion": "^12.27.0"
  },
  "devDependencies": {
    "vite": "^5.4.19",
    "@vitejs/plugin-react-swc": "^3.11.0",
    "tailwindcss": "^3.4.17"
  }
}

React 18

Modern UI with concurrent rendering and automatic batching for optimal performance

Vite

Lightning-fast dev server with hot module replacement (HMR)

TailwindCSS

Utility-first CSS framework with custom KAIU design system

Radix UI

Accessible component primitives for dialogs, dropdowns, and forms
Key Frontend Features:
  • Server-state management with TanStack Query
  • Form validation using React Hook Form + Zod schemas
  • Real-time updates via Socket.IO client
  • PWA support with offline capabilities (vite-plugin-pwa)

Backend Layer

server.mjs
import express from 'express';
import cors from 'cors';
import { createServer } from 'http';
import { Server } from 'socket.io';
import apiRoutes from './backend/api/routes.js';
import { setIO } from './backend/whatsapp/queue.js';

const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
  cors: {
    origin: "*",
    methods: ["GET", "POST", "PATCH"]
  }
});

// Share IO instance with routes and queue workers
app.set('io', io);
setIO(io);

const PORT = 3001;
app.use(cors());
app.use(express.json());

// API Routes
app.use('/api', apiRoutes);

httpServer.listen(PORT, () => {
  console.log(`🚀 Server running on http://localhost:${PORT}`);
});
Core Services:
  • backend/api/routes.js - RESTful API routing
  • backend/services/logistics/ - Shipping integrations (Venndelo, Coordinadora)
  • backend/services/inventory/ - Stock management and reservation
  • backend/services/ai/ - RAG retriever and LangChain orchestration
  • backend/services/email.js - Transactional emails via Resend
Integration Endpoints:
  • backend/wompi/ - Payment gateway webhooks and signature generation
  • backend/whatsapp/ - Meta Cloud API webhook handlers and queue workers
  • backend/admin/ - Protected endpoints for dashboard operations

Database Layer

schema.prisma
generator client {
  provider = "prisma-client-js"
  engineType = "library"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
Why PostgreSQL?
  • ACID compliance for transactional integrity
  • pgvector extension for semantic search (RAG embeddings)
  • JSON columns for flexible metadata storage
  • Robust indexing and query optimization
Prisma ORM Benefits:
  • Type-safe database queries
  • Automatic migrations
  • Introspection and schema validation
  • Connection pooling and query optimization

Queue System (BullMQ + Redis)

backend/whatsapp/queue.js
import { Queue, Worker } from 'bullmq';
import IORedis from 'ioredis';
import { generateSupportResponse } from '../services/ai/Retriever.js';

const queueConnection = new IORedis({
  host: process.env.REDIS_HOST || 'localhost',
  port: process.env.REDIS_PORT || 6379,
  password: process.env.REDIS_PASSWORD,
  maxRetriesPerRequest: null
});

export const whatsappQueue = new Queue('whatsapp-ai', { 
  connection: queueConnection 
});

export const worker = new Worker('whatsapp-ai', async job => {
  const { wamid, from, text } = job.data;
  
  // Process message with AI
  const aiResponse = await generateSupportResponse(text, history);
  
  // Send reply via WhatsApp API
  await axios.post(
    `https://graph.facebook.com/v21.0/${process.env.WHATSAPP_PHONE_ID}/messages`,
    { messaging_product: "whatsapp", to: from, text: { body: aiResponse.text } },
    { headers: { 'Authorization': `Bearer ${process.env.WHATSAPP_ACCESS_TOKEN}` } }
  );
}, { 
  connection: queueConnection,
  limiter: { max: 10, duration: 1000 },
  settings: { backoffStrategy: 'exponential' }
});
  • Reliability: Job persistence, retries, and failure handling
  • Concurrency: Rate limiting to respect WhatsApp API quotas
  • Observability: Built-in metrics and event listeners
  • Scalability: Horizontal scaling with multiple workers
  1. WhatsApp webhook receives message → Enqueues job
  2. Worker picks up job from Redis queue
  3. Validates session and bot status
  4. Checks for handover keywords
  5. Generates AI response with RAG
  6. Sends reply via WhatsApp Cloud API
  7. Emits real-time updates to dashboard via Socket.IO
  8. Updates session history in PostgreSQL

AI Orchestrator (Anthropic + LangChain)

backend/services/ai/Retriever.js
import { ChatAnthropic } from "@langchain/anthropic";
import { HumanMessage, SystemMessage, ToolMessage, AIMessage } from "@langchain/core/messages";

const chatModel = new ChatAnthropic({
  modelName: "claude-3-haiku-20240307",
  temperature: 0.1,
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
});

const tools = [
  {
    name: "searchInventory",
    description: "Search product catalog for prices, availability, and variants",
    input_schema: {
      type: "object",
      properties: {
        query: { type: "string", description: "Product name or variant to search" }
      },
      required: ["query"]
    }
  },
  {
    name: "searchKnowledgeBase",
    description: "Search company policies, shipping times, and FAQs",
    input_schema: {
      type: "object",
      properties: {
        query: { type: "string", description: "Policy or information to search" }
      },
      required: ["query"]
    }
  }
];

export async function generateSupportResponse(userQuestion, chatHistory = []) {
  const recentHistory = chatHistory.slice(-4);
  const messages = [
    new SystemMessage(AGENT_PROMPT),
    ...recentHistory.map(m => m.role === 'user' ? new HumanMessage(m.content) : new AIMessage(m.content)),
    new HumanMessage(userQuestion)
  ];
  
  const modelWithTools = chatModel.bindTools(tools);
  let aiMessage = await modelWithTools.invoke(messages);
  
  // Process tool calls
  if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
    messages.push(aiMessage);
    
    for (const toolCall of aiMessage.tool_calls) {
      let result;
      if (toolCall.name === "searchInventory") {
        result = await executeSearchInventory(toolCall.args.query);
      } else if (toolCall.name === "searchKnowledgeBase") {
        result = await executeSearchKnowledgeBase(toolCall.args.query);
      }
      
      messages.push(new ToolMessage({
        tool_call_id: toolCall.id,
        content: result,
        name: toolCall.name
      }));
    }
    
    // Generate final response with tool results
    aiMessage = await modelWithTools.invoke(messages);
  }
  
  return { text: aiMessage.content + "\n\n_🤖 Asistente Virtual KAIU_" };
}

Claude 3 Haiku

Fast, cost-effective model optimized for customer support

Native Tools

Function calling for inventory queries and knowledge retrieval

Anti-Hallucination

Strict prompts prevent the AI from inventing product information

Context Window

Truncated to last 4 messages to prevent tool hallucinations
Critical Rule: The AI MUST use searchInventory tool for every product query. It never relies on memory to avoid hallucinating prices or availability.

Real-Time Communication (Socket.IO)

// Server-side events
io.on('connection', (socket) => {
  console.log('🔌 Dashboard Client Connected:', socket.id);
  
  socket.on('join_session', (sessionId) => {
    socket.join(`session_${sessionId}`);
  });
});

// Emit new message to specific session
io.to(`session_${session.id}`).emit('new_message', { 
  sessionId: session.id, 
  message: { role: 'user', content: text, time: "Just now" } 
});

// Broadcast session updates to all dashboards
io.emit('session_update', { id: session.id, status: 'handover' });
Socket.IO Events:
EventDirectionPurpose
connectionClient → ServerEstablish WebSocket connection
join_sessionClient → ServerSubscribe to specific conversation
new_messageServer → ClientReal-time message delivery
session_newServer → ClientNew WhatsApp conversation started
session_updateServer → ClientBot status or handover change
chat_list_updateServer → ClientRefresh conversation sidebar

Data Flow Diagrams

WhatsApp Message Processing

Order Creation Flow

Security & Privacy

JWT-Based Authentication:
backend/admin/login.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';

const user = await prisma.user.findUnique({ where: { email } });
const valid = await bcrypt.compare(password, user.password);

if (valid) {
  const token = jwt.sign(
    { userId: user.id, role: user.role }, 
    process.env.JWT_SECRET,
    { expiresIn: '7d' }
  );
  res.json({ token });
}
Role-Based Access Control:
  • CUSTOMER: Can place orders and track shipments
  • SUPPORT: Access to WhatsApp dashboard and knowledge base
  • WAREHOUSE: Manage inventory and generate shipping labels
  • ADMIN: Full system access including user management
All chat messages are automatically sanitized before storing in AI context:
backend/whatsapp/queue.js
import { redactPII } from '../utils/pii-filter.js';

// Redact emails and phone numbers
const cleanText = redactPII(text);
const userMsg = { role: 'user', content: cleanText };
history.push(userMsg);
What is redacted:
  • Email addresses → [EMAIL_REDACTED]
  • Phone numbers → [PHONE_REDACTED]
  • Credit card numbers → [CARD_REDACTED]
Original messages are still sent to WhatsApp API, but sanitized versions are stored in the database and shown to AI.
WhatsApp Verification:
app.get('/api/whatsapp/webhook', (req, res) => {
  const token = req.query['hub.verify_token'];
  if (token === process.env.WHATSAPP_WEBHOOK_VERIFY_TOKEN) {
    res.status(200).send(req.query['hub.challenge']);
  } else {
    res.status(403).send('Invalid token');
  }
});
Wompi Signature Validation:
backend/wompi/webhook.js
import crypto from 'crypto';

const expectedSignature = crypto
  .createHash('sha256')
  .update(req.rawBody.toString() + process.env.WOMPI_EVENT_SECRET)
  .digest('hex');

if (signature !== expectedSignature) {
  return res.status(401).send('Invalid signature');
}

Integrations

Meta Graph API v21.0
// Send text message
await axios.post(
  `https://graph.facebook.com/v21.0/${process.env.WHATSAPP_PHONE_ID}/messages`,
  {
    messaging_product: "whatsapp",
    to: phoneNumber,
    text: { body: messageText }
  },
  { headers: { 'Authorization': `Bearer ${process.env.WHATSAPP_ACCESS_TOKEN}` } }
);

// Send image
await axios.post(
  `https://graph.facebook.com/v21.0/${process.env.WHATSAPP_PHONE_ID}/messages`,
  {
    messaging_product: "whatsapp",
    to: phoneNumber,
    type: "image",
    image: { link: imageUrl }
  },
  { headers: { 'Authorization': `Bearer ${process.env.WHATSAPP_ACCESS_TOKEN}` } }
);
Features Used:
  • Text and media messaging
  • Message status callbacks
  • 24-hour customer service window

Performance Optimizations

Database Indexing

Indexes on User.email, Product.sku, Order.readableId, and WhatsAppSession.phoneNumber for fast lookups

Connection Pooling

Prisma manages PostgreSQL connections efficiently with automatic pooling

Redis Caching

BullMQ uses Redis for job queues, which can also cache frequently accessed data

Lazy Loading

AI embedding model and chat client initialized only when first needed
backend/services/ai/Retriever.js
// Singleton pattern for expensive resources
let chatModel = null;

function getChatModel() {
  if (!chatModel) {
    chatModel = new ChatAnthropic({
      modelName: "claude-3-haiku-20240307",
      anthropicApiKey: process.env.ANTHROPIC_API_KEY,
    });
  }
  return chatModel;
}

Deployment Architecture

Project Structure

kaiu-natural-living/
├── src/                    # Frontend React application
│   ├── components/        # Reusable UI components
│   ├── pages/            # Route pages (Home, Checkout, Dashboard)
│   └── lib/              # Utilities and API clients
├── backend/               # Express API server
│   ├── api/              # RESTful routes
│   ├── whatsapp/         # WhatsApp webhook and queue
│   ├── services/         # Business logic
│   │   ├── ai/          # AI orchestrator and RAG
│   │   ├── logistics/   # Shipping integrations
│   │   └── inventory/   # Stock management
│   ├── wompi/           # Payment gateway integration
│   └── admin/           # Protected admin endpoints
├── prisma/               # Database schema and migrations
│   ├── schema.prisma    # Data models
│   └── seed.ts          # Sample data
├── server.mjs           # Express + Socket.IO entry point
└── START_ALL.sh         # Development startup script

Monitoring & Observability

Console logs with structured prefixes:
  • 🚀 Server startup events
  • 🔌 Socket.IO connections
  • ⚙️ BullMQ job processing
  • 🤖 AI orchestrator actions
  • Successful operations
  • Error conditions
For production, integrate with services like Datadog, Sentry, or LogRocket.
worker.on('failed', (job, err) => {
  console.log(`Job ${job.id} has failed with ${err.message}`);
  // Send to error tracking service
});

process.on('SIGTERM', () => {
  console.log('Shutting down gracefully...');
  server.close(() => process.exit(0));
});
Track key metrics:
  • API response times (p50, p95, p99)
  • BullMQ job processing duration
  • WhatsApp API success/failure rates
  • AI token usage and costs
  • Database query performance

Next Steps

API Reference

Explore all available endpoints and request/response schemas

AI Orchestrator Guide

Learn how to customize the chatbot and add new tools

Database Schema

Deep dive into all data models and relationships

Deployment Guide

Production deployment best practices

Build docs developers (and LLMs) love