79 lines
3.9 KiB
Markdown
79 lines
3.9 KiB
Markdown
<!--
|
|
SPDX-FileCopyrightText: 2026 Stan Grams <sjg@haxx.space>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
-->
|
|
|
|
# Frontend architecture
|
|
|
|
The HTTP frontend is a strict TypeScript application built with esbuild. Rust
|
|
embeds deterministic JavaScript output from `assets/web/generated`; Cargo does
|
|
not run Node.js or contact the network.
|
|
|
|
## Runtime graph
|
|
|
|
`frontend/src/bootstrap.ts` is the only first-party script referenced by the
|
|
HTML document. Its imports establish startup order for WebGL support, shared UI
|
|
services, decoder dispatch, the local Leaflet AIS adapter, and the application
|
|
coordinator. Leaflet and the Opus decoder remain isolated vendored scripts.
|
|
|
|
Feature entries under `frontend/src/plugins` are ESM bundles. The typed plugin
|
|
loader imports them by feature group and keeps expensive map, scheduling, and
|
|
decoder behavior lazy. Shared code is emitted as content-hashed chunks. The
|
|
decode-history worker is an independent entry compiled against Web Worker
|
|
globals.
|
|
|
|
Dependencies point from application and feature code toward `core` and `api`.
|
|
`api/generated.ts` contains Rust wire formats; `api/client.ts` and focused
|
|
parsers validate untrusted HTTP, SSE, WebSocket, and worker data before it is
|
|
used as typed application state.
|
|
|
|
## Browser host contract
|
|
|
|
Separate lazy bundles cannot share module instances with the stable application
|
|
entry, so they use three intentional host namespaces:
|
|
|
|
| Global | Purpose | Mutation policy |
|
|
| --- | --- | --- |
|
|
| `window.trx` | Application state, core services, and feature registrations | The root is frozen; lazy features may register only their documented `modules.*` service. |
|
|
| `window.trxPluginRuntime` | Typed decoder registration and message dispatch | Runtime object is installed once; plugins register lifecycle handlers through its API. |
|
|
| `window.trxUi` | Notifications, confirmations, tab accessibility, and control presentation | Installed once by `ui-core.ts`; consumers call methods but do not replace them. |
|
|
|
|
The WebGL adapter exposes `createTrxWebGlRenderer`, `trxParseCssColor`,
|
|
`trxHslToRgba`, and `trxClearCssColorCache` for the application bundle. Leaflet
|
|
adds `L.TrxAisTrackSymbol` and `L.trxAisTrackSymbol` to the vendored Leaflet
|
|
namespace.
|
|
|
|
The following transitional properties are explicitly part of the lazy-feature
|
|
host contract and are declared in `app.ts`: `lastSpectrumData`, `lastFreqHz`,
|
|
`currentBandwidthHz`, `ft8BaseHz`, `getDecodeHistoryRetentionMs`,
|
|
`applyDecodeHistoryRetention`, `getDecodeRigMeta`, `renderRdsOverlays`,
|
|
`buildAisVesselUrl`, `trxScheduleUiFrameJob`,
|
|
`takeSchedulerControlForDecoderDisable`, `navigateToTab`, `_syncRecorderState`,
|
|
and `refreshRdsUi`. Optional callbacks owned by lazy features are
|
|
`refreshCwTonePicker`, `updateFt8RfDisplay`, `clearSatPredictionDom`,
|
|
`syncWefaxToggle`, `updateAisBar`, `updateVdesBar`, `updateAprsBar`,
|
|
`updateFt8Bar`, `updateSatLiveState`, `applyCwAutoUi`, and
|
|
`applyCwAutoUiFromServer`.
|
|
|
|
This list is closed: new standalone mutable `window` properties are not an
|
|
accepted integration mechanism. Extend an existing typed service or introduce
|
|
an imported interface instead. Removing transitional properties as feature
|
|
boundaries become directly importable remains preferable.
|
|
|
|
## Build and verification
|
|
|
|
The generated directory is removed before every build, preventing orphaned
|
|
compatibility bundles. Stable feature entry names are allowlisted by the Rust
|
|
asset manifest; shared chunks use content hashes. The generic Rust handler
|
|
rejects unknown names and unsupported MIME types and serves embedded assets
|
|
with compression, ETags, and immutable caching.
|
|
|
|
CI installs from `package-lock.json`, caches only npm downloads, type-checks the
|
|
window and worker environments separately, lints, runs unit and DOM tests,
|
|
starts the application in Chromium, regenerates Rust contracts and bundles,
|
|
checks for drift, and runs REUSE validation after generation.
|
|
|
|
See `frontend/src/README.md` for local commands and
|
|
`docs/ts-migration-plan.md` for the migration decisions and completion gates.
|