LogoZero

Architecture Overview

System design and technical architecture patterns for scalable email client development.

Zero is built with a modern, scalable architecture that emphasizes performance, maintainability, and user experience. This document provides a comprehensive overview of the system design, technology choices, and architectural patterns.

High-Level Architecture

The architecture follows a microservices pattern with clear separation of concerns between frontend, backend, and external services.

Technology Stack

Frontend Technologies

React 19

UI library with latest features and concurrent rendering

TypeScript

Type-safe JavaScript with enhanced developer experience

React Router v7

Full-stack web framework with Vite integration for routing and SSR

Tailwind CSS

Utility-first CSS framework for rapid styling

Zustand

Lightweight state management without boilerplate

Shadcn UI

Beautifully designed components built with Radix UI and Tailwind CSS

Framer Motion

Production-ready motion library for React

Backend Technologies

Node.js

JavaScript runtime for server-side applications

TypeScript

Type-safe backend development

Hono

Fast, lightweight web framework for Cloudflare Workers

Drizzle ORM

Type-safe database toolkit with excellent TypeScript support

Better Auth

Modern authentication and authorization library

PostgreSQL

Primary database with Docker Compose setup for local development

Cloudflare Workers

Edge computing platform for global distribution

Infrastructure Components

Docker

Containerization for consistent deployments

Cloudflare

CDN, DNS, and edge services

Cloudflare Workers

Serverless runtime for edge computing

Cloudflare Durable Objects

Stateful serverless objects for real-time collaboration

Cloudflare Vectorize

Vector database for AI-powered search and recommendations

Cloudflare AI

AI inference at the edge for smart email features

System Components

The system is organized into distinct components, each handling specific aspects of the email client functionality.

Project Structure

Zero follows a monorepo structure with clear separation between applications, packages, and configuration.

docker-compose.db.yaml
turbo.json
pnpm-workspace.yaml

1. Frontend Architecture

State Management

We use Zustand for lightweight, performant state management without the complexity of Redux.

store/mail-store.ts
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'

interface MailState {
  emails: Email[]
  selectedEmail: Email | null
  filters: FilterState
  // Actions
  setEmails: (emails: Email[]) => void
  selectEmail: (email: Email) => void
  updateFilters: (filters: Partial<FilterState>) => void
}

export const useMailStore = create<MailState>()(
  devtools(
    persist(
      (set, get) => ({
        emails: [],
        selectedEmail: null,
        filters: { unread: false, starred: false },
        
        setEmails: (emails) => set({ emails }),
        selectEmail: (email) => set({ selectedEmail: email }),
        updateFilters: (filters) => 
          set({ filters: { ...get().filters, ...filters } }),
      }),
      { name: 'mail-store' }
    )
  )
)

Component Architecture

components/mail/email-list.tsx
import { memo } from 'react'
import { useMailStore } from '@/store/mail-store'
import { EmailListItem } from './email-list-item'
import { VirtualizedList } from '@/components/ui/virtualized-list'

export const EmailList = memo(() => {
  const { emails, selectEmail } = useMailStore()
  
  return (
    <VirtualizedList
      items={emails}
      renderItem={(email) => (
        <EmailListItem
          key={email.id}
          email={email}
          onSelect={() => selectEmail(email)}
        />
      )}
      itemHeight={80}
      className="flex-1"
    />
  )
})

2. Backend Architecture

The backend follows a service-oriented architecture with clear separation between routes, services, and data access layers.

Server Structure

drizzle.config.ts
wrangler.jsonc

Database Schema

We use Drizzle ORM for type-safe database operations with excellent TypeScript integration.

src/db/schema.ts
import {
  pgTableCreator,
  text,
  timestamp,
  boolean,
  integer,
  jsonb,
  primaryKey,
  unique,
} from 'drizzle-orm/pg-core';
import { defaultUserSettings } from '../lib/schemas';

export const createTable = pgTableCreator((name) => `mail0_${name}`);

