v1.0 Dashboard Public Profile GitHub
Reference Stable

Architecture Overview

KaiVox AI is a monolithic Laravel 11 application with multi-tenancy, two guard auth, a hybrid billing model, and a modular phase-based feature set. This page documents the core architectural decisions.

Tech Stack

LayerTechnologyNotes
Backend FrameworkLaravel 11PHP 8.2 — use D:\xampp\php82\php.exe artisan locally
DatabaseMySQL 8DB name: kaivox_ai, root/root locally
FrontendBootstrap 4.6 + Blade + ViteNo React/Vue — server-rendered Blade templates
Build ToolViteRun npm run build after CSS/JS changes
AI EngineOpenAI GPT-4oPlatform-level key, all tenants share one key
Telephony (India)VobizWebhook-based, no SDK dependency
Telephony (Global)Twiliotwilio/sdk Composer package
HTTP ClientGuzzle (via Laravel)Used for OpenAI, Google Calendar, Vobiz API, Open-Meteo
QueuesDatabase driverQUEUE_CONNECTION=database, email jobs queued
SchedulerLaravel CronAppointment reminders (hourly), missed-call follow-up (15 min), phone billing (daily 02:00)
PaymentsStripe + RazorpayStripe for global, Razorpay for India
Local DevLaragon on WindowsURL: http://kaivox-ai.test/

Multi-Tenancy Design

KaiVox uses a single-database, shared-schema multi-tenancy model. Every table that holds tenant-specific data has a tenant_id foreign key referencing the tenants table.

Key rule: Every query on a tenant-scoped model must scope to the authenticated tenant. Controllers always resolve the tenant from auth()->user()->tenant or the URL slug.

Tenant Resolution

There are two contexts where a tenant is identified:

  • Authenticated dashboard requests — tenant comes from auth()->user()->tenant_id (eager-loaded via User::$with = ['tenant'])
  • Public/webhook requests — tenant resolved from the {slug} URL segment via Tenant::where('slug', $slug)->firstOrFail()

Tables with tenant_id

All core tables include tenant_id: users, appointments, customers, call_logs, staff, services, locations, messages, knowledge_items, automation_rules, phone_numbers, business_profiles, reviews, visitors, audit_logs, and more.

Two Login Types

TypeGuardLogin URLDashboardDescription
World User web (default) /login /dashboard Business owners and their staff. Every world user belongs to exactly one tenant.
Super Admin super_admin /super-admin/login /super-admin/dashboard Hardik (platform owner). Separate guard, separate session. Full platform visibility.

User Roles within a Tenant

World users have a role column (owner / admin / staff). The OwnerOnly middleware restricts billing and security routes to role = owner. Helpers available on the User model: isOwner(), isAdmin().

Billing Model

KaiVox uses a hybrid subscription + wallet model — inspired by Vobiz prepaid billing.

ComponentDetail
PlansStarter / Pro / Enterprise — each includes a monthly call-minute quota
QuotaFree minutes per month (e.g. Starter = 50 min). After quota exhausted → wallet is charged
WalletPrepaid balance topped up via Stripe or Razorpay. Deducted per minute of call time
Charge pointBillingService::chargeForCall() called at hangup — deducts from quota first, then wallet
Per-minute rateSet by Super Admin per plan. Example: $0.01/min after quota
Low balance alertAutomation trigger low_wallet fires when balance drops below threshold

Directory Structure — Key Files

Controllers

app/Http/Controllers/
├── Auth/                          # Login, register, password reset
├── DashboardController.php        # Main dashboard KPIs
├── AppointmentsController.php     # Booking CRUD + calendar
├── CustomersController.php        # CRM profiles + segmentation
├── StaffController.php            # Staff management + availability
├── ServicesController.php         # Services catalog
├── CallLogsController.php         # Call transcripts + sentiment
├── MessagesController.php         # Unified inbox
├── AnalyticsController.php        # Charts, heatmaps, KPIs
├── BillingController.php          # Wallet, invoices, plan upgrade
├── KnowledgeController.php        # Knowledge Brain CRUD
├── AutomationController.php       # Automation rules builder
├── FrontDeskController.php        # Queue management
├── KioskController.php            # Kiosk mode (no auth)
├── DisplayController.php          # Digital display screen
├── PhoneNumbersController.php     # DID marketplace + lifecycle
├── AgencyController.php           # Agency dashboard + invites
├── BusinessProfileController.php  # Profile settings
├── PublicProfileController.php    # GET /p/{slug} — public
├── MarketingController.php        # Homepage, pricing, industries
├── SettingsController.php         # All settings tabs
└── SuperAdmin/                    # Super admin panel controllers

