# Building a Multi-Tenant SaaS Platform with Next.js

Multi-tenant SaaS (Software as a Service) platforms allow multiple clients (tenants) to share a single application while maintaining separation of their data and configurations. In this guide, we will explore how to build a multi-tenant SaaS platform using Next.js, leveraging its middleware and dynamic routing capabilities.

---

## Key Concepts in Multi-Tenancy

### 1\. **Tenant Identification**

Each request must be associated with a specific tenant. This can be done through:

* Subdomains (e.g., `tenant1.example.com`)
    
* Path-based routing (e.g., `example.com/tenant1`)
    
* Custom headers (e.g., `X-Tenant-ID`)
    

### 2\. **Tenant Isolation**

Ensure data isolation between tenants. This involves:

* Separate database schemas or collections per tenant
    
* Scoped configurations for themes, permissions, or features
    

### 3\. **Custom Branding**

Allow tenants to customize the application, such as uploading logos or changing colors, while sharing the same codebase.

---

## Setting Up Dynamic Routing in Next.js

Dynamic routing in Next.js enables tenant-specific pages. Let’s implement a path-based routing structure.

### Folder Structure

```typescript
src
├── app
│   ├── [tenant]
│   │   ├── dashboard
│   │   │   └── page.tsx
│   │   ├── settings
│   │   │   └── page.tsx
│   ├── middleware.ts
```

In this structure:

* `[tenant]` is a dynamic segment that matches tenant identifiers.
    
* Pages like `/[tenant]/dashboard` and `/[tenant]/settings` serve tenant-specific content.
    

### Dynamic Routes

Create tenant-specific pages using dynamic segments:

```typescript
import { useRouter } from 'next/navigation';

export default function DashboardPage() {
  const router = useRouter();
  const { tenant } = router.query;

  return (
    <div>
      <h1>Welcome, {tenant}</h1>
      <p>This is the dashboard for tenant: {tenant}</p>
    </div>
  );
}
```

---

## Using Middleware for Tenant Identification

Middleware in Next.js can intercept requests and perform tasks such as tenant identification and redirection.

### Middleware Example

Create a `middleware.ts` file in the `app` directory:

```typescript
import { NextResponse } from 'next/server';

export function middleware(req) {
  const url = req.nextUrl;
  const tenant = url.pathname.split('/')[1];

  if (!tenant) {
    // Redirect to a generic landing page if no tenant is specified
    return NextResponse.redirect(new URL('/landing', req.url));
  }

  // Add tenant to the request headers for downstream processing
  req.headers.set('x-tenant-id', tenant);

  return NextResponse.next();
}

export const config = {
  matcher: '/:path*',
};
```

This middleware:

1. Extracts the tenant from the URL path.
    
2. Redirects users without a tenant to a landing page.
    
3. Adds the tenant identifier to the request headers for further use.
    

---

## Data Isolation for Tenants

### Database Design

* **Single Database with Tenant ID**: Add a `tenantId` field to each record.
    
* **Separate Databases or Schemas**: Use a unique database or schema for each tenant.
    

### Fetching Tenant Data

Modify API calls to include tenant-specific filters:

```typescript
export default async function handler(req, res) {
  const tenantId = req.headers['x-tenant-id'];

  // Fetch data scoped to the tenant
  const data = await fetchDataForTenant(tenantId);

  res.status(200).json(data);
}
```

---

## Custom Branding and Configurations

Allow tenants to upload their own assets or set configurations.

### Example: Tenant Themes

#### Define Theme Configurations

```typescript
const tenantThemes = {
  tenant1: { primaryColor: '#ff0000', logo: '/logos/tenant1.png' },
  tenant2: { primaryColor: '#0000ff', logo: '/logos/tenant2.png' },
};
```

#### Apply Themes in Components

```typescript
import { useRouter } from 'next/router';

export default function Header() {
  const router = useRouter();
  const { tenant } = router.query;

  const theme = tenantThemes[tenant] || tenantThemes['default'];

  return (
    <header style={{ backgroundColor: theme.primaryColor }}>
      <img src={theme.logo} alt={`${tenant} logo`} />
    </header>
  );
}
```

---

## Benefits of Using Next.js for Multi-Tenancy

1. **Simplified Routing**: Dynamic routing makes tenant-specific URLs easy to implement.
    
2. **Built-In Middleware**: Next.js middleware simplifies tenant identification and request handling.
    
3. **Scalable Architecture**: ISR and API routes support high traffic while maintaining performance.
    
4. **Customizable UI**: Tenant-specific branding and themes enhance the user experience.
    

---

## Conclusion

Building a multi-tenant SaaS platform with Next.js is efficient and scalable. By leveraging middleware and dynamic routing, you can create tenant-specific experiences while maintaining a shared codebase. With proper database design and configuration management, you can ensure data isolation and customization for each tenant, paving the way for a robust and flexible SaaS application.
