Platform Architecture

Auto Commerce is built on a modular, plugin-based architecture where a minimal core system provides multi-tenancy, authentication, and module orchestration — while all business features are implemented as self-contained modules.

Design Philosophy

  • Plugin-based — Tenants enable only the modules they need. No bloat.
  • Event-driven — Modules communicate through a typed event bus, not direct coupling.
  • Multi-tenant first — Database-per-tenant isolation from day one.
  • API-first — Every feature is accessible through REST APIs.

Tech Stack

Layer Technologies
Backend Laravel 11, PHP 8.4, PostgreSQL 16, Redis 7
Frontend Next.js 14 (App Router), React 18, TypeScript, Tailwind CSS
Mobile Expo SDK 55, React Native 0.83, React 19
Real-Time Laravel Reverb (WebSockets), Laravel Horizon (Queues)
Auth Laravel Passport (OAuth2), spatie/permission (RBAC)
Infra Docker, Kubernetes (k3s), Nginx

System Architecture

┌─────────────────────────────────────────────────────────┐
│                      Clients                            │
│   Next.js Frontend  │  Expo Mobile App  │  External API │
└──────────┬──────────┴────────┬──────────┴───────┬───────┘
           │                   │                  │
           ▼                   ▼                  ▼
┌─────────────────────────────────────────────────────────┐
│                  Nginx (Reverse Proxy)                   │
│              SSL termination, rate limiting              │
└──────────┬──────────────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────────────────────────┐
│              Laravel API (PHP-FPM)                       │
│  ┌───────────┐  ┌───────────┐  ┌─────────────────────┐ │
│  │ Tenant    │  │ Auth      │  │ Module Loader        │ │
│  │ Resolver  │→ │ (Passport)│→ │ (discovers & boots)  │ │
│  └───────────┘  └───────────┘  └─────────┬───────────┘ │
│                                           │             │
│  ┌────────────────────────────────────────┼───────────┐ │
│  │          Module API Bus (events + RPC)  │          │ │
│  │  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐     │ │
│  │  │Products│ │ Orders │ │Shopify │ │Delhvry │ ... │ │
│  │  └────────┘ └────────┘ └────────┘ └────────┘     │ │
│  └────────────────────────────────────────────────────┘ │
└──────────┬──────────────────────────┬───────────────────┘
           │                          │
           ▼                          ▼
┌──────────────────┐    ┌──────────────────────────┐
│   PostgreSQL     │    │   Redis                  │
│  ┌────────────┐  │    │  Cache, Sessions, Queues │
│  │ Landlord DB│  │    └──────────────────────────┘
│  ├────────────┤  │
│  │ Tenant DB 1│  │    ┌──────────────────────────┐
│  ├────────────┤  │    │   Laravel Reverb         │
│  │ Tenant DB 2│  │    │   WebSocket Server       │
│  └────────────┘  │    └──────────────────────────┘
└──────────────────┘

Multi-Tenancy

Auto Commerce uses database-per-tenant isolation via stancl/tenancy:

Database Purpose Contains
Landlord Central/system database Tenant records, billing, module registry, user accounts
Tenant One per organization Orders, products, customers, settings, module data

Tenant Identification

Tenants are resolved through:

  • Subdomain: acme.autocom.com → tenant acme
  • Header: X-Tenant: acme (for API clients)
  • Path: /api/v1/... with tenant context from auth token

What's Shared vs. Isolated

Shared (Landlord) Isolated (Per-Tenant)
User accounts Orders, Products, Customers
Tenant membership & roles Module settings & data
Available modules registry Dashboards & widgets
Billing & plans Files & media

Module System

Modules are self-contained feature packages in /modules/. Each module has its own backend (Laravel) and frontend (React) code.

Module Types

Type Contract Examples
core Orders, Products, Customers, Dashboard
store StoreProviderContract Shopify, WooCommerce
shipping ShippingProviderContract Delhivery, Shiprocket, BlueDart
channel ChannelProviderContract WhatsApp, SMS, Email
payment PaymentProviderContract Razorpay, Cashfree
ai AIProviderContract OpenAI, Claude

Module Communication

Modules never call each other directly. All communication flows through the Module API Bus:

Module A                    Module B
    │                           │
    ├── Bus::call('B', 'method', $data) ──► handles request
    │                           │
    ├── Bus::publish('event.name', $payload)
    │                           │
    │   ◄── subscribes to event ┤

This means:

  • Modules can be installed/removed without breaking other modules
  • Events are published even if no subscriber exists (graceful degradation)
  • New modules can subscribe to existing events without code changes

Module Lifecycle

Registered → Installed → Enabled → Active
                                      ↓
                           Disabled → Uninstalled

Directory Structure

autocom/
├── backend/                    # Laravel API
│   ├── app/
│   │   ├── Core/               # Contracts, base services, module loader
│   │   ├── Http/Controllers/   # System controllers (auth, tenants)
│   │   └── Models/             # System models (User, Tenant)
│   ├── config/                 # Laravel config files
│   ├── database/
│   │   └── migrations/
│   │       ├── *.php           # Landlord (system) migrations
│   │       └── tenant/         # Tenant-scoped migrations
│   └── routes/
│       ├── api.php             # System API routes
│       └── tenant.php          # Tenant-scoped routes
│
├── frontend/                   # Next.js Web App
│   ├── app/                    # App Router pages
│   ├── components/             # Shared UI components
│   ├── contexts/               # React contexts (auth, modules, theme)
│   └── lib/                    # API client, module loader, utilities
│
├── app/                        # Expo Mobile App
│   ├── app/                    # Expo Router pages
│   ├── components/             # React Native components
│   └── contexts/               # Mobile contexts
│
├── docs/                       # Documentation (this site)
│
└── modules/                    # Feature Modules (HMVC)
    ├── Core/                   # Shared models, contracts, base classes
    ├── Products/               # Product catalog
    ├── Customers/              # Customer management
    ├── Orders/                 # Order lifecycle
    ├── CoreDashboard/          # Dashboard & widgets
    ├── Workflows/              # Visual workflow builder
    ├── StoreShopify/           # Shopify integration
    ├── ShippingDelhivery/      # Delhivery shipping
    ├── ChannelWhatsApp/        # WhatsApp messaging
    └── [YourModule]/           # Each has: module.json + backend/ + frontend/

Request Lifecycle

A typical authenticated API request flows through:

  1. Nginx receives request, forwards to PHP-FPM
  2. Tenant Resolver identifies tenant from subdomain or X-Tenant header
  3. Auth Middleware validates Passport token
  4. Permission Middleware checks RBAC permissions (orders.view, etc.)
  5. Tenancy Bootstrap switches database connection to tenant DB
  6. Controller handles the request using module services
  7. Events are published to the Module API Bus
  8. Queue Jobs are dispatched for async work (notifications, webhooks)

Data Flow Example

An order flowing from Shopify to delivery notification:

Shopify webhook → StoreShopify module
    │
    ├── Bus::call('Orders', 'orders.createOrUpdate', $data)
    │       │
    │       ├── OrderIngestService validates & creates order
    │       ├── Publishes: order.created
    │       │
    │       ├── Orders module self-subscribes → reserves inventory
    │       ├── Workflows module subscribes → triggers automations
    │       ├── ResellerOrders subscribes → forwards to chain
    │       │
    │       └── Notification rules → Bus::call('ChannelWhatsApp', 'send', ...)
    │                                       │
    │                                       └── WhatsApp API → Customer

Next Steps