diff --git a/readme.ui.md b/readme.ui.md index da72dd8..6c1b8fa 100644 --- a/readme.ui.md +++ b/readme.ui.md @@ -355,17 +355,39 @@ marked with a `restart required` badge, and the UI surfaces a single component-per-view under `ts_web/elements//`, a tiny SmartRouter-style client router (`ts_web/router.ts`), and a single `appstate.ts` as the store. +- **Bundled into the binary via `ts_bundled/bundle.ts`.** ModelGrid is a + Deno project that ships as a `deno compile` single binary, so the UI + follows the `@stack.gallery/registry` pattern: a build step bundles + the `ts_web/` sources (HTML, JS, CSS, fonts, icons) into a single + generated `ts_bundled/bundle.ts` module that exports a + `{ path → bytes | string }` map. The daemon dynamically imports that + module at startup and hands the map to **typedserver**, which serves + it on the UI port. Result: no external asset directory, no runtime + filesystem dependency, one binary still ships the entire console. +- **Dev vs prod asset source.** In `deno task dev`, typedserver is + pointed at `ts_web/` on disk so UI edits are hot-reloadable without + re-running the bundler. In `deno task compile` / prod, the bundler + regenerates `ts_bundled/bundle.ts` first and the compiled binary + serves exclusively from the embedded map. A single flag + (`UI_ASSET_SOURCE=disk|bundle`, default `bundle`) picks the strategy + at runtime. +- **Bundler placement.** Mirrors `@stack.gallery/registry`: keep the + bundler in `scripts/bundle-ui.ts`, invoke it from a `deno task + bundle:ui` that the `compile:all` task depends on, and `.gitignore` + the generated `ts_bundled/bundle.ts` so it is only produced during + release builds (or regenerated on demand for local prod testing). - **Packaging.** Follow dcrouter's module split: `@modelgrid.com/modelgrid` - ships the daemon and the UI bundle; a future - `@modelgrid.com/modelgrid-web` can carve out the web boundary if the - bundle grows large. + ships the daemon and the embedded UI bundle; a future + `@modelgrid.com/modelgrid-web` can carve out the web sources as their + own publishable boundary if the bundle grows large or the UI needs to + be consumed independently. - **Dark theme default** (black background, high-contrast foreground) to match dcrouter and the expected server-ops environment. Light theme is a later toggle. -- **No server-side rendering.** The UI is a static SPA served by the - daemon; all data is fetched through the API. This keeps the runtime - surface small and makes the UI-less `curl` story identical to the UI - story. +- **No server-side rendering.** The UI is a static SPA; typedserver + returns the asset map's `index.html` for the app shell and the rest + of the state comes from the API. This keeps the runtime surface + small and makes the UI-less `curl` story identical to the UI story. ## ❓ Open Questions