export const user = createTable('user', {
  id: text('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  emailVerified: boolean('email_verified').notNull(),
  image: text('image'),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
  defaultConnectionId: text('default_connection_id'),
  customPrompt: text('custom_prompt'),
  phoneNumber: text('phone_number').unique(),
  phoneNumberVerified: boolean('phone_number_verified'),
});

export const session = createTable('session', {
  id: text('id').primaryKey(),
  expiresAt: timestamp('expires_at').notNull(),
  token: text('token').notNull().unique(),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
  ipAddress: text('ip_address'),
  userAgent: text('user_agent'),
  userId: text('user_id')
    .notNull()
    .references(() => user.id),
});

export const account = createTable('account', {
  id: text('id').primaryKey(),
  accountId: text('account_id').notNull(),
  providerId: text('provider_id').notNull(),
  userId: text('user_id')
    .notNull()
    .references(() => user.id),
  accessToken: text('access_token'),
  refreshToken: text('refresh_token'),
  idToken: text('id_token'),
  accessTokenExpiresAt: timestamp('access_token_expires_at'),
  refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
  scope: text('scope'),
  password: text('password'),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const userHotkeys = createTable('user_hotkeys', {
  userId: text('user_id')
    .primaryKey()
    .references(() => user.id),
  shortcuts: jsonb('shortcuts').notNull(),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const verification = createTable('verification', {
  id: text('id').primaryKey(),
  identifier: text('identifier').notNull(),
  value: text('value').notNull(),
  expiresAt: timestamp('expires_at').notNull(),
  createdAt: timestamp('created_at'),
  updatedAt: timestamp('updated_at'),
});

export const earlyAccess = createTable('early_access', {
  id: text('id').primaryKey(),
  email: text('email').notNull().unique(),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
  isEarlyAccess: boolean('is_early_access').notNull().default(false),
  hasUsedTicket: text('has_used_ticket').default(''),
});

export const connection = createTable(
  'connection',
  {
    id: text('id').primaryKey(),
    userId: text('user_id')
      .notNull()
      .references(() => user.id),
    email: text('email').notNull(),
    name: text('name'),
    picture: text('picture'),
    accessToken: text('access_token'),
    refreshToken: text('refresh_token'),
    scope: text('scope').notNull(),
    providerId: text('provider_id').$type<'google' | 'microsoft'>().notNull(),
    expiresAt: timestamp('expires_at').notNull(),
    createdAt: timestamp('created_at').notNull(),
    updatedAt: timestamp('updated_at').notNull(),
  },
  (t) => [unique().on(t.userId, t.email)],
);

export const summary = createTable('summary', {
  messageId: text('message_id').primaryKey(),
  content: text('content').notNull(),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
  connectionId: text('connection_id').notNull(),
  saved: boolean('saved').notNull().default(false),
  tags: text('tags'),
  suggestedReply: text('suggested_reply'),
});

export const note = createTable('note', {
  id: text('id').primaryKey(),
  userId: text('user_id')
    .notNull()
    .references(() => user.id, { onDelete: 'cascade' }),
  threadId: text('thread_id').notNull(),
  content: text('content').notNull(),
  color: text('color').notNull().default('default'),
  isPinned: boolean('is_pinned').default(false),
  order: integer('order').notNull().default(0),
  createdAt: timestamp('created_at').notNull().defaultNow(),
  updatedAt: timestamp('updated_at').notNull().defaultNow(),
});

export const userSettings = createTable('user_settings', {
  id: text('id').primaryKey(),
  userId: text('user_id')
    .notNull()
    .references(() => user.id)
    .unique(),
  settings: jsonb('settings').notNull().default(defaultUserSettings),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const writingStyleMatrix = createTable(
  'writing_style_matrix',
  {
    connectionId: text()
      .notNull()
      .references(() => connection.id, { onDelete: 'cascade' }),
    numMessages: integer().notNull(),
    style: jsonb().$type<unknown>().notNull(),
    updatedAt: timestamp()
      .defaultNow()
      .notNull()
      .$onUpdate(() => new Date()),
  },
  (table) => {
    return [
      primaryKey({
        columns: [table.connectionId],
      }),
    ];
  },
);

export const jwks = createTable('jwks', {
  id: text('id').primaryKey(),
  publicKey: text('public_key').notNull(),
  privateKey: text('private_key').notNull(),
  createdAt: timestamp('created_at').notNull(),
});

API Routes

src/routes/ai.ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import { requireAuth } from '../lib/auth'
import { OpenAIService } from '../services/openai'

const ai = new Hono()

// Compose email with AI
ai.post('/compose', 
  requireAuth,
  zValidator('json', z.object({
    prompt: z.string(),
    context: z.string().optional(),
  })),
  async (c) => {
    const userId = c.get('user').id
    const { prompt, context } = c.req.valid('json')
    
    const composition = await OpenAIService.composeEmail({
      userId,
      prompt,
      context,
    })
    
    return c.json({ composition })
  }
)

// Summarize email
ai.post('/summarize',
  requireAuth,
  zValidator('json', z.object({
    content: z.string(),
  })),
  async (c) => {
    const { content } = c.req.valid('json')
    
    const summary = await OpenAIService.summarizeEmail(content)
    
    return c.json({ summary })
  }
)

export default ai

3. MCP Service Integration

Zero uses the Model Context Protocol (MCP) for email operations, providing a standardized interface for AI agents to interact with email systems.

MCP Service Architecture

src/services/mcp-service/index.ts
import { MCPServer } from '@modelcontextprotocol/sdk/server.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { ListResourcesRequestSchema } from '@modelcontextprotocol/sdk/types.js'

export class ZeroMCPService {
  private server: MCPServer
  
  constructor() {
    this.server = new MCPServer(
      {
        name: 'zero-mcp',
        version: '1.0.0',
      },
      {
        capabilities: {
          resources: {},
          tools: {},
        },
      }
    )
    
    this.setupHandlers()
  }
  
  private setupHandlers() {
    // Email management tools
    this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
      return {
        resources: [
          {
            uri: 'zero://emails',
            name: 'Email Management',
            description: 'Access and manage emails',
          },
          {
            uri: 'zero://labels',
            name: 'Label Management', 
            description: 'Manage email labels and organization',
          },
        ],
      }
    })
  }
  
  async start() {
    const transport = new StdioServerTransport()
    await this.server.connect(transport)
  }
}

5. Authentication System

We use Better Auth for modern, secure authentication with OAuth providers and session management.

Better Auth Integration

src/lib/auth.ts
import { betterAuth } from "better-auth"
import { drizzleAdapter } from "better-auth/adapters/drizzle"
import { db } from "../db"
import * as schema from "../db/schema"

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schema,
  }),
  
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      scope: [
        'email',
        'profile',
        'https://www.googleapis.com/auth/gmail.readonly',
        'https://www.googleapis.com/auth/gmail.send',
        'https://www.googleapis.com/auth/gmail.modify'
      ]
    }
  },
  
  session: {
    expiresIn: 60 * 60 * 24 * 7, // 7 days
    updateAge: 60 * 60 * 24, // 1 day
  },
  
  plugins: [],
})

