Skip to main content

White-Label Configuration

A configuration example focused on tenant branding and customization for white-label deployments.

Complete White-Label Config

// src/eai.config/tenants/acme-corp.config.ts
import type { EAIConfig } from '../types';

export const acmeCorpConfig: EAIConfig = {
tenantId: 'acme-corp',
displayName: 'ACME Corporation Portal',

// ============================================
// THEME - Brand customization
// ============================================
theme: {
// Brand colors
primaryColor: '#FF6B35', // ACME Orange
secondaryColor: '#004E89', // ACME Blue
accentColor: '#F7C59F', // Light accent

// Assets
logo: '/tenants/acme-corp/logo.svg',
logoAlt: 'ACME Corporation',
logoWidth: 180,
favicon: '/tenants/acme-corp/favicon.ico',

// Typography
fontFamily: 'Inter, sans-serif',
headingFontFamily: 'Montserrat, sans-serif',

// Custom CSS class applied to root
rootClassName: 'tenant-acme-corp',
},

// ============================================
// STORE
// ============================================
store: {
user: {
initialState: {
name: null,
email: null,
company: 'ACME Corporation',
role: null,
},
persist: true,
},
ui: {
initialState: {
theme: 'light',
sidebarOpen: true,
},
persist: true,
},
},

// ============================================
// LAYOUT - ACME-specific UI
// ============================================
layout: {
header: [
{
component: 'Header',
priority: 1,
props: {
// Use tenant-specific logo
logo: '/tenants/acme-corp/logo.svg',
logoAlt: 'ACME Corporation',

// Custom navigation
navItems: [
{ label: 'Dashboard', href: '/dashboard', icon: 'home' },
{ label: 'Orders', href: '/orders', icon: 'package' },
{ label: 'Inventory', href: '/inventory', icon: 'box' },
{ label: 'Reports', href: '/reports', icon: 'chart' },
],

// ACME-specific features
showSearch: true,
showNotifications: true,
supportEmail: 'support@acme-corp.com',
},
storeBindings: [
{ prop: 'userName', storePath: 'user.name' },
{ prop: 'companyName', storePath: 'user.company' },
],
},
],

leftPane: [
{
component: 'BrandedSidebar',
priority: 1,
props: {
// ACME brand message
welcomeMessage: 'Welcome to ACME Portal',
brandColor: '#FF6B35',

// ACME-specific links
quickLinks: [
{ label: 'New Order', href: '/orders/new' },
{ label: 'Track Shipment', href: '/tracking' },
{ label: 'Contact Support', href: '/support' },
],
},
storeBindings: [
{ prop: 'userName', storePath: 'user.name' },
],
},
],

middlePane: [
// ACME-branded welcome
{
component: 'BrandedWelcome',
priority: 1,
props: {
headline: 'Welcome to ACME Corporation',
tagline: 'Quality products, delivered fast.',
heroImage: '/tenants/acme-corp/hero.jpg',
ctaText: 'Get Started',
ctaHref: '/onboarding',
},
showWhen: (state) => !state.user?.name,
},

// Authenticated dashboard
{
component: 'Dashboard',
priority: 2,
props: {
widgets: ['recent-orders', 'inventory-alerts', 'shipments'],
},
showWhen: (state) => !!state.user?.name,
},
],

rightPane: [
// ACME help resources
{
component: 'HelpPanel',
priority: 1,
props: {
title: 'ACME Support',
phone: '1-800-ACME-HELP',
email: 'support@acme-corp.com',
hours: 'Mon-Fri 9am-5pm EST',
articles: [
{ title: 'Getting Started', href: '/help/start' },
{ title: 'Place an Order', href: '/help/orders' },
{ title: 'Track Shipments', href: '/help/tracking' },
],
},
},
],
},

// ============================================
// FEATURES - ACME-specific features
// ============================================
features: {
ordering: true,
tracking: true,
analytics: true,
chat: false, // ACME doesn't use chat
aiAssistant: false, // ACME doesn't use AI
},
};

Tenant-Specific Assets

Create a folder for each tenant's assets:

public/
└── tenants/
└── acme-corp/
├── logo.svg
├── logo-dark.svg
├── favicon.ico
├── hero.jpg
└── og-image.png

Tenant-Specific CSS

Create CSS for tenant-specific styles:

/* src/app/tenants/acme-corp.css */

/* Apply when tenant is active */
[data-tenant="acme-corp"] {
/* Override CSS variables */
--primary: 14 90% 58%; /* #FF6B35 */
--primary-foreground: 0 0% 100%;
--secondary: 207 100% 27%; /* #004E89 */

/* Custom font */
--font-sans: 'Inter', sans-serif;
--font-heading: 'Montserrat', sans-serif;
}

/* Tenant-specific component styles */
.tenant-acme-corp .header {
background: linear-gradient(90deg, #FF6B35, #FF8C42);
}

.tenant-acme-corp .logo {
height: 48px;
}

.tenant-acme-corp .cta-button {
background: #FF6B35;
border-radius: 24px;
}

Import in layout:

// src/app/layout.tsx
import './tenants/acme-corp.css';

Applying Tenant Theme

Set the tenant data attribute on the root element:

// src/app/layout.tsx
export default function RootLayout({ children }) {
const tenantId = getTenantId();

return (
<html data-tenant={tenantId}>
<body className={`tenant-${tenantId}`}>
{children}
</body>
</html>
);
}

White-Label Checklist

When setting up a new white-label tenant:

  • Create tenant config file
  • Register in index.ts
  • Add logo and favicon to /public/tenants/[tenant]/
  • Create tenant-specific CSS
  • Configure theme colors
  • Customize navigation items
  • Set up support contact info
  • Configure feature flags
  • Test all color combinations
  • Verify logo displays correctly

Multiple Tenants Example

// src/eai.config/index.ts
import { acmeCorpConfig } from './tenants/acme-corp.config';
import { betaIncConfig } from './tenants/beta-inc.config';
import { gammaLtdConfig } from './tenants/gamma-ltd.config';

const configs: Record<string, EAIConfig> = {
template: templateConfig, // Default fallback
'acme-corp': acmeCorpConfig,
'beta-inc': betaIncConfig,
'gamma-ltd': gammaLtdConfig,
};

Tenant Detection

Tenants can be detected via:

// Query parameter
// localhost:3000?tenant=acme-corp

// Subdomain (requires DNS setup)
// acme-corp.yourapp.com

// Custom domain (requires reverse proxy)
// portal.acme-corp.com