mdxui

SaaSApp

Multi-tenant product application with workspace management and billing

SaaSApp

The SaaSApp specialization provides a complete multi-tenant SaaS application interface with workspace management, team collaboration, billing and subscriptions, and third-party integrations. It's designed for B2B or B2C products that need tenant isolation and subscription management.

Overview

SaaSApp extends the base App with SaaS-specific features:

  • Multi-Tenancy - Workspace/organization isolation
  • Workspace Switcher - Switch between organizations
  • Team Management - Invite members and assign roles
  • Billing & Subscriptions - Manage plans and payment
  • Integrations - Connect third-party services

Type Signature

interface SaaSAppProps extends AppProps {
  /** SaaS application configuration */
  config?: {
    /** Enable multi-tenancy */
    multiTenant?: boolean // default: true
    /** Show workspace switcher */
    showWorkspaceSwitcher?: boolean // default: true
    /** Show billing section */
    showBilling?: boolean // default: true
    /** Show team management */
    showTeam?: boolean // default: true
    /** Show integrations */
    showIntegrations?: boolean // default: true
    /** Pricing tiers */
    pricingTiers?: string[] // e.g., ["free", "pro", "enterprise"]
    /** Feature flags */
    features?: Record<string, boolean>
  }
}

Naming Convention

All SaaSApp components follow the pattern: SaaS${Component} = ${Component} + SaaS-specific props.

// Base component + SaaS props = SaaS component
SaaSDashboard = Dashboard + { showUsageMetrics, showTeamActivity }
SaaSTeam = Team + { showInvites, enableSSO }
SaaSBilling = Billing + { showUsage, showInvoices }
SaaSIntegrations = Integrations + { showMarketplace, enableOAuth }
SaaSSettings = Settings + { showWorkspace, showBilling }

Quick Start

import type { AppComponents } from 'mdxui'
import { SaaSApp } from '@mdxui/cockpit'

export const components: AppComponents = {
  App: SaaSApp,
  Shell,
  Sidebar,
  Header,
  Dashboard: SaaSDashboard,
  Settings: SaaSSettings,
}

In your MDX:

<SaaSApp
  name="Acme Platform"
  config={{
    multiTenant: true,
    showWorkspaceSwitcher: true,
    showBilling: true,
    showTeam: true,
    showIntegrations: true,
    pricingTiers: ['free', 'pro', 'enterprise']
  }}
>
  <Shell>
    <SaaSDashboard />
  </Shell>
</SaaSApp>

App Structure

SaaSApp
├── SaaSDashboard - Product dashboard with usage metrics
├── [ProductViews] - Core product functionality (app-specific)
├── SaaSTeam - Team member management and invites
├── SaaSBilling - Subscription and payment management
├── SaaSIntegrations - Third-party integrations
└── SaaSSettings - Workspace and account settings

Default Views

SaaSDashboard

Main product dashboard showing usage and team activity.

interface SaaSDashboardProps extends DashboardProps {
  /** Show usage metrics */
  showUsageMetrics?: boolean // default: true
  /** Show team activity */
  showTeamActivity?: boolean // default: true
  /** Show billing summary */
  showBillingSummary?: boolean // default: true
  /** Show plan limits */
  showPlanLimits?: boolean // default: true
}

Layout:

DashboardView (single)
├── MetricsPanel - Plan usage, team size, activity
├── ChartPanel - Usage trends over time
├── ActivityPanel - Recent team activity
└── StatsPanel - Quick stats and limits

Usage:

<SaaSDashboard
  showUsageMetrics={true}
  showTeamActivity={true}
  showBillingSummary={true}
  showPlanLimits={true}
/>

SaaSTeam

Team member management with roles and permissions.

interface SaaSTeamProps {
  /** Show pending invites */
  showInvites?: boolean // default: true
  /** Enable SSO configuration */
  enableSSO?: boolean // default: false
  /** Show role management */
  showRoles?: boolean // default: true
  /** Available roles */
  roles?: Array<{
    name: string
    permissions: string[]
  }>
}

Layout:

TeamView (column)
├── ToolbarPanel - Invite button, filters
├── TablePanel - Team members
│   ├── Avatar + Name
│   ├── Email
│   ├── Role
│   ├── Last active
│   └── Actions (edit, remove)
├── InvitesPanel - Pending invitations
│   ├── Email
│   ├── Role
│   ├── Sent date
│   └── Actions (resend, cancel)
└── DetailPanel - Member details
    ├── Profile info
    ├── Role editor
    ├── Activity log
    └── Danger zone (remove)

Usage:

<SaaSTeam
  showInvites={true}
  enableSSO={false}
  showRoles={true}
  roles={[
    { name: 'owner', permissions: ['*'] },
    { name: 'admin', permissions: ['read', 'write', 'invite'] },
    { name: 'member', permissions: ['read', 'write'] },
    { name: 'viewer', permissions: ['read'] }
  ]}
/>

SaaSBilling