export const { GET, POST } = auth.handler

4. AI Integration

AI features are powered by multiple providers including OpenAI, Perplexity, and Cloudflare AI for enhanced email functionality.

AI Service Architecture

src/services/ai-service.ts
import { generateText } from 'ai'
import { openai } from '@ai-sdk/openai'
import { perplexity } from '@ai-sdk/perplexity'

export class AIService {
  static async composeEmail(params: {
    prompt: string
    context?: string
    style?: 'formal' | 'casual' | 'professional'
  }) {
    const { prompt, context, style = 'professional' } = params
    
    const systemPrompt = `You are an AI email assistant. Write a ${style} email based on the user's request.`
    
    const { text } = await generateText({
      model: openai('gpt-4'),
      system: systemPrompt,
      prompt: context ? `Context: ${context}\n\nRequest: ${prompt}` : prompt,
      maxTokens: 500,
    })
    
    return text
  }
  
  static async summarizeThread(emails: Array<{ subject: string; body: string }>) {
    const emailContent = emails
      .map(email => `Subject: ${email.subject}\nBody: ${email.body}`)
      .join('\n\n---\n\n')
    
    const { text } = await generateText({
      model: openai('gpt-4'),
      system: 'Summarize this email thread concisely, highlighting key points and action items.',
      prompt: emailContent,
      maxTokens: 200,
    })
    
    return text
  }
  
  static async searchWeb(query: string) {
    const { text } = await generateText({
      model: perplexity('llama-3.1-sonar-small-128k-online'),
      prompt: query,
      maxTokens: 1000,
    })
    
    return text
  }
}

Data Flow

Understanding the data flow helps in debugging and optimizing the system performance.

1. Email Access Flow

This sequence diagram shows how emails are accessed through the MCP service from external providers.

2. Email Composition Flow

Performance Optimizations

Performance optimizations are applied at every layer to ensure a responsive user experience.

Frontend Optimizations

Code Splitting

Route-based code splitting with React.lazy()

Virtual Scrolling

Efficient rendering of large email lists

Memoization

React.memo and useMemo for expensive computations

Image Optimization

Lazy loading and responsive images

Bundle Optimization

Tree shaking and chunk optimization

Backend Optimizations

Database Indexing

Optimized queries with proper indexes

Connection Pooling

Efficient database connection management

Caching

Redis caching for frequently accessed data

Background Jobs

Asynchronous processing for heavy operations

CDN

Static asset delivery via Cloudflare

Email Processing Optimizations

MCP Protocol Efficiency

Optimized MCP calls for minimal latency

OAuth Token Management

Efficient token refresh and caching

Batch Operations

Process multiple emails in single API calls

Smart Caching

Cache frequently accessed emails and metadata

Security Architecture

Security is paramount in email client architecture. Multiple layers of protection ensure data safety.

Scalability Considerations

The architecture is designed to scale from single-user installations to enterprise deployments.

Horizontal Scaling Strategy

Stateless Design

Servers can be scaled horizontally without session dependencies

Load Balancing

Distribute traffic across multiple instances

Database Scaling

Read replicas and sharding strategies

Microservices

Service-oriented architecture for independent scaling

Caching Strategy

Multi-level Caching - Browser, Cloudflare CDN, and application caching
OAuth Token Caching - Secure token storage and refresh management
Email Metadata Caching - Cache frequently accessed email headers and labels
Static Asset Caching - Long-term caching for static resources via Cloudflare