Skip to main content

Architecture Overview

The Vertical Template follows a Backend-for-Frontend (BFF) pattern where the Next.js server acts as a secure proxy between the browser and backend APIs.

System Architecture

Key Concepts

1. Backend-for-Frontend (BFF) Pattern

The Next.js server acts as a secure proxy between the browser and backend APIs:

  • Security: Access tokens never exposed to browser JavaScript
  • CORS: Same-origin requests avoid cross-origin restrictions
  • Simplicity: Client code doesn't handle token management

All API calls flow through the catch-all route at /api/eai/[[...rest]]/route.ts.

2. Config-Driven UI

The UI is dynamically rendered from TypeScript configuration files:

// src/eai.config/tenants/my-tenant.config.ts
export const myTenantConfig: EAIConfig = {
tenantId: 'my-tenant',
displayName: 'My Application',

store: {
user: { initialState: { name: null }, persist: true },
},

layout: {
header: [{ component: 'Header', priority: 1 }],
middlePane: [{ component: 'Dashboard', priority: 1 }],
},
};

Benefits:

  • No code changes for different tenants
  • Rapid prototyping via configuration
  • Type-safe configuration with TypeScript

3. Multi-Tenant Architecture

Each tenant/customer gets isolated configuration:

  • Unique tenantId identifier
  • Custom branding and theming
  • Tenant-specific layout and components
  • Separate store slices and state

Switch tenants via ?tenant=tenant-id query parameter.

4. Zustand State Management

A unified store created dynamically from tenant config:

  • Dot-notation access: useStoreValue('user.profile.email')
  • Selective persistence: Per-slice persist: true/false
  • DevTools integration: Named actions visible in Redux DevTools

Request Flow

Authentication Flow

  • Session storage: HTTP-only cookie (JWT strategy)
  • Token storage: Encrypted in session, never exposed to client
  • Refresh: Automatic via Auth.js when token expires

Anonymous User Support

The template supports anonymous users via Client Credentials Flow:

  1. When no user session exists, proxy falls back to client credentials
  2. App authenticates with Entra using its own credentials
  3. Each app registration has one anonymous user associated with it
  4. Anonymous users have limited privileges (read-only, public data)

Use cases:

  • Public landing pages fetching non-sensitive data
  • Chat endpoint for unauthenticated users
  • Pre-authentication content loading

Integration Points

ServicePurposeEndpoint Pattern
Public APIOrchestration/api/eai/v3/orchestrate
EAI CMSData persistenceVia Public API
Azure AIAI operationsVia Public API
ChatConversational AI/api/eai/v3/chat (SSE streaming)

Platform & Services