Subscription and payment management.

interface SaaSBillingProps {
  /** Show usage-based billing */
  showUsage?: boolean // default: true
  /** Show invoice history */
  showInvoices?: boolean // default: true
  /** Show payment methods */
  showPaymentMethods?: boolean // default: true
  /** Enable plan changes */
  enablePlanChanges?: boolean // default: true
  /** Pricing tiers */
  pricingTiers?: Array<{
    name: string
    price: number
    interval: 'month' | 'year'
    features: string[]
  }>
}

Layout:

BillingView (single)
├── MetricsPanel - Current plan, next billing date, total
├── PlanPanel - Current plan details and upgrade options
│   ├── Plan name
│   ├── Price
│   ├── Features
│   └── Change plan button
├── UsagePanel - Usage-based metrics
│   ├── Resource usage
│   ├── Limits
│   └── Overage charges
├── InvoicesPanel - Invoice history
│   ├── Date
│   ├── Amount
│   ├── Status
│   └── Download
└── PaymentMethodsPanel - Saved payment methods
    ├── Card info
    ├── Default badge
    └── Actions (edit, delete, set default)

Usage:

<SaaSBilling
  showUsage={true}
  showInvoices={true}
  showPaymentMethods={true}
  enablePlanChanges={true}
  pricingTiers={[
    {
      name: 'Free',
      price: 0,
      interval: 'month',
      features: ['Up to 3 users', '100 items', 'Basic support']
    },
    {
      name: 'Pro',
      price: 29,
      interval: 'month',
      features: ['Unlimited users', '10,000 items', 'Priority support', 'Advanced analytics']
    },
    {
      name: 'Enterprise',
      price: 299,
      interval: 'month',
      features: ['Unlimited everything', 'SLA', 'Dedicated support', 'Custom integrations']
    }
  ]}
/>

SaaSIntegrations

Third-party integration management.

interface SaaSIntegrationsProps {
  /** Show integration marketplace */
  showMarketplace?: boolean // default: true
  /** Enable OAuth flows */
  enableOAuth?: boolean // default: true
  /** Show connected integrations */
  showConnected?: boolean // default: true
  /** Available integrations */
  integrations?: Array<{
    id: string
    name: string
    description: string
    icon: string
    category: string
    oauthUrl?: string
  }>
}

Layout:

IntegrationsView (column)
├── TabsPanel - Connected, Available, Categories
├── CardsPanel - Integration cards
│   ├── Icon + Name
│   ├── Description
│   ├── Category badge
│   └── Connect/Configure button
└── DetailPanel - Integration details
    ├── Overview
    ├── Configuration form
    ├── Test connection
    └── Disconnect button

Usage:

<SaaSIntegrations
  showMarketplace={true}
  enableOAuth={true}
  showConnected={true}
  integrations={[
    {
      id: 'slack',
      name: 'Slack',
      description: 'Send notifications to Slack channels',
      icon: 'slack-icon.svg',
      category: 'Communication',
      oauthUrl: 'https://slack.com/oauth/authorize'
    },
    {
      id: 'stripe',
      name: 'Stripe',
      description: 'Accept payments with Stripe',
      icon: 'stripe-icon.svg',
      category: 'Payment'
    }
  ]}
/>

SaaSSettings

Workspace and account settings.

interface SaaSSettingsProps extends SettingsProps {
  /** Show workspace settings */
  showWorkspace?: boolean // default: true
  /** Show billing settings */
  showBilling?: boolean // default: true
  /** Show danger zone */
  showDangerZone?: boolean // default: true
}

Layout:

SettingsView (single)
├── TabsPanel - General, Workspace, Billing, Security, Danger
├── GeneralPanel - Profile settings
├── WorkspacePanel - Workspace name, logo, domain
├── BillingPanel - Billing contact, tax ID
├── SecurityPanel - Password, 2FA, sessions
└── DangerPanel - Transfer ownership, delete workspace

Usage:

<SaaSSettings
  showWorkspace={true}
  showBilling={true}
  showDangerZone={true}
/>

Configuration

Multi-Tenancy

<SaaSApp
  config={{
    multiTenant: true,
    showWorkspaceSwitcher: true
  }}
>
  {/* Workspace isolation enabled */}
</SaaSApp>

Workspace Switcher

// Enable workspace switcher in header
<SaaSApp
  config={{
    showWorkspaceSwitcher: true
  }}
>
  <Shell>
    {/* Workspace dropdown appears in header */}
  </Shell>
</SaaSApp>

Pricing Tiers

<SaaSApp
  config={{
    pricingTiers: ['free', 'pro', 'enterprise']
  }}
>
  <SaaSBilling
    pricingTiers={[
      {
        name: 'Free',
        price: 0,
        interval: 'month',
        features: ['Basic features']
      },
      {
        name: 'Pro',
        price: 29,
        interval: 'month',
        features: ['All features']
      }
    ]}
  />
</SaaSApp>

Feature Flags

