Skip to content

Architecture

PortBay is a native local development control plane built with Tauri 2, Rust, Svelte 5, Process Compose, Caddy, and mkcert.

mermaid
flowchart TB
  gui["PortBay GUI\nTauri 2 + Svelte 5"]
  cli["portbay CLI\nsame Rust core"]
  ipc["Tauri IPC\ninvoke + events"]
  core["portbay_lib\nshared library crate"]
  registry["registry/\natomic JSON store"]
  reconciler["reconciler/\ndirty-mark + tick loop"]
  pc_mod["process_compose/\nREST client + YAML gen"]
  caddy_mod["caddy/\nadmin API client"]
  certs_mod["certs\nmkcert wrapper"]
  hosts_mod["hosts/\n/etc/hosts manager"]
  mcp["crates/mcp\nportbay-mcp sidecar\n(MCP stdio server)"]
  helper["crates/hosts-helper\nportbay-hosts-helper sidecar\n(privileged helper)"]
  pc_bin["process-compose sidecar\nprocess supervision"]
  caddy_bin["caddy sidecar\nreverse proxy + TLS"]
  dnsmasq_bin["dnsmasq sidecar\nzero-config DNS"]
  projects["User project processes\npnpm dev · php-fpm · node · custom"]

  gui --> ipc
  cli --> core
  ipc --> core
  core --> registry
  core --> reconciler
  reconciler --> pc_mod
  reconciler --> caddy_mod
  reconciler --> certs_mod
  reconciler --> hosts_mod
  core --> mcp
  hosts_mod --> helper
  pc_mod --> pc_bin
  caddy_mod --> caddy_bin
  pc_bin --> projects
  caddy_bin --> projects

Component Choices

ComponentChoiceReason
Desktop shellTauri 2Small installer, Rust-native core, cross-platform path.
FrontendSvelte 5 + Tailwind 4Compiler-first reactivity and low runtime overhead.
Core languageRustSingle binary, strong process-control ergonomics, Tauri-native.
Process daemonProcess ComposeMature process supervision, health checks, logs, REST API.
Reverse proxyCaddy 2Runtime admin API, HTTPS-first model, simpler config than nginx.
Local TLSmkcertStandard local CA and certificate flow.
DNSdnsmasqZero-config wildcard routing for the whole .portbay.test suffix.
StorageJSON registryAuditable, portable, sufficient for one-user local state.

Cargo Workspace

The src-tauri/ directory is a Cargo workspace with three members:

CrateBinaryRole
portbay (root)portbay-app + portbayTauri GUI entry point and the standalone CLI. Both link against portbay_lib.
crates/mcpportbay-mcpMCP stdio server. Exposes PortBay's registry and lifecycle operations to AI agents. Ships as a Tauri sidecar (binaries/portbay-mcp).
crates/hosts-helperportbay-hosts-helperPrivileged helper that applies /etc/hosts writes without prompting for a sudo password on every operation. Ships as a Tauri sidecar (binaries/portbay-hosts-helper).

portbay_lib is the shared library crate (the [lib] entry of the root package). The mcp feature flag is off in GUI/CLI builds; crates/mcp enables it when it depends on the root package, so the MCP stack and its rmcp/schemars dependency tree are never compiled into the app itself.

Bundled Sidecars

Tauri's externalBin bundles the following binaries inside PortBay.app:

BinaryPurpose
process-composeProject process supervision
caddyReverse proxy and local HTTPS
mkcertLocal CA and certificate issuance
mailpitLocal SMTP/web mail catcher
cloudflaredTunnel support
dnsmasqWildcard DNS resolver
portbay-hosts-helperPrivileged /etc/hosts helper
portbay-mcpMCP stdio server for AI agents

Reconcile Loop

The reconciler drives the live system toward the on-disk registry. It runs as a background tokio task and fires on three triggers:

  1. CRUD commands — any save_registry call marks the reconciler dirty. The next tick runs asynchronously so command responses return before reconciliation completes (optimistic lifecycle).
  2. Cold boot — one tick fires after both Process Compose and Caddy sidecars are up.
  3. Periodic safety tick — every 30 seconds, to catch drift from CLI writes or external edits.

Multiple mark_dirty signals within one tick window coalesce (tokio Notify stores at most one permit).

Each tick runs four sub-reconcilers in order:

Sub-reconcilerWhat it does
certsIssues or renews mkcert certificates for projects that need them.
pcRegenerates process-compose.yaml from the registry and restarts the daemon when the hash changes.
caddyPOSTs a fresh Caddy JSON config to the admin API when the config hash changes.
hostsSyncs /etc/hosts entries against the registry — skipped when the dnsmasq resolver is installed, because the whole suffix is covered by DNS.

Data Flow

  1. The user edits projects in the GUI or CLI.
  2. Rust validates and writes the registry.
  3. The reconciler marks dirty; the background tick re-derives Process Compose YAML and Caddy config.
  4. Process Compose starts, stops, or restarts project processes as needed.
  5. Caddy picks up new routes and TLS certificates.
  6. Status changes flow back to the GUI through Tauri IPC events.

Runtime Files

PathPurpose
~/Library/Application Support/PortBay/registry.jsonProject registry
~/Library/Application Support/PortBay/runtime.jsonLive sidecar port assignments
~/Library/Application Support/PortBay/certs/<project-id>/mkcert-issued certificates
~/Library/Application Support/PortBay/logs/<project-id>.logPer-project logs
~/Library/Application Support/PortBay/process-compose.yamlGenerated Process Compose config
~/Library/Application Support/PortBay/caddy/autosave.jsonCaddy-managed autosave
/etc/hostsPortBay-managed host block (fallback when dnsmasq is not installed)
/etc/resolver/<suffix>dnsmasq resolver stub (when zero-config DNS is active)

Phase Status

PhaseStatus
Phase 0 — validation spikesDone
Phase 1 — headless coreDone
Phase 2 — GUI MVPDone
Phase 3 — UX polish, error handling, onboardingDone
Phase 4 — Pro entitlement, MCP server, open-source release readinessIn progress
Phase 5 — Linux and WindowsDeferred

The raw engineering notes remain in docs/ARCHITECTURE.md for contributors who need source-level detail.

PortBay is pre-MVP software. Use the docs as an operating guide, not a stability guarantee.