Dashboard Architecture
How the Next.js Dashboard communicates with the Go backend
Last Updated: January 25, 2026
Overview
The Fulcrum Dashboard is a Next.js 14 application that provides the admin UI for managing AI agent governance. It communicates with the Go backend via API routes that proxy requests to gRPC services or the MCP server.
Architecture Diagram
Browser Next.js Server Go Backend
┌────────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ │ │ │ │ │
│ React UI │──HTTP────▶│ /api/* routes │──gRPC────▶│ fulcrum-server │
│ │ JSON │ │ Proto │ :50051 │
│ - Pages │ │ - agents │ │ │
│ - Components │ │ - traces │ │ - AgentService │
│ - Hooks │ │ - events │ │ - BrainService │
│ │ │ │ │ │
│ Demo Mode │ │ /api/* routes │──MCP─────▶│ MCP Server │
│ Context │ │ │ JSON-RPC │ :8080 │
│ (Client) │ │ - policies │ │ │
│ │ │ - budgets │ │ - policies │
│ │ │ - keys │ │ - budgets │
│ │ │ - approvals │ │ - keys │
└────────────────┘ └─────────────────┘ └──────────────────┘
│ │
│ │
│ localStorage ├── isClerkEnabled()?
│ fulcrum_demo_mode │ ├── Yes → Call backend (gRPC/MCP)
│ │ └── No → Return mock data (some routes)
└────────────────────────────┘
Authentication Modes
The dashboard supports multiple authentication modes for different environments:
| Mode | Clerk Config | MOCK_AUTH | Demo Mode | API Behavior |
|---|---|---|---|---|
| Production | ✅ Keys set | false |
false |
gRPC/MCP calls, real data |
| Mock Auth | ❌ No keys | true |
false |
Mock user context, backend calls |
| Demo Mode | Any | Any | true (client) |
Client shows demo data |
| No Backend | ❌ No keys | false |
false |
API returns mock data* |
*Note: Only routes that check isClerkEnabled() at the start return mock data.
Auth Configuration Files
| File | Purpose |
|---|---|
lib/auth-config.ts |
isClerkEnabled(), isMockAuthEnabled(), MOCK_USER |
lib/grpc-client.ts |
gRPC client factory with connection handling |
lib/mcp-client.ts |
MCP client for policy/budget operations |
isClerkEnabled() Logic
// lib/auth-config.ts
export const isClerkEnabled = (): boolean => {
// Mock auth mode bypasses Clerk entirely
if (isMockAuthEnabled()) {
return false;
}
// Use publishable key as source of truth
return !!process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY;
};
API Routes Reference
Routes with Mock Support
These routes check isClerkEnabled() and can return mock/demo data when Clerk is not configured:
| Route | Backend | Mock Behavior |
|---|---|---|
/api/agents |
gRPC (AgentService) | Returns demo agents from data/demo/agents.ts |
/api/policies |
MCP | Uses mock tenant, calls MCP (needs backend) |
/api/budgets |
MCP | Uses mock tenant, calls MCP (needs backend) |
/api/approvals |
MCP | Uses mock tenant, calls MCP (needs backend) |
/api/keys |
MCP | Uses mock tenant, calls MCP (needs backend) |
Routes Without Mock Support
These routes require a running backend:
| Route | Backend | Notes |
|---|---|---|
/api/traces |
Direct PostgreSQL | Queries DB directly, no auth check |
/api/events |
Direct PostgreSQL | Queries DB directly |
/api/audit-logs |
Direct PostgreSQL | Queries DB directly |
Demo Mode (Client-Side)
Demo mode is a client-side only feature that shows sample data without any backend calls.
How It Works
- User toggles demo mode via
DemoTogglecomponent - State stored in
localStoragekey:fulcrum_demo_mode useDemoMode()hook provides context to all components- When enabled, data hooks return demo data instead of fetching
Key Files
| File | Purpose |
|---|---|
lib/hooks/useDemoMode.tsx |
Demo mode context provider and hook |
data/demo/index.ts |
Demo data exports |
data/demo/agents.ts |
Demo agent data |
data/demo/policies.ts |
Demo policy data |
data/demo/helpers.ts |
Time helpers for realistic timestamps |
Demo Mode vs Mock Auth
| Aspect | Demo Mode | Mock Auth |
|---|---|---|
| Location | Client-side (browser) | Server-side (API routes) |
| Data Source | Static demo data | Backend with mock tenant |
| Backend Required | No | Yes |
| Use Case | Demos, screenshots | E2E tests, local dev |
Data Flow Patterns
Pattern 1: gRPC Routes (Agents)
Browser → /api/agents → getAgentServiceClient() → gRPC → fulcrum-server
↓
isClerkEnabled()?
↓
No → Return demo data
Pattern 2: MCP Routes (Policies, Budgets)
Browser → /api/policies → getMCPClient() → HTTP → MCP Server
↓
isClerkEnabled()?
↓
No → Use MOCK_USER tenant, still call MCP
Pattern 3: Direct DB Routes (Traces)
Key Implementation Details
gRPC Client Setup
// lib/grpc-client.ts
export function getAgentServiceClient(): AgentServiceClient {
const channel = new ChannelCredentials.createInsecure();
return new AgentServiceClient(
process.env.GRPC_ENDPOINT || 'localhost:50051',
channel
);
}
MCP Client Setup
// lib/mcp-client.ts
export function getMCPClient(): MCPClient {
return new MCPClient({
endpoint: process.env.MCP_ENDPOINT || 'http://localhost:8080',
});
}
Mock Tenant Pattern
All routes that need tenant isolation use this pattern:
async function getTenantId(): Promise<{
tenantId: string;
userId: string | null;
error?: NextResponse;
}> {
// When Clerk is disabled, use mock user
if (!isClerkEnabled()) {
return { tenantId: MOCK_USER.tenantId, userId: MOCK_USER.userId };
}
const { userId, orgId } = await auth();
// ... Clerk auth logic
}
Environment Variables
| Variable | Purpose | Required |
|---|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY |
Clerk public key | For production |
CLERK_SECRET_KEY |
Clerk secret key | For production |
MOCK_AUTH |
Enable mock auth mode | For E2E tests |
GRPC_ENDPOINT |
gRPC server address | Yes |
MCP_ENDPOINT |
MCP server address | Yes |
DATABASE_URL |
PostgreSQL connection | Yes |
Troubleshooting
"Failed to connect to gRPC" in E2E Tests
Cause: Route doesn't check isClerkEnabled() before calling gRPC.
Fix: Add mock data fallback at the start of the route handler.
Demo mode shows real data
Cause: Demo mode is client-side only. The page might be server-rendered.
Fix: Ensure the component uses useDemoMode() hook and conditionally renders.
Auth works locally but fails in CI
Cause: MOCK_AUTH=true not set in CI environment.
Fix: Add MOCK_AUTH=true to CI environment variables.
Related Documentation
- System Overview - Backend architecture
- Data Architecture - Database design
- API Overview - API reference
- Deployment Architecture - Infrastructure
Back to Documentation Index