ADR 0017 — Runtime platform detection
Context
Section titled “Context”The same renderer bundle runs as a Cloudflare Pages SPA and inside Electron. The two differ only in transport: on the web, protocol executors call /api/* over HTTP; on desktop, they call Electron main-process handlers over the IPC bridge. We need a way for shared renderer code to pick the right transport. Two broad options: compile-time platform builds (separate bundles with dead-code elimination) or a single bundle that branches at runtime.
Decision
Section titled “Decision”Detect the platform at runtime via isElectron() in src/lib/shared/platform.ts (it checks for the window.electron bridge that the context-isolated preload exposes). Each feature’s executor branches on isElectron() to choose IPC vs. HTTP; there is no behavioural difference beyond transport. This keeps a single bundle and a single code path, with the platform seam isolated to the executor boundary.
Consequences
Section titled “Consequences”Positive
- One bundle to build, test, and ship; no per-platform build matrix for the renderer.
- The platform seam is explicit and centralized (
isElectron()+ per-executor branch), easy to reason about.
Negative
- A small amount of dead transport code ships to each platform (the unused branch), though it’s negligible.
- Renderer code can be tempted to sprinkle
isElectron()checks widely; the discipline is to confine them to transport selection, not feature logic — capability differences belong incapabilities.ts(ADR 0012).
References
Section titled “References”- Source:
docs/adr/0017-runtime-platform-detection.md - Related: ADR 0001, ADR 0012.