Skip to content

System Settings

Tenant-specific configuration and branding management.

Overview

The System Settings module provides per-tenant configuration management including company information, branding, feature toggles, and integration settings. All settings are tenant-isolated and can be managed by tenant administrators.

Features

  • Company Information: Name, address, contact details
  • Branding: Colors, logo, theme customization
  • Feature Toggles: Enable/disable modules per tenant
  • Integration Settings: API keys, webhook URLs
  • Notification Settings: Email, SMS, push notification preferences
  • Multi-Tenant: Complete tenant isolation

Architecture

mermaid
graph TB
    A[Tenant Admin] --> B[System Settings UI]
    B --> C[Settings API]
    C --> D[system_settings Table]
    D --> E[Tenant Isolation]
    
    F[Application] --> C
    C --> G[Default Settings]
    
    style B fill:#3b82f6
    style D fill:#10b981
    style E fill:#f59e0b

Database Schema

system_settings Table

ColumnTypeConstraintsDescription
iduuidPRIMARY KEYUnique settings identifier
tenant_iduuidUNIQUE NOT NULL, FK → tenantsTenant (1:1 relationship)
settingsjsonbNOT NULL, DEFAULT '{}'Settings JSON object
created_attimestamptzNOT NULL, DEFAULT now()Creation timestamp
updated_attimestamptzNOT NULL, DEFAULT now()Last update timestamp

Indexes:

  • idx_system_settings_tenant on tenant_id (UNIQUE)

Settings Structure

Company Settings

typescript
interface CompanySettings {
  name: string;
  address?: string;
  city?: string;
  postalCode?: string;
  country?: string;
  phone?: string;
  email?: string;
  website?: string;
  taxId?: string;
  logoUrl?: string;
}

Branding Settings

typescript
interface BrandingSettings {
  primaryColor: string; // Hex color, e.g., '#3b82f6'
  accentColor: string; // Hex color, e.g., '#10b981'
  theme: 'light' | 'dark' | 'auto';
  logoUrl?: string;
  faviconUrl?: string;
}

Feature Toggles

typescript
interface FeatureToggles {
  inventory: boolean;
  pickPack: boolean;
  floorPlan: boolean;
  slottingAI: boolean;
  maintenance: boolean;
  safety: boolean;
  equipmentTracking: boolean;
  autoAssignment: boolean;
  sso: boolean;
}

Integration Settings

typescript
interface IntegrationSettings {
  apiKeys?: {
    [key: string]: string;
  };
  webhookUrls?: {
    [key: string]: string;
  };
  externalSystems?: {
    [key: string]: any;
  };
}

Notification Settings

typescript
interface NotificationSettings {
  email: {
    enabled: boolean;
    fromAddress?: string;
    templates?: {
      [key: string]: string;
    };
  };
  sms: {
    enabled: boolean;
    provider?: string;
  };
  push: {
    enabled: boolean;
  };
}

Complete Settings Object

typescript
interface SystemSettings {
  company: CompanySettings;
  branding: BrandingSettings;
  features: FeatureToggles;
  integrations: IntegrationSettings;
  notifications: NotificationSettings;
  // ... other settings
}

API Functions

Get Settings

typescript
import { getSettings } from '@/lib/systemSettings';

const { data, error } = await getSettings();
// Returns: SystemSettings with tenant defaults merged

Behavior:

  1. Fetches tenant-specific settings
  2. Merges with default settings
  3. Returns complete settings object

Update Settings

typescript
import { updateSettings } from '@/lib/systemSettings';

const { data, error } = await updateSettings({
  company: {
    name: 'Updated Company Name',
    address: '123 Main St',
  },
  branding: {
    primaryColor: '#3b82f6',
    accentColor: '#10b981',
  },
});

Parameters:

  • Partial SystemSettings object
  • Only provided fields are updated
  • Other fields remain unchanged

Returns: { data: SystemSettings | null, error: any }

Get Setting Value

typescript
import { getSettingValue } from '@/lib/systemSettings';

const primaryColor = await getSettingValue('branding.primaryColor');
// Returns: string | null

Path Syntax:

  • Dot notation for nested properties
  • Returns null if not found
  • Returns default if available

Default Settings

typescript
const DEFAULT_SETTINGS: SystemSettings = {
  company: {
    name: '',
    address: '',
    // ... empty defaults
  },
  branding: {
    primaryColor: '#3b82f6',
    accentColor: '#10b981',
    theme: 'dark',
  },
  features: {
    inventory: true,
    pickPack: true,
    floorPlan: true,
    slottingAI: true,
    maintenance: true,
    safety: true,
    equipmentTracking: true,
    autoAssignment: true,
    sso: false,
  },
  integrations: {},
  notifications: {
    email: { enabled: true },
    sms: { enabled: false },
    push: { enabled: true },
  },
};

Usage Examples

Apply Branding

typescript
// Get settings
const { data: settings } = await getSettings();

// Apply primary color
document.documentElement.style.setProperty(
  '--primary',
  settings.branding.primaryColor
);

// Apply accent color
document.documentElement.style.setProperty(
  '--accent',
  settings.branding.accentColor
);

Check Feature Access

typescript
import { isFeatureEnabled } from '@/lib/systemSettings';

const canUseSSO = await isFeatureEnabled('sso');
if (canUseSSO) {
  // Show SSO login button
}

Get Company Name

typescript
const companyName = await getSettingValue('company.name');
// Use in UI: "Welcome to {companyName}"

Permissions

RolePermissions
Tenant AdminFull access: read, update all settings
Tenant UserRead-only access
Super AdminFull access to all tenants' settings

Best Practices

1. Use Defaults

Always merge with defaults:

typescript
// ✅ GOOD
const { data: settings } = await getSettings(); // Auto-merges defaults

// ❌ BAD
const { data: rawSettings } = await supabase
  .from('system_settings')
  .select('settings')
  .single(); // No defaults

2. Validate Settings

Validate before updating:

typescript
if (!settings.company.name) {
  throw new Error('Company name is required');
}

3. Cache Settings

Cache settings in application state:

typescript
// Settings don't change frequently
// Cache for 5-10 minutes

4. Feature Toggles

Use feature toggles for gradual rollouts:

typescript
const { data: settings } = await getSettings();
if (settings.features.slottingAI) {
  // Show Slotting AI features
}

Integration

UI Integration

Settings are applied throughout the application:

typescript
// Theme application
const theme = settings.branding.theme;
// Apply theme to UI

// Color application
const primaryColor = settings.branding.primaryColor;
// Apply to CSS variables

SSO Integration

SSO feature toggle controls SSO availability:

typescript
const { data: settings } = await getSettings();
if (settings.features.sso) {
  // Show SSO login option
  // Load SSO providers
}

Troubleshooting

Issue: Settings Not Applied

Symptom: Changes to settings don't reflect in UI.

Solution:

  1. Verify settings were saved successfully
  2. Clear application cache
  3. Refresh page
  4. Check tenant context is correct

Issue: Defaults Not Merging

Symptom: Missing settings return undefined instead of defaults.

Solution:

  1. Use getSettings() function (not direct query)
  2. Verify default settings are defined
  3. Check merge logic in function

Issue: Feature Toggle Not Working

Symptom: Feature still visible when disabled.

Solution:

  1. Verify feature toggle is set correctly
  2. Check UI code checks feature flag
  3. Clear cache and refresh

Released under Commercial License