
Portal
Sole Developer & Architect
The core SaaS platform powering the entire LaunchThat ecosystem. 36 plugin packages mount independently via a WordPress-inspired hooks system (addAction/addFilter). 18 Convex components provide domain isolation. Multi-tenant with subdomain + custom domain routing, org-scoped data isolation, and plugin-contributed RBAC. 108+ Next.js pages, 33 API routes, 200+ components.
CRM, LMS, e-commerce, support, calendar, discord, tasks, and more
Each domain (tenant, access, notifications, etc.) encapsulated as a Convex component
Admin, frontend, auth, and plugin-contributed routes
Clerk webhooks, Convex token bridging, plugin endpoints
The Problem
Building a SaaS platform that can serve multiple tenants with completely different feature sets, UI customizations, and billing requirements — without maintaining separate codebases for each customer. Each tenant needs their own subdomain, plugins, roles, and billing.
The Solution
Created a plugin architecture inspired by WordPress hooks (addAction/addFilter) where 36 plugin packages mount independently. Each tenant gets subdomain routing (including custom domains), org-scoped data via Convex with organizationId-based isolation, plugin-contributed role definitions, and Stripe billing. Convex components encapsulate each domain (CRM, LMS, e-commerce, support, etc.) with their own schemas and access patterns.
Technical Decisions
Key architecture decisions and their outcomes
WordPress-style hooks over hard-coded plugin registration
Needed plugins to contribute UI, routes, roles, and settings without modifying core code.
Built an addAction/addFilter hook system. Plugins register callbacks at install time and contribute menu items, role definitions, and settings pages via hooks.
Adding a new plugin is a single package import + hook registration. Zero core code changes.
Convex components for plugin data isolation
36 plugins with distinct schemas would create an unmaintainable single schema file.
Each plugin mounts as a Convex component with its own schema, queries, and mutations. The app's convex.config.ts composes them.
Clean domain boundaries. Plugin schemas are versioned independently. Core schema stays small.
Subdomain + custom domain multi-tenancy
Tenants need branded experiences on their own domains, not just subdomains.
Middleware extracts tenant from subdomain or custom domain via extractSubdomain/resolveTenantForRequest. Special 'auth' subdomain reserved for auth UI.
Tenants can use org.launchthat.app or their own custom domain. DNS verification handles the rest.
Engineering Details
- Plugin hook system: addAction/addFilter inspired by WordPress — plugins register callbacks for UI, routes, roles, settings
- 18 Convex components: core-tenant, access, notifications, support, socialfeed, LMS, disclaimers, affiliates, email, ecommerce, discord, CRM, tasks, vimeo, logs, onboarding, puck, migrations
- Multi-tenant routing: proxy.ts extracts subdomain from *.localhost, Vercel preview URLs, and production domains
- Plugin-contributed RBAC: plugins register role definitions via ADMIN_SETTINGS_ROLES_DEFINITIONS_FILTER hook
- Real-time presence: @convex-dev/presence for agent/user presence in support plugin
- Clerk + Convex auth bridging: TenantConvexProvider wraps protected routes with auth requirement
- Posts system: org-scoped content with post types, taxonomies, and per-org indexes
Key Highlights
- 36 plugin packages with WordPress-style hooks system (addAction/addFilter)
- 18 Convex components mounted for domain isolation
- Multi-tenant: subdomain + custom domain routing with org-scoped data
- Plugin-contributed RBAC with role scopes and permission levels
- Real-time presence via @convex-dev/presence
- 108+ Next.js pages, 33 API routes, 200+ components
- Clerk auth with Convex session bridging
- Stripe billing with entitlements per tenant
Tech Stack
Skills & Technologies
Related Articles
27 Apps, One Monorepo, Zero Regrets
We kept creating new repos for every project. Shared code drifted, configs diverged, and a single bug fix became a multi-day coordination exercise. Here is how a Turborepo monorepo fixed all of it.
Multi-Tenant SaaS: One Codebase, Wildly Different Products
Every customer wanted something different. The CRM customer needed contacts. The LMS customer needed courses. We were shipping bloated software that served nobody well. Here is how plugins fixed it.
From Monolith to 34 Plugins: How We Built an Extensible Platform Without Losing Our Minds
A customer asked for Monday.com integration. We could have hard-coded it into the core. Instead, we built a plugin system — and 18 months later we have 34 plugins serving 27 apps.
Portal V1: The WordPress Era — Building a SaaS on a CMS
Seven years ago I set out to build a multi-tenant platform on WordPress Multisite. All client data lived in one database, third-party glue held everything together, and a $100/mo host still could not keep up. Here is what I learned — and why I had to leave WordPress behind.
Portal V2: Learning to Build — Next.js, Drizzle, and the Long Migration
I replaced a WordPress multisite with a custom Next.js app backed by Postgres. Load times dropped from 8 seconds to under 2. But the platform was still fractured across a dozen third-party services, and every schema change was a deployment risk.
Portal V3: The Convex Migration — When the Backend Finally Clicked
Switching from Drizzle/Postgres to Convex collapsed the frontend-backend gap, doubled development speed, and let me cancel $230/month in third-party services. Here is how the migration worked and what it unlocked.
Portal V4: Bare Metal, Kubernetes, and True Multi-Tenancy
We moved off Vercel onto a 128GB bare-metal server. Each client now gets their own frontend containers, their own Convex backend instance, and their own database backups — orchestrated with Kubernetes and Helm. Here is how we got here and what we learned about owning infrastructure.
The Engineering Patterns Behind a 34-Plugin Platform
Every system in the LaunchThat ecosystem uses classical software engineering patterns — Strategy, Observer, Adapter, State Machine — and formal data structures. Here is how GoF patterns, SOLID principles, and CS fundamentals show up in production code.
Observability Across Five Production Systems
Monitoring, tracing, and instrumentation look different in every system we run. Here is what we actually measure, how we measure it, and what those measurements have caught — across Kubernetes infrastructure, integration pipelines, high-performance APIs, browser automation, and AI agents.
.NET vs Convex: When to Use a Traditional Backend vs a Reactive Platform
Both .NET and Convex can power production backends. After building multi-tenant SaaS platforms, high-performance APIs, and real-time dashboards across both, here is how I decide which one fits — and when the answer is both.