Skip to main content
Rowboat uses a multi-stage build system with TypeScript compilation, esbuild bundling, and Electron Forge for packaging.

Build System Overview

The build system uses different tools for different parts:
Package manager: pnpm is required for the workspace:* protocol used in the monorepo.

Development Build

Quick Start

1

Install dependencies

2

Build workspace packages

Builds: shared → core → preload
3

Start development mode

Starts Vite dev server and Electron with hot-reload.

Available Scripts

Build Order

Packages must be built in dependency order:
Always build shared before core, and both before main. The npm run deps command handles this automatically.

Why This Order?

Each package depends on type definitions from upstream packages:

Main Process Bundle

The main process uses a two-stage build:

Stage 1: TypeScript Compilation

TypeScript compiles src/ to intermediate JavaScript with:
  • Target: ES2022
  • Module: ESNext
  • Type definitions: Generated

Stage 2: esbuild Bundling

The bundle.mjs script bundles everything into a single file:
Why bundle? pnpm uses symlinks for workspace packages. Electron Forge’s dependency walker can’t follow these symlinks. Bundling creates a single file with all code, eliminating the need for node_modules in the packaged app.

Renderer Bundle

The renderer uses Vite for both development and production:

Development

Vite provides:
  • Hot module replacement (HMR)
  • React Fast Refresh
  • Instant updates

Production

Vite outputs optimized assets:
  • Minified JavaScript
  • Code splitting
  • Hashed filenames for caching

Production Packaging

Electron Forge creates distributable packages.

Package (No Installer)

Creates an application bundle:

Make (With Installer)

Creates installers for distribution:

Forge Configuration

Packaging is configured in apps/main/forge.config.cjs:

Code Signing (macOS)

For production builds with code signing, set these environment variables:
Code signing is only required for public distribution. Local development and testing don’t require these variables.

Generating App-Specific Password

1

Sign in to Apple ID

2

Navigate to Security

Click “Sign-In and Security” → “App-Specific Passwords”
3

Generate password

Click ”+” to create a new app-specific password for “Electron Forge”
4

Save to environment

Build Troubleshooting

Workspace Dependencies Not Found

Solution: Build dependencies first

Main Process Not Updating

Problem: Changes to main process don’t appear in the app. Solution: Main process doesn’t hot-reload. Restart the dev server:

Preload Script Not Loading

Problem: Preload APIs not available in renderer. Solution: Rebuild preload scripts:

TypeScript Errors

Problem: Type errors in IDE but code runs. Solution: Rebuild packages to regenerate type definitions:

Clean Build

If you encounter persistent issues, try a clean build:

Build Performance

Development

  • Cold start: ~15-30 seconds (includes npm run deps)
  • Hot reload (renderer): Instant with Vite HMR
  • Rebuild after changes: Depends on what changed
    • Renderer only: Instant (HMR)
    • Preload/shared/core: ~5-10 seconds + restart
    • Main process: ~5-10 seconds + restart

Production

  • Package (no installer): ~30-60 seconds
  • Make (with installer): ~60-120 seconds
  • Code signing: Adds ~30-60 seconds
Build times vary based on hardware and platform. Apple Silicon Macs are generally faster than Intel.