Getting started

Configuration

All configuration lives in two places: .env (secrets and service keys) and opsdash.config.ts (feature overrides and branding).

Environment variables

Required

VariableDescriptionSource
NEXT_PUBLIC_SUPABASE_URLSupabase project URLsupabase start or Dashboard → Settings → API
NEXT_PUBLIC_SUPABASE_ANON_KEYPublic anon keySame
SUPABASE_SERVICE_ROLE_KEYService role key — never expose to clientSame — click Reveal
NEXT_PUBLIC_APP_URLApp full URL, no trailing slashhttp://localhost:3000 for dev

Stripe (Billing)

VariableDescription
STRIPE_SECRET_KEYStripe secret key (sk_test_... or sk_live_...)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYStripe publishable key (pk_test_... or pk_live_...)
STRIPE_WEBHOOK_SECRETWebhook signing secret (whsec_...)
STRIPE_PRICE_PRO_MONTHLYPrice ID for Pro plan, monthly
STRIPE_PRICE_PRO_YEARLYPrice ID for Pro plan, yearly
STRIPE_PRICE_ENTERPRISE_MONTHLYPrice ID for Enterprise plan, monthly
STRIPE_PRICE_ENTERPRISE_YEARLYPrice ID for Enterprise plan, yearly

Email (Resend)

VariableDescription
RESEND_API_KEYResend API key — get at resend.com
RESEND_FROMOptional sender address — e.g. OpsDash <noreply@yourdomain.com>

If RESEND_API_KEY is not set, invitation emails are skipped silently. Invite links still work — share them manually.

Other variables

VariablePurpose
CRON_SECRETProtects cron endpoints — openssl rand -hex 32
PLATFORM_ADMIN_EMAILSComma-separated emails with platform admin access (case-sensitive)
VAPID_PUBLIC_KEYVAPID public key for web push — npx web-push generate-vapid-keys
VAPID_PRIVATE_KEYVAPID private key (server-side only)
NEXT_PUBLIC_VAPID_PUBLIC_KEYSame as VAPID_PUBLIC_KEY (needed client-side)
GOOGLE_GMAIL_CLIENT_IDGoogle OAuth client ID for Gmail sync
GOOGLE_GMAIL_CLIENT_SECRETGoogle OAuth client secret
OPENAI_API_KEYOpenAI API key (optional — AI features)

Stripe setup

1 — Create products and prices

In Stripe Dashboard → Products → Add product:

  1. Pro → Monthly $29/month → copy Price ID → STRIPE_PRICE_PRO_MONTHLY. Yearly $290/year STRIPE_PRICE_PRO_YEARLY.
  2. Enterprise → Monthly $99/month STRIPE_PRICE_ENTERPRISE_MONTHLY. Yearly $990/year STRIPE_PRICE_ENTERPRISE_YEARLY.

2 — Configure webhook

Stripe Dashboard → Developers → Webhooks → Add endpoint:

  • URL: https://yourdomain.com/api/webhooks/stripe
  • Events: checkout.session.completed, invoice.payment_succeeded, customer.subscription.updated, customer.subscription.deleted
  • Copy the signing secret → STRIPE_WEBHOOK_SECRET

For local testing:

stripe listen --forward-to localhost:3000/api/webhooks/stripe

Test card: 4242 4242 4242 4242, any future date, any CVC.

opsdash.config.ts

For private instance deployments, this is the only file a buyer needs to edit. It overrides modules, features, branding, and billing without touching application code.

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

export default defineConfig({
  branding: {
    name: 'ClientOS',
    logo: '/logos/client.png',
    primaryColor: '#1a56db',
  },
  modules: {
    crm: { enabled: true },
    projects: { enabled: true },
    automation: { enabled: false }, // disable entire module
    billing: { enabled: true },
  },
  features: {
    'crm:contacts': {
      usageLimit: { free: 500, pro: 25_000, enterprise: 'unlimited' },
    },
  },
  auth: {
    providers: ['email', 'google'],
  },
  nav: {
    order: ['dashboard', 'crm', 'projects', 'forms', 'settings'],
  },
});

Branding

  1. Set branding.name in opsdash.config.ts
  2. Replace public/logo.svg and public/logo-icon.svg
  3. Set branding.accentColor as HSL values (e.g. 221 83% 53%)

Full guide: Whitelabel configuration