<SaaSApp
  config={{
    features: {
      analytics: true,
      apiAccess: false,
      customBranding: true,
      sso: false
    }
  }}
>
  {/* Features controlled by flags */}
</SaaSApp>

Auto-Wiring

SaaSApp components automatically wire to Payload collections:

ComponentCollectionPurpose
SaaSTeamteamMembersTeam member management
SaaS BillingsubscriptionsSubscription management
SaaSBillinginvoicesInvoice history
SaaSIntegrationsintegrationsIntegration connections

Collection Schemas

workspaces Collection:

{
  name: string
  slug: string
  logo?: string
  domain?: string
  plan: 'free' | 'pro' | 'enterprise'
  features: Record<string, boolean>
  ownerId: User
  createdAt: Date
}

teamMembers Collection:

{
  workspaceId: string
  userId: User
  role: 'owner' | 'admin' | 'member' | 'viewer'
  invitedBy: User
  joinedAt: Date
}

subscriptions Collection:

{
  workspaceId: string
  plan: string
  interval: 'month' | 'year'
  price: number
  status: 'active' | 'canceled' | 'past_due'
  currentPeriodEnd: Date
  customerId: string // Stripe customer ID
}

invoices Collection:

{
  workspaceId: string
  subscriptionId: string
  amount: number
  status: 'paid' | 'open' | 'void'
  dueDate: Date
  paidAt?: Date
  invoiceUrl: string
}

integrations Collection:

{
  workspaceId: string
  integrationId: string
  config: Record<string, any>
  accessToken?: string
  refreshToken?: string
  expiresAt?: Date
  enabled: boolean
}

Default navigation structure:

const navigation = [
  { path: '/', label: 'Dashboard', icon: 'LayoutDashboard' },
  // Product-specific views here
  { path: '/team', label: 'Team', icon: 'Users' },
  { path: '/billing', label: 'Billing', icon: 'CreditCard' },
  { path: '/integrations', label: 'Integrations', icon: 'Puzzle' },
  { path: '/settings', label: 'Settings', icon: 'Settings' },
]

Best Practices

Multi-Tenancy

  1. Workspace isolation - Always scope queries by workspace
  2. Role-based access - Enforce permissions per workspace
  3. Resource limits - Respect plan limits per workspace
  4. Tenant migration - Support workspace transfers
<SaaSApp
  config={{
    multiTenant: true,
    showWorkspaceSwitcher: true
  }}
/>

Team Management

  1. Invite flows - Email invitations with expiry
  2. Role hierarchy - Owner > Admin > Member > Viewer
  3. SSO support - Enable for enterprise plans
  4. Activity logs - Track member actions
<SaaSTeam
  showInvites={true}
  enableSSO={true}
  roles={[
    { name: 'owner', permissions: ['*'] },
    { name: 'admin', permissions: ['read', 'write', 'invite'] },
    { name: 'member', permissions: ['read', 'write'] }
  ]}
/>

Billing

  1. Transparent pricing - Show all charges clearly
  2. Usage tracking - Monitor plan limits
  3. Payment failures - Handle gracefully with retries
  4. Downgrade protection - Preserve data on plan changes
<SaaSBilling
  showUsage={true}
  showInvoices={true}
  enablePlanChanges={true}
/>

Integrations

  1. OAuth security - Use secure token storage
  2. Token refresh - Auto-refresh expired tokens
  3. Error handling - Graceful degradation
  4. Testing tools - Provide test connections
<SaaSIntegrations
  enableOAuth={true}
  showMarketplace={true}
/>

Examples

Minimal SaaS App

<SaaSApp name="My Product">
  <Shell>
    <SaaSDashboard />
  </Shell>
</SaaSApp>
<SaaSApp
  name="Acme Platform"
  config={{
    multiTenant: true,
    showWorkspaceSwitcher: true,
    showBilling: true,
    showTeam: true,
    showIntegrations: true,
    pricingTiers: ['free', 'pro', 'enterprise'],
    features: {
      analytics: true,
      apiAccess: true,
      customBranding: true,
      sso: true
    }
  }}
>
  <Shell>
    <Routes>
      <Route path="/" element={
        <SaaSDashboard
          showUsageMetrics={true}
          showTeamActivity={true}
          showBillingSummary={true}
        />
      } />
      <Route path="/team" element={
        <SaaSTeam
          showInvites={true}
          enableSSO={true}
          showRoles={true}
        />
      } />
      <Route path="/billing" element={
        <SaaSBilling
          showUsage={true}
          showInvoices={true}
          showPaymentMethods={true}
          enablePlanChanges={true}
        />
      } />
      <Route path="/integrations" element={
        <SaaSIntegrations
          showMarketplace={true}
          enableOAuth={true}
        />
      } />
      <Route path="/settings" element={
        <SaaSSettings
          showWorkspace={true}
          showBilling={true}
          showDangerZone={true}
        />
      } />
    </Routes>
  </Shell>
</SaaSApp>

On this page