Skip to main content
Agora’s multi-tenant architecture enables a single codebase to power governance portals for multiple DAOs. Each tenant (DAO instance) has its own contracts, UI customization, and feature configuration, all controlled by environment variables and factory patterns.

Architecture Overview

The multi-tenant system is built on a singleton pattern that loads tenant-specific configurations at runtime based on the NEXT_PUBLIC_AGORA_INSTANCE_NAME environment variable.

Key Components

The tenant system consists of four main factories:
  1. TenantContractFactory - Loads blockchain contracts (governor, token, timelock)
  2. TenantUIFactory - Loads UI customization (colors, logos, copy)
  3. TenantTokenFactory - Configures governance token details
  4. TenantSlugFactory - Maps namespace to database slug

Configuration Structure

Environment Setup

Set the tenant namespace to determine which DAO configuration loads:
Available tenant namespaces include: optimism, ens, uniswap, etherfi, cyber, scroll, linea, boost, xai, b3, protocol-guild, towns, syndicate, and derive.

Contract Configuration

Each tenant defines its contract addresses in src/lib/tenant/configs/contracts/{namespace}.ts:

UI Configuration

Customize the UI for each tenant in src/lib/tenant/configs/ui/{namespace}.ts:

Adding a New Tenant

Follow these steps to add a new DAO to Agora:
1

Add namespace constant

Add your DAO to src/lib/constants.ts:
2

Create contract configuration

Create src/lib/tenant/configs/contracts/your-dao.ts with your contract addresses, ABIs, and delegation model.
3

Create UI configuration

Create src/lib/tenant/configs/ui/your-dao.ts with branding, colors, and feature toggles.
4

Update factories

Add cases to TenantContractFactory and TenantUIFactory in their respective files to handle your new namespace.
5

Configure environment

Set NEXT_PUBLIC_AGORA_INSTANCE_NAME=your-dao in your .env.local file.

Accessing Tenant Data

Access tenant configuration anywhere in your application:

Brand Name Mapping

Customize how your DAO name appears throughout the UI:

Delegation Models

Agora supports different delegation models per tenant:
  • FULL - Standard delegation (one delegatee)
  • PARTIAL - Split delegation across multiple delegates
  • ADVANCED - Alligator-style subdelegation chains

Database Namespacing

Each tenant has its own database schema for isolation:
Queries automatically scope to the tenant’s schema using the slug.

Feature Toggles

Control features per tenant using the toggle system:
Common toggles:
  • proposals - Enable/disable proposals page
  • delegates - Enable/disable delegates page
  • proposal-lifecycle - Draft proposal system
  • delegation-encouragement - Delegation CTAs
  • proposal-execute - On-chain execution

Multi-Chain Support

Tenants can support tokens across multiple chains:
Voting power is automatically aggregated across all configured chains. See src/lib/votingPowerUtils.ts:68 for implementation details.

Production Considerations

Environment configuration is loaded at build time. Changes to NEXT_PUBLIC_AGORA_INSTANCE_NAME require a rebuild.

Best Practices

  1. Separate deployments - Deploy each tenant to its own domain for isolation
  2. Environment variables - Use different .env files per tenant
  3. Database isolation - Ensure proper schema separation in your database
  4. Contract verification - Always verify mainnet/testnet contract addresses
  5. Testing - Test tenant switching locally before deploying

Example Deployment

Troubleshooting

Tenant not loading

Ensure your namespace is defined in TENANT_NAMESPACES and has cases in both factory classes.

Wrong contracts loading

Check NEXT_PUBLIC_AGORA_ENV - it controls prod vs dev contract addresses.

UI not updating

Restart dev server after changing tenant configuration files.