Guides

Whitelabel guide

OpsDash can be fully white-labeled and resold as your own product — your logo, your colors, your domain, your pricing. This guide covers the complete configuration path.

What can be customized

ElementConfigurableHow
App nameYesopsdash.config.ts branding.name
LogoYesReplace public/logo.svg and public/logo-icon.svg
FaviconYesReplace public/favicon.ico
Primary color / brand paletteYesbranding.accentColor in config (HSL value)
Email sender nameYesRESEND_FROM env var
DomainYesDeploy to their domain
Pricing tiersYespackages/billing/src/config/plans.ts
Enabled modulesYesmodules.* in opsdash.config.ts
Feature limits per tierYesfeatures.* in opsdash.config.ts

Branding configuration

// opsdash.config.ts
import { defineConfig } from '@opsdash/config';

export default defineConfig({
  branding: {
    name: 'AgencyOS Pro',
    logo: '/logos/agencyos.png',  // place file in /public/logos/
    accentColor: '263 70% 50%',   // HSL without hsl() — drives all primary UI
  },
});

The app name appears in: sidebar header, browser tab title, invitation emails, notifications.

The primary color drives all highlighted UI elements: buttons, active nav items, badges, focus rings.

Module configuration

modules: {
  crm: { enabled: true },
  projects: { enabled: true },
  automation: { enabled: true },
  billing: { enabled: true }, // disable if client doesn't need Stripe
}

Disabled modules are completely hidden — they do not appear in the sidebar, search, or command palette.

Custom pricing tiers

Edit packages/billing/src/config/plans.ts to set workspace limits per tier. Update the Stripe Price IDs in .env to match your own products in the reseller's Stripe account.

// packages/billing/src/config/plans.ts
export function getPlanLimits(plan: SubscriptionPlan) {
  const limits = {
    free:       { members: 3, storage_mb: 500, api_calls: 1000 },
    pro:        { members: 20, storage_mb: 25600, api_calls: 50000 },
    enterprise: { members: -1, storage_mb: -1, api_calls: -1 }, // -1 = unlimited
  };
  return limits[plan];
}

Emails

Set RESEND_FROM in .env:

RESEND_FROM="AgencyOS Pro <noreply@yourdomain.com>"

This sets the sender name and address for all transactional emails (invitations, notifications, password resets).

Hiding the OpsDash attribution

If your license includes removal of attribution, locate the footer component in apps/web/src/components/layout/sidebar.tsx and remove or replace the attribution text. No other components reference the product name directly — it comes from branding.name in config.

Deployment

Deploy the whitelabeled instance exactly as a private instance — see the Private instance guide. The only difference is the branding config and, if applicable, the reseller's own Stripe account.