Loadbudget

TECHNOLOGY

What is the system built with?

Binds: architecture, code

This page carries the languages, SDKs and tools, as they stand today. A choice and its reason bind architecture. A setting, a path or a value that a section names binds code.

Only settled choices appear here. Anything still open is a GitHub Issue, and the platform facts bearing on it are stated there rather than in docs/.

Language and UI

Swift and SwiftUI, native, with an iOS target and a watchOS target.

The Watch app decides this. watchOS is not an officially supported Flutter or React Native platform, and Kotlin Multiplatform reaches it only at Tier 2. CI compiles that tier, but it does not always run it. Compatibility between compiler releases is best-effort, and not guaranteed. KMP also shares logic only. The UI is SwiftUI under every configuration.

The HealthKit surface points the same way. Effort scores are written through relateWorkoutEffortSample, live workouts need HKLiveWorkoutBuilder on the watch, and background delivery needs an entitlement. The maintained bridges document none of it. Each gap is a native module written in Swift, which is the cost a bridge exists to avoid.

Swift Charts draws each chart. The framework ships with the SDK, so it adds no dependency. A chart gives VoiceOver and Audio Graph a description of its data through accessibilityChartDescriptor. The app writes that description.

Localization

English and Polish, through a String Catalog.

SessionActivity.label and EffortSource.phrase stay in English. HealthExport writes them into a file, and a file must carry the same word across every language the athlete picks. SessionActivity.localizedLabel and EffortSource.localizedPhrase map each case to the word that a screen shows in her language.

Concurrency

The app targets default to the main actor. The package does not.

ios-app/project.yml sets SWIFT_DEFAULT_ACTOR_ISOLATION to MainActor, and SWIFT_APPROACHABLE_CONCURRENCY to YES.

ios-app/Core/Package.swift turns on the same upcoming features, and it sets no default isolation. The domain is pure computation, so a caller on any actor can price a session.

SWIFT_VERSION is the language mode, and 6 is the newest mode. It is not the compiler version. Read swift --version for that.

The lb command line

Python, with uv. pyproject.toml at the repository root declares the uv workspace and its shared tool settings. tools/pyproject.toml declares the dependencies of lb. uv.lock pins them. uv run builds the environment on first use.

.python-version at the repository root pins the interpreter to Python 3.14. Every uv command below the root reads it, on a laptop and in CI alike. So no workflow names a version of its own.

required-version in the root pyproject.toml pins uv to one minor release. A uv outside that range refuses to run. astral-sh/setup-uv reads the same field, so CI installs a release in that range. Each uv_build bound names the same minor release. A uv of another minor release builds a workspace member with a uv_build package from PyPI, and not with its own backend.

tools/src/lb/ holds the lb package. The product ios-app-tools holds the tooling of the app, and lb names each of its commands. The product apple-app-delivery holds the commands that deliver the app through Xcode Cloud and TestFlight. ios_app_tools.delivery passes them the settings of the app. The product app-store-connect-client signs each request to App Store Connect. It reads Xcode Cloud and its result bundles. apple-app-delivery calls it.

Bazel runs the Python tests as well. MODULE.bazel takes rules_python, and rules_python reads uv.lock itself, so the pins have one home. .bazelversion pins Bazel. Gazelle writes one py_library for each directory that holds Python in a member of the uv workspace. Each test file has one target. Gazelle writes it with lb_py_test from bazel/pytest.bzl. That macro runs pytest-for-bazel. aspect_rules_lint runs ty on each Python target, as an aspect of bazel test.

Bazel runs the Node checks and builds the site too, through aspect_rules_js. MODULE.bazel pins the Node toolchain. npm_translate_lock reads Web/pnpm-lock.yaml for the site, and bazel/jscpd/pnpm-lock.yaml for jscpd. Web/BUILD.bazel holds astro check, the tests of the site, and the targets that build, serve and deploy it. The root BUILD.bazel holds jscpd.

A session drives a browser through Playwright MCP. .mcp.json names the playwright server, and npx starts the @playwright/mcp release that it pins. So the server runs on a Node outside Bazel. infra/pins/node/amd64.json pins the Node of lb-agents, and brew installs Node on a laptop. docs/development/WORKFLOW.md, section “Graphical changes carry visual evidence”, states what the server captures.

tools/commit-review-against-rule-pages/docs/architecture/PROVIDERS.md owns review provider architecture.

Swift is the language of the app. A script that calls a web API is not the app, and it needs no Apple SDK. To write one in Swift costs the Swift toolchain on every machine that runs it, plus a package dependency to sign ES256, because CryptoKit is Apple only.

The runners of GitHub Actions

Go, built by Bazel. firecracker-runners-for-github talks to GitHub through github.com/actions/scaleset. That library is the client of runner scale sets that GitHub publishes, and it is a Go module. So the product is in Go.

MODULE.bazel takes rules_go, and the Go SDK comes from the go line of tools/firecracker-runners-for-github/go.mod. Gazelle writes the Go targets.

Storage and sync

ios-app/docs/architecture/PERSISTENCE.md holds this. It names the local store, the record that CloudKit syncs, and what the app promises about encryption.

The load model

ios-app/docs/development/LOAD.md holds this. It names the unit, the order in which effort arrives, and what the number never claims.

The replay of the coach

ios-app/docs/development/REPLAY.md holds this. It names what a replay assumes, the source of a dataset, and the views that a KPI reads.

DuckDB reads each dataset and runs each KPI. It reads Parquet, JSON and SQL in one library. Swift calls its C API. MODULE.bazel pins the prebuilt library of each host by its sha256. No Swift package of DuckDB builds on Linux.

Build SDK and deployment target

ios-app/docs/development/DEPLOYMENT_TARGET.md holds this. It names the SDK version, the OS floor, and the constraints that bound it.