Your own walled account

Every builder gets their own account with its own web address, its own people, and its own data that nobody outside the company can reach.

What it is

One row in the organizations table is one building company. Every tenant-scoped table in the database carries an org_id column, every request resolves exactly one acting org, and every read and write is filtered to it server-side. The account has a slug that becomes a subdomain, an owner, a plan, a status, and its own branding, settings, pricing, crews, contacts and money.

Also called: sub-account · multi-tenant · separate company account · my own dashboard · tenant

See it
Your own walled account
Day rate
$600
Days figured
10
Crew size
3
Fuel & equipment
$300
Finished 2 days early — $1,400 back to the crew
Two browser windows side by side on two different subdomains showing two completely different pipelines with the same UI chrome. Rendered by the app shell (src/components/layout/AppShell.tsx) with the tenant name from AppContext. Sample data — no customer information appears here.
How it works
  1. 1Migration 013 created the organizations table and added an org_id column to every tenant-scoped table.
  2. 2The request host is resolved to an org: subdomain first (acme.leads2build.com), then verified custom domain.
  3. 3Middleware stamps x-org-id / x-org-slug onto the request so every downstream route knows which company it is serving.
  4. 4serverAuth.getAuthedUser resolves the acting org with a fixed precedence: impersonation target, subdomain, the user's own metadata org, then the linked Clerk organization.
  5. 5The /api/db proxy stamps that org_id onto every row written and appends .eq('org_id', …) to every row read.
Why we built it

The product started as one builder's dashboard, so 'the company' was implicit — it was whoever was logged in. Migration 013's header states the transition plainly: existing rows backfill to 'org_default' (the first account) 'so nothing breaks before the rest of the multi-tenant code lands.' Everything else in this domain exists because that transitional assumption kept resurfacing as a bug: a default org that silently caught rows, a URL that was trusted over a membership check, a cache that outlived a switch. serverAuth still carries the original note — orgId 'falls back to org_default … keeps the single-tenant flow working' — with the fallback now restricted to the platform owner alone, because for anyone else it meant landing in another company's data.

The problem
  • Two builders on one platform must never see each other's leads, prices, crews or money.
  • A single-tenant app can't be sold to a second customer without a boundary that the code enforces on every query.
  • Data written without a company stamp silently lands in whichever account the column default points at.
Sound familiar?
What you get
Your pipeline, pricing and customer list are readable only inside your account.
Your company has its own web address, branding and settings rather than a shared workspace.
Every query in the app is filtered by your account id server-side, not by a client-side filter you have to trust.
What's inside

See it on your own jobs

Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.

or keep browsing features →