The tray's right-click menu is drawn by the app: one tree from tray.rs
(stable submenu keys), one frameless always-on-top menu-N window per
panel rendered by tray-menu.html with the design system, placed inside
the monitor's work area. A pure panel book keeps transient and pinned
panels apart; pinned panels (pin button, Ctrl+click, middle click) are
draggable, step aside from each other and are saved in state.json
(menuPins) and restored at start. tray_update pushes the tree to the
open panels, which update in place; closed panels are destroyed. The
native menu, rendered from the same tree, stays as the fallback and on
Linux. Only menu-* windows get the menu_* commands (menu.json).
In-app context menus get the same behaviour through a pure menu stack
(ui/menu-stack.ts): pin a menu, tear off a submenu, pinned panels
survive the next menu, are draggable and re-read their entries from
live sources so data changes update them in place.
Also drops a stray diff3 marker line from CHANGELOG.md.
- app view: 12 tabs become 5 sections, each with a header (what it is for, the one next step from state
already read) and its sub views in a segmented control; 1-5 jump, Ctrl+Shift+[ ] cycle, Ctrl+K and the
context menu list sections and sub views; old tab ids, section and section/sub links all resolve
- Players > Game services (games only): both stores, one row per leaderboard / achievement with its
languages and each store's state, Game Center locale map, Play API-disabled state with the console plan
- games status --json: items, localeMap, playApiDisabled; inspect summary: games
- sidebar: apps grouped by attention / in progress / live / not on a store, one status line each, studio
filter, workspace as a footer icon row
- boot check opens places like a person (section, then sub view)
One ContextMenu in the design system (keyboard, type-ahead, submenus, check items,
disabled reasons, Shift+F10 / Menu key, viewport placement, light and dark). The
native menu is prevented globally; text fields keep Cut / Copy / Paste / Select all.
Menus on sidebar and portfolio apps, app hero, releases, store art, live art,
reviews, checks, editor fields, catalog, prices, accounts, app folders, ignored.
The signed release showed only its background colour and never started the sidecar. Tauri's freezePrototype
freezes Object.prototype before the bundle runs; d3-color and d3-format (under the visx charts) assign
`constructor` / `toString` on plain objects while loading, which throws on a frozen prototype, so the bundle
stopped before React drew anything. The saved state was not the cause.
- build/freeze-safe.ts: Vite plugin that rewrites those assignments in dependencies into a helper that defines
the property when the frozen prototype would refuse it
- error boundaries for the window, each screen and each app tab (Copy details, Reload, Reset saved state with a
backup); public/boot.js shows the same panel when the bundle fails or the window stays empty
- logs/host.log (start, saved state, sidecar start/stop, panics) and logs/webview.log (log_webview), rotated,
home as ~, keys, tokens and e-mail addresses replaced
- state.json `version` 2 with an explicit 1 -> 2 migration (original kept as state.json.v1.bak), per-entry
tolerant parsing, partial settings keep their fields, unreadable files kept aside
- folders that are gone: "Folder not found" with Locate... (project_locate) / Remove; portfolio reads skip them
- tools/desktop-boot-check.ts: the built window with the release CSP and the frozen prototype, a mocked host from
the state fixtures (empty, D1 with folders gone, D3) and the real sidecar, through every screen; in bun run ci,
the Forgejo CI workflow and the macOS release
Desktop icons move from lucide to Phosphor (@phosphor-icons/react, per-icon imports, regular weight; fill for the
active nav item, notices and rating stars). The site's icons and the fixture art use Phosphor's own files from
@phosphor-icons/core. App Store and Google Play are shown with their marks from simple-icons (CC0 data), vendored
unchanged by tools/site-icons.ts and rendered as a mask in the neutral text colour next to the store's name; the
trademark note is in docs/desktop.md and the site footer. lucide-react and lucide-static removed. The
no-hand-written-SVG guard allows only the vendored files (byte-equal to their packages) and per-icon Phosphor
imports. Site stylesheet ?v= bumped.
- Rust host: spawns storebound serve --stdio with fixed args, hands over a per-session secret,
mints confirm tokens only after a native dialog showing the summary and the dry run
- every app command re-checks window label and page origin; one capability (main window, app
commands + event listen only, no plugin API in the webview); strict CSP; tests/security.rs pins it
- store keys picked in native dialogs, kept in the OS keychain, passed per call in memory only
- plugins: shell (Rust only), single-instance, deep-link storebound://, window-state, opener,
dialog, notification, updater (placeholder endpoint and key until signing), process
- app-centric UI: Portfolio, App (Releases, Catalog, Listings, Health, Reviews, TestFlight),
App folders, Accounts, Dependencies, Settings; light / dark with the storebound.dev tokens,
reduced motion, home folder shown as ~
- macOS menu: Cmd+Q quits, Edit menu, Window menu keeps the main window; Linux DMABUF fix
- Bun workspace (npm files unchanged), ci runs desktop typecheck, build, cargo test and clippy;
scrub covers home paths; docs/desktop.md (protocol, safety, dependency sources and licenses)