Insolitum Developers

Module Architecture

How modules work in the Insolitum Universe platform. Iframe-based plugin architecture, authentication flow, and data access patterns.

Module Architecture

Insolitum Universe uses an iframe-based plugin architecture. Each module is an independent web application embedded inside the Universe Shell.

Module Architecture β€” Click any component for details

postMessage (auth)SQL queries (RLS)Socket.iopub/subAuth + dataUniverse ShellReact SPAYour ModuleNext.js (iframe)SupabasePostgreSQL + AuthNATSEvent BusWS GatewaySocket.io Bridge

Core Concepts

Universe Shell

The main application (universe-shell) provides:

  • Authentication β€” Supabase Auth with JWT tokens
  • Navigation β€” Sidebar, routing, module switching
  • Module loading β€” Iframe embedding with dynamic routes
  • Subscription management β€” Module access control per organization

Partner Modules

Your module is an independent Next.js 14 application that:

  • Runs on its own domain/port (e.g., my-module.vercel.app)
  • Is embedded in the Shell via <iframe>
  • Receives authentication via postMessage protocol
  • Accesses the shared Supabase database with tenant isolation
  • Communicates with other modules via NATS events

Shared Infrastructure

ComponentDescription
SupabasePostgreSQL database + Auth + Realtime. Shared across all modules. Row Level Security (RLS) ensures tenant isolation.
NATSDistributed event bus for real-time communication. Modules publish/subscribe via WebSocket gateway.
WebSocket GatewaySocket.io server that bridges browser clients to NATS. Handles auth and tenant routing.

How Shell Loads Your Module

  1. User navigates to /admin/modules/your-module in the Shell
  2. Shell checks module_subscriptions table β€” does this org have access?
  3. Shell renders <ModuleFrame> component with your deploy_url
  4. An <iframe> loads your module's URL with ?org_id=<uuid> parameter
  5. Your module mounts and sends REQUEST_AUTH_SESSION to parent
  6. Shell responds with AUTH_SESSION containing access/refresh tokens
  7. Your module's ShellAuthProvider sets the Supabase session
  8. Your module is now fully authenticated and renders its UI

Built-in vs Partner Modules

AspectBuilt-in ModulesPartner Modules
RoutingHardcoded routes in ShellDynamic catch-all route /admin/modules/:slug/*
ConfigMODULE_CONFIGS in @insolitum/typesmodules table in Supabase
ExamplesLexShift, NeuroSense, FabricaYour custom modules
DeploySame monorepoSeparate repository, own hosting

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Universe Shell                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚               Your Module (iframe)               β”‚ β”‚
β”‚  β”‚                                                   β”‚ β”‚
β”‚  β”‚  useShellAuth() ──→ Supabase queries (RLS)       β”‚ β”‚
β”‚  β”‚  useModuleApi() ──→ Tenant-scoped CRUD           β”‚ β”‚
β”‚  β”‚  useNats()      ──→ WebSocket ──→ NATS events    β”‚ β”‚
β”‚  β”‚                                                   β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                       β”‚
β”‚  postMessage ←──→ AUTH_SESSION (tokens)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                              β”‚
         β–Ό                              β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Supabase β”‚                β”‚ NATS Cluster β”‚
    β”‚ (shared) β”‚                β”‚  (events)    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Directory Structure Convention

Every module follows the Next.js 14 App Router pattern:

my-module/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                    # Pages and API routes
β”‚   β”‚   β”œβ”€β”€ layout.tsx          # ShellAuthProvider wrapper
β”‚   β”‚   β”œβ”€β”€ page.tsx            # Main page / dashboard
β”‚   β”‚   β”œβ”€β”€ [feature]/page.tsx  # Feature pages
β”‚   β”‚   └── api/
β”‚   β”‚       └── health/route.ts # Health endpoint (required!)
β”‚   β”œβ”€β”€ hooks/                  # Custom React hooks
β”‚   β”œβ”€β”€ lib/                    # Utilities
β”‚   β”œβ”€β”€ components/             # React components
β”‚   └── i18n/                   # Internationalization
β”œβ”€β”€ package.json
β”œβ”€β”€ next.config.ts              # CSP headers for iframe
β”œβ”€β”€ tailwind.config.ts          # Dark theme
└── .env.local                  # Credentials

The next.config.ts must include CSP headers that allow iframe embedding from *.insolitum.ai. The module-starter template includes this configuration by default.

Next Steps

On this page