Skip to main content
Rowboat is an Electron desktop application built as a nested pnpm monorepo. The architecture separates concerns across three Electron processes (main, renderer, preload) and shared business logic packages.

Architecture Diagram

Electron Process Architecture

The main process (apps/main/src/main.ts) is the Node.js backend that:
  • Creates and manages browser windows
  • Handles all file system and OS operations
  • Runs background services (Gmail sync, calendar sync, knowledge graph processing)
  • Exposes IPC handlers for renderer communication
  • Manages OAuth flows and external integrations
Key Characteristics:
  • Full Node.js access (fs, path, crypto, etc.)
  • Bundled with esbuild to single CommonJS file
  • No hot-reload in development (requires restart)
  • Entry: apps/main/src/main.ts
  • Output: .package/dist/main.cjs
Startup Sequence:
The renderer process (apps/renderer/src/main.tsx) is the UI layer that:
  • Renders the React application
  • Runs in a sandboxed browser environment
  • Cannot directly access Node.js APIs
  • Communicates with main via IPC (preload bridge)
Key Characteristics:
  • React 19 + Vite 7
  • TailwindCSS + Radix UI components
  • Hot-reload enabled in development
  • Sandboxed (no Node integration, context isolation enabled)
  • Entry: apps/renderer/src/main.tsx
  • Output: apps/renderer/dist/
Security Configuration:
The preload scripts (apps/preload/src/preload.ts) provide a secure bridge:
  • Run before renderer code loads
  • Have access to both Node.js and browser APIs
  • Expose safe IPC methods via contextBridge
  • Validate all requests/responses with Zod schemas
Key Characteristics:
  • TypeScript with strict validation
  • Exposes only whitelisted IPC channels
  • No direct Node.js access from renderer
  • Entry: apps/preload/src/preload.ts
  • Output: apps/preload/dist/preload.js
IPC Bridge Example:

Package Architecture

Rowboat uses a nested pnpm workspace structure where the Electron app (apps/x) is itself a monorepo with shared packages.

Workspace Structure

Build Dependencies

The npm run deps command builds packages in order: shared → core → preload. Always run this after modifying shared packages.

Package Responsibilities

Purpose: Type definitions, Zod schemas, and utilities shared across all packages.Contents:
  • IPC channel definitions and validators
  • Shared TypeScript types
  • Zod schemas for runtime validation
  • Common utilities
Location: apps/x/packages/shared/src/Usage:
Purpose: Core business logic, AI integration, OAuth, and background services.Contents:
  • Knowledge graph processing
  • AI/LLM integration (Vercel AI SDK)
  • OAuth client implementations
  • Background sync services (Gmail, Calendar, Fireflies)
  • Configuration management
  • Agent runtime
Location: apps/x/packages/core/src/Key Modules:
  • knowledge/ - Knowledge graph and entity extraction
  • models/ - LLM provider integration
  • auth/ - OAuth 2.0 + PKCE flows
  • services/ - Background services
  • runs/ - Agent execution runtime

Build System

Why esbuild Bundling?

pnpm uses symlinks for workspace packages. Electron Forge’s dependency walker cannot follow these symlinks during packaging. esbuild bundles everything into a single file, eliminating the need for node_modules in the packaged app.

Build Tools

Development Commands

Background Services

Rowboat runs several long-lived background services in the main process: Service Initialization:

Tech Stack Summary

Key Design Principles

  • No Node.js in renderer: All Node operations go through IPC
  • Context isolation: Preload context separated from renderer
  • Sandbox enabled: Renderer runs in Chromium sandbox
  • Validated IPC: All messages validated with Zod schemas
  • Single-file bundling: esbuild creates one main.cjs file
  • Hot reload: Renderer changes reload instantly
  • Lazy loading: React components lazy-loaded where possible
  • Efficient IPC: Minimal data transfer between processes
  • Type safety: Full TypeScript coverage
  • Schema validation: Runtime validation with Zod
  • Fast rebuilds: Vite HMR for instant feedback
  • Monorepo structure: Shared code in @x packages

Next Steps