Theme
Lesson 01 — Toolchain and process boundaries
Outcome
Extend the real toolchain skeleton: keep the Go core independent, use the existing Bun root workspace for the desktop package, and establish clear commands for running/checking each half independently.
Why this comes now
Tooling becomes invisible infrastructure. A messy bootstrap spreads platform assumptions everywhere before you have product code.
Understand
The Go core is a separate executable. Electron is not the backend; it is a desktop shell that starts and monitors the core. Bun manages the JavaScript workspace because it is fast and convenient, but the architecture must not depend on Bun-specific runtime behavior in the renderer.
The core should be runnable from a terminal. This gives us a clean test/debug path and makes future remote control possible without redesigning ownership.
Build the real project
- Create
core/go.modwith the chosen supported Go 1.26 toolchain. - Add
core/cmd/forge-core/main.gothat starts, logs its version, and exits cleanly on context cancellation. - Extend the existing Bun workspace with the desktop TypeScript package, then add its TypeScript config and Vite/Electron entry points.
- Add root commands (
Makefile, scripts, or simple documented commands) forcore-test,desktop-check, andcheck. - Add
.editorconfigand.gitignore. - Keep the scaffold small: do not add an ORM, DI framework, or logging ecosystem before there is a need.
Completion gate
go test ./... passes. go run ./cmd/forge-core starts and can be stopped cleanly. bun install, bun run docs:build, and the desktop typecheck/build command succeed once desktop dependencies are installed. The core does not import desktop code and vice versa.
Pitfalls to avoid
Avoid giant monorepo tooling for two packages. Avoid using Electron main as a place for business logic. Avoid pinning tool versions in six different files.
References
Go modules, Go context package, Bun workspaces, Electron process model.
Checkpoint
Update docs/status/CURRENT.md; write down the exact developer commands in the root README if they differ from the starter placeholders.