Unclassified
Quick Start: Tenant Routing System
What's New
Your IntegrateWise app now has multi-tenant support via subdomains. Each tenant gets:
- ✅ Branded landing page at their own subdomain
- ✅ Customizable colors, logo, and copy
- ✅ Industry-specific content (SaaS/Healthcare/Fintech)
- ✅ Automatic tenant scoping for all features
Test It Locally
Start the dev server
cd apps/web
npm run dev
Visit the demo workspaces
Open these URLs in your browser (on localhost:3000):
| URL | Workspace | Industry | Color |
|---|---|---|---|
| http://saas-corp.localhost:3000 | SaaS Corp | SaaS | Blue 🚀 |
| http://healthtech.localhost:3000 | HealthTech Inc | Healthcare | Green ⚕️ |
| http://fintech-solutions.localhost:3000 | Fintech Solutions | Fintech | Purple 💰 |
| http://app.localhost:3000 | Workspace Picker | Hub | Default |
Try it out
Each landing page has:
- Navigation with tenant logo and sign-in
- Hero section with industry-specific headline
- Features grid showing key capabilities
- Industry section with relevant stats
- Call-to-action buttons
- Footer with links
Test flows
Not signed in:
- Click "Get Started" or "Sign In" → redirects to
/auth/sign-in
Signed in, not onboarded:
- Click any CTA → redirects to
/onboarding
Signed in, onboarded:
- Click any CTA → redirects to
/work
Try tenant picker:
- Visit http://app.localhost:3000 → see all workspaces
- Click on any workspace card → navigates to subdomain
How It Works
Subdomain Resolution
Request: saas-corp.localhost:3000
↓
Middleware reads Host header
↓
Extracts "saas-corp" subdomain
↓
Looks up tenant in DataProvider
↓
Injects X-Tenant-Slug & X-Tenant-Id headers
↓
Routes to (tenant) route group
↓
TenantProvider loads tenant data
↓
Landing page gets branding from tenant.branding
↓
CSS variables apply colors & logo
↓
Page renders with industry-specific copy
Available Hooks
// In any client component inside (tenant) route group:
const tenant = useTenant();
return (
<div>
<h1>{tenant?.name}</h1>
<p>{tenant?.branding?.tagline}</p>
<button style={{ background: tenant?.branding?.primaryColor }}>
Click me
</button>
</div>
);
}
File Structure
apps/web/
├── middleware.ts # Subdomain routing
├── lib/
│ ├── context/
│ │ └── tenant-context.tsx # React context for tenant
│ ├── data/
│ │ ├── types.ts # Extended Tenant type
│ │ └── in-memory-provider.ts # Seed data + methods
│ └── tenant-lookup.ts # (Optional) Lookup utility
├── components/
│ └── tenant/
│ ├── landing-page.tsx # Per-tenant landing page
│ └── tenant-picker.tsx # Workspace picker
└── app/
├── (tenant)/
│ ├── layout.tsx # Tenant context wrapper
│ ├── page.tsx # Landing route
│ └── onboarding/ # Tenant-scoped
│ └── work/ # Tenant-scoped
└── app/
└── page.tsx # Workspace picker
Customizing Tenants
Add a new tenant
Edit lib/data/in-memory-provider.ts:
const SEED_TENANTS: Record<string, Omit<Tenant, "id">> = {
"my-company": {
name: "My Company",
slug: "my-company",
industry: "saas",
environment: "customer-zero",
status: "active",
branding: {
logoUrl: "🎉",
primaryColor: "#EC4899",
backgroundColor: "#FCE7F3",
tagline: "Custom tagline here",
},
landing: {
headline: "Custom headline",
subhead: "Custom subheading",
featuredPluginIds: [],
featuredAgentIds: [],
},
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
// ... other tenants
};
Then restart dev server and visit:
http://my-company.localhost:3000
Customize branding
Update the branding object:
logoUrl: emoji or image URLprimaryColor: hex color (e.g., "#3B82F6")backgroundColor: hex color (e.g., "#F0F9FF")tagline: short tagline
Customize landing copy
Update the landing object:
headline: main headingsubhead: subheadingfeaturedPluginIds: array of plugin IDs to highlightfeaturedAgentIds: array of agent IDs to highlight
Slug Requirements
Slugs must be:
- ✅ Lowercase alphanumeric + hyphens:
my-company,saas-corp - ✅ 2-63 characters long
- ✅ No leading/trailing hyphens
- ❌ Not reserved: www, app, api, admin, docs, localhost, staging, dev
- ❌ Not already taken
Use the validation method:
const provider = getDataProvider();
const isValid = await provider.tenants.validateSlug("my-company");
// Returns true if valid and available
Production Readiness
What's ready for production:
- ✅ Subdomain routing
- ✅ Tenant context propagation
- ✅ Branding system
- ✅ Landing page components
- ✅ Error handling & fallbacks
What needs work for production:
- ⚠️ Move to persistent database (Neon PostgreSQL)
- ⚠️ Add admin UI for tenant provisioning
- ⚠️ Implement custom domain support (CNAME)
- ⚠️ Add caching layer (Redis) for slug lookups
- ⚠️ Set up RLS policies on database for tenant isolation
- ⚠️ Add audit logging for tenant operations
See TENANT_ROUTING_IMPLEMENTATION.md for full details.
Troubleshooting
Subdomain not resolving
- Check
/etc/hostson Mac/Linux orC:\Windows\System32\drivers\etc\hostson Windows - Add:
127.0.0.1 saas-corp.localhost - Restart browser
Or use the browser's developer tools to test:
// In console:
console.log(window.location.hostname); // should show subdomain
Branding not applying
- Check browser DevTools → Elements tab
- Look for
--primary-colorCSS variable on root element - Verify tenant data loaded: check
useTenant()return value - Check network tab: confirm X-Tenant-Slug header sent
Tenant not found
- Check DataProvider has tenant slug:
npm run devand check console - Verify slug matches exactly (case-sensitive)
- Check reserved list in
middleware.ts - Try accessing tenant picker first: http://app.localhost:3000
Next Features to Build
Suggested Enhancements
-
Admin Dashboard
- Create/edit/delete tenants
- Manage branding
- View usage stats
- Team member management
-
Custom Domains
- Support CNAME mappings (acme.com → acme.integratewise.com)
- DNS validation
- SSL certificate provisioning
-
Database Integration
- Migrate from in-memory to Neon
- Add Redis caching
- Implement RLS policies
-
Advanced Branding
- Upload custom fonts
- Design theme builder
- Custom CSS injection
-
Analytics
- Workspace creation tracking
- Usage metrics per tenant
- Admin reporting dashboard
Documentation
- Full Details: See
TENANT_ROUTING_IMPLEMENTATION.md - Architecture: See
TENANT_ARCHITECTURE.md - Delivery: See
DELIVERY_SUMMARY.md
Support
For questions or issues:
- Check the architecture diagrams in
TENANT_ARCHITECTURE.md - Review the data flow section in
DELIVERY_SUMMARY.md - Check component source code (well-commented)
- Test with the seed data tenants first
Happy multi-tenant building! 🚀