Services

app/Services/
├── ConversationEngine.php         # OpenAI GPT-4o call handler
├── VobizService.php               # Vobiz webhook responder
├── TwilioService.php              # Twilio voice + SMS + WhatsApp
├── SmsService.php                 # SMS sending abstraction
├── WhatsAppService.php            # WhatsApp sending
├── BillingService.php             # chargeForCall(), wallet deduction
├── CustomerService.php            # syncStats(), VIP auto-promote
├── KnowledgeService.php           # buildAiContext() — injects FAQs into AI
├── LocalIntelligenceService.php   # Holidays, language, weather for AI
├── AutomationService.php          # Trigger checker + action dispatcher
├── IndustryPackService.php        # Applies vertical pack to tenant
├── PhoneNumberService.php         # DID purchase, billing, release
├── AgencyService.php              # Invite → accept → leave flow
├── NotificationService.php        # Booking confirmations, reminders
├── WebhookService.php             # HMAC-signed outbound webhooks
├── IntentRouter.php               # Keyword-based intent detection
├── FailoverService.php            # OpenAI failover + fallback responses
├── AuditService.php               # Audit log writer
└── GoogleCalendarService.php      # OAuth2 + event sync (Guzzle REST)

Models

app/Models/
├── Tenant.php                     # Core tenant — slug, plan, wallet, relations
├── User.php                       # World user — role, isOwner(), tenant relation
├── SuperAdmin.php                 # Separate model for super admin guard
├── Appointment.php                # Bookings + status + Google Calendar sync
├── Customer.php                   # CRM profile — segment, pipeline_stage, LTV
├── CallLog.php                    # Call transcript, sentiment, duration, score
├── Staff.php                      # Team member + availability hours
├── Service.php                    # Service catalog — duration, price
├── Location.php                   # Multi-location branches
├── Message.php                    # SMS/email/WhatsApp message thread
├── KnowledgeItem.php              # FAQ/SOP/pricing/policy items
├── AutomationRule.php             # Trigger → condition → action definition
├── AutomationRun.php              # Execution log per automation rule
├── EscalationQueue.php            # Human handoff requests
├── PhoneNumber.php                # DID — provider, status, billing dates
├── PhoneNumberBilling.php         # Per-number billing history
├── BusinessProfile.php            # Public profile metadata
├── Review.php                     # Customer reviews on public profile
├── AgencyClient.php               # Pivot — agency_tenant_id, client_tenant_id, status
├── Visitor.php                    # Kiosk check-in + queue token
├── HolidayTemplate.php            # Global holiday DB (98 holidays, 6 countries)
├── WebhookEndpoint.php            # Tenant-configured webhook URLs
├── WebhookDelivery.php            # Delivery log + retry tracking
└── AuditLog.php                   # Security audit trail

Key Views

resources/views/
├── layouts/
│   ├── app.blade.php              # Main authenticated app layout
│   └── marketing.blade.php        # Public marketing site layout
├── dashboard/index.blade.php      # World user dashboard
├── super-admin/dashboard.blade.php# Super admin dashboard
├── appointments/                  # Calendar + CRUD views
├── customers/                     # CRM profiles
├── settings/                      # All settings tabs (tabbed UI)
├── public/profile.blade.php       # GET /p/{slug} — public profile
├── kiosk/                         # Kiosk mode + display screen
├── docs/                          # This documentation
└── marketing/                     # Homepage, pricing, industries pages

Routes

routes/
├── web.php                        # World user + public routes
├── api.php                        # Public REST API v1 (/api/v1/*) + webhooks
└── (super-admin routes in web.php under /super-admin/* prefix)

Request Lifecycle (Authenticated)

Browser request
    ↓
routes/web.php  →  middleware: auth, verified
    ↓
Controller resolves tenant from auth()->user()->tenant
    ↓
Controller scopes all DB queries to tenant_id
    ↓
Blade view rendered with tenant-scoped data
    ↓
Response returned

Request Lifecycle (Webhook / API)

POST /api/vobiz/{slug}/answer
    ↓
routes/api.php  →  no auth middleware (CSRF exempt)
    ↓
VobizController resolves tenant by slug
    ↓
VobizService::handleAnswer()
    ↓
ConversationEngine::respond()  →  OpenAI GPT-4o
    ↓
XML response returned to Vobiz