TenantContext provides multi-tenant resolution at the application root level. It identifies the current box (gym) based on the hostname or query parameter and fetches box configuration before the user session is loaded.
Provider Setup
Wrap your application withTenantProvider at the root level, typically outside or alongside the AuthProvider.
The
TenantProvider should wrap the AuthProvider to ensure tenant context is available before authentication is initialized.Hook Usage
Access the tenant context using theuseTenant hook.
The
useTenant hook must be used within a TenantProvider. An error will be thrown if used outside the provider tree.State Properties
The context exposes the following state properties:The tenant slug extracted from the hostname (production) or query parameter (development).
- Returns a string slug if on a tenant subdomain/route
- Returns
nullif not in tenant mode (e.g., main app domain)
The full box configuration object fetched from the
boxes table based on the tenantSlug.Returns null if:- Not in tenant mode (
tenantSlugisnull) - Box not found in database
- Fetch operation failed
Convenience flag indicating whether the app is running in tenant mode.
trueiftenantSlug !== nullfalseif on the main app domain
Indicates whether the tenant box’s subscription is suspended or cancelled.Returns
true if tenantBox.subscription_status is:'suspended''cancelled'
Indicates whether the tenant slug was present but no matching box was found in the database.
trueif slug exists but box lookup failedfalseif box found or not in tenant mode
Indicates whether the tenant box data is currently being fetched.
trueduring initial box fetchfalseonce fetch completes (success or failure)- Always
falseif not in tenant mode
Multi-Tenant Architecture
TheTenantContext enables BoxApp to serve multiple gyms from a single application:
Tenant Resolution Flow
- Extract Slug: On app initialization,
getTenantSlug()determines if the current URL represents a tenant. - Fetch Box: If a slug is found, an anonymous query to Supabase fetches the box configuration.
- Provide Context: The box data is made available to all child components.
Anonymous Access
The box fetch is performed before authentication is initialized and uses an anonymous Supabase query.Your Supabase Row Level Security (RLS) policies must allow anonymous reads on the
boxes table for the slug column. This enables public access to box configuration data.Usage Patterns
Conditional Rendering Based on Tenant
Subscription Status Gating
Tenant Not Found Handling
Loading State Management
Integration with AuthContext
The tenant and auth contexts work together for complete multi-tenant authentication:tenantBoxId is passed to AuthProvider:
- New user registrations are automatically associated with this box
- OAuth flows reconcile the user’s box assignment
- Profile fetching validates box membership
TypeScript Types
Implementation Details
Best Practices
-
Provider Order: Always wrap
AuthProviderinsideTenantProviderto ensure tenant context is available first. -
Loading States: Check
isLoadingbefore rendering tenant-dependent UI to avoid flashing incorrect content. -
Error Boundaries: Wrap tenant-aware routes with error boundaries to gracefully handle
tenantNotFoundscenarios. -
Subscription Checks: Use
isSuspendedto gate access to premium features or show upgrade prompts. -
RLS Configuration: Ensure your Supabase RLS policies allow anonymous reads on the
boxestable for tenant resolution to work.