Blog
Jul 1, 2025 - 3 MIN READ
Subdomain-Based Multi-Tenancy in Nuxt

Subdomain-Based Multi-Tenancy in Nuxt

*By Sean Erick C. Ramones, Vue SME | JavaScript/TypeScript SME*

Sean Erick C. Ramones

Sean Erick C. Ramones

What is Multi-Tenancy?

Multi-tenancy is an architecture where a single app instance serves multiple clients (tenants). Each tenant behaves like it has its own isolated version of the app.

Benefits

  • Centralized maintenance
  • Efficient infrastructure usage
  • Per-tenant custom branding
  • Easier scaling and onboarding

Subdomain-Based Tenancy in Nuxt

You might have seen urls like this in Jira, Github, Slack, etc. Each tenant accesses the platform via their own subdomain, like:

mllr.preesh.com
acme.preesh.com
some-other-org.preesh.com

Tenant Middleware (Nuxt 3)

// middleware/tenant.ts
export default defineNuxtRouteMiddleware(() => {
  const host = useRequestHeaders()['host'] || '';
  const [subdomain] = host.split('.');
  const knownTenants = useRuntimeConfig().public.knownTenants || [];
  if (!knownTenants.includes(subdomain)) return navigateTo('/invalid-tenant');
  useState('tenant', () => subdomain);
});
// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/*': { middleware: ['tenant'] },
  },
  runtimeConfig: {
    public: {
      knownTenants: ['acme', 'globex']
    }
  }
});

Custom Branding Per Tenant

We can define per-tenant branding that influences UI themes, logos, and color schemes.

// composables/useTenantConfig.ts
export const useTenantConfig = () => {
  const tenant = useState('tenant');
  const map = {
    acme: { color: '#FF5733', logo: '/acme-logo.svg' },
    globex: { color: '#3333FF', logo: '/globex-logo.svg' }
  }; // Ideally pulled from a DB or config API
  return map[tenant.value];
};

Use this config in layout and theming logic for dynamic styles and assets.


Authentication and Role Management

Suggested Roles

  • HR Admin – Full platform access
  • Manager – Can send cards to direct reports
  • Employee – Read-only access to received cards

Role-Based Access Middleware

// middleware/role.ts
export default defineNuxtRouteMiddleware(() => {
  const user = useState('user').value;
  if (!user || user.role !== 'HR_ADMIN') return navigateTo('/unauthorized');
});

Security Strategies

To prevent cross-tenant data leakage and protect user data:

  • Tenant Isolation: Scope all database queries by tenant_id
  • Subdomain Cookies: Use tenant-specific cookies or headers
  • Rate Limiting: Apply tenant-specific rate limits
  • Session Protection: Do not share session tokens across tenants

Database Schema Design

Each key entity must include a tenant_id to isolate data:

CREATE TABLE users (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  role TEXT
);

CREATE TABLE cards (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  created_by UUID,
  message TEXT
);

Deployment Notes

  • Set up wildcard DNS: *.preesh.com
  • Use platforms like Vercel or Netlify for dynamic subdomain routing
  • Automate initial tenant provisioning (branding config, database seeding)

Additional Development Notes

Nuxt Labs recently joined Vercel, which may improve official support for:

  • Wildcard subdomain routing
  • Scheduled jobs or background workers
  • Tenant-based static rendering and caching

While current tenant configs (e.g., themes, logos) are manually defined, a future enhancement could allow tenants to edit their own configuration dynamically. This can be achieved using Nuxt Content as a lightweight CMS for managing per-tenant markdown/config content.

We could also allow tenants to add sub-pages, custom messages, or FAQ sections using markdown files per tenant.


Summary

This multi-tenant Nuxt setup enables Preesh to scale efficiently as a SaaS tool for HR departments, with:

  • Per-tenant isolation via subdomains
  • Role-based access control
  • Custom theming and branding
  • Secure and scalable architecture

Future upgrades may include self-service onboarding, tenant CMS integration, and more flexible customization per company.

Built with Nuxt UI • © 2026