5ed4170e696e6d5ca84a697bddc18a5f0eb24460
Three new wires from page to shell and back, proving the bridge end to
end. The dashboard placeholder now follows the system color-scheme via
the full chain: page-side dashShell.call('getTheme') → WebKit script
message handler → DBus method on the shell-owned service → gsettings
read → return value back up. ThemeChanged proves the reverse direction:
the shell watches color-scheme and emits a DBus signal that the
container forwards to the page as a CustomEvent.
extension/src/dbus-service.ts
Owns top.hangmanlab.Dashward.Shell on the session bus; exports
GetTheme (reads org.gnome.desktop.interface::color-scheme, maps
prefer-dark→dark / else→light); emits ThemeChanged on the gsettings
changed signal. Bus acquisition is async, so the constructor takes an
onReady callback that fires from the bus_acquired handler.
extension/src/extension.ts
Sequencing: warden → guard → dbus, and only after dbus_acquired
callback fires do we spawn ContainerSupervisor. Disable order is
reversed (container first so its DBus proxy stops calling the service
before we unown the bus name).
container/src/dbus-client.ts
Thin GJS proxy wrapper around the Shell interface; exposes a typed
getTheme() / onThemeChange(cb) API.
container/src/bridge.ts
Registers a `shellCall` UCM script-message handler; parses
{id, method, args} JSON from the page, dispatches to invoke(), and
feeds the result back via evaluate_javascript. Shell signals are
forwarded to the page via window.__dashShell__._onSignal.
container/runtime/runtime.ts
Installs window.__dashShell__ at script start, calls getTheme() on
load and applies the result to <html data-theme>, listens for the
ThemeChanged CustomEvent.
container/runtime/dashboard.html + esbuild.config.js
Switched the runtime bundle from `format: 'esm'` to IIFE so it loads
as a classic <script> -- WebKitGTK silently refuses `<script
type="module">` over file:// for ES module resolution. Added an
inline error catcher that surfaces JS errors in the visible boot
diagnostic div instead of failing silently.
container/src/main.ts
Construct ShellClient + Bridge before load_uri so the very first
page-side dashShell.call() has a handler waiting. Added load-changed
/ load-failed signal logging for future diagnosis.
Verified on ubuntu2504-test VM: enable produces clean log chain through
"container window arrived", page renders with "P4 — shell bridge
online" placeholder and the correct system theme on first paint, manual
`gsettings set ... color-scheme prefer-dark` flips the placeholder
background live.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dashward
A dedicated rightmost workspace for custom widgets on Ubuntu/GNOME, in the spirit of macOS Dashboard.
- GNOME Shell extension (GJS) creates the dashboard workspace, defends it from regular window incursions, and supervises the container.
- WebKitGTK container (separate process) renders an HTML page on that workspace.
- Widget SDK (TypeScript) lets you write widgets as web components.
Status: P0 skeleton. Design lives in
UBUNTU-DASHBOARD-SPACE.md
(see also ~/arch/UBUNTU-DASHBOARD-SPACE.md locally).
Target
- Ubuntu 25.04 / GNOME Shell 48 / Wayland.
- Other distros & versions: post-v1.
Repo layout
sdk/ TS widget SDK, published as @dashward/widget-sdk
extension/ GNOME Shell extension (GJS, TS-authored)
src/ Extension source
widgets-builtin/ Builtin widgets shipped with the extension
container/ WebKit kiosk process
src/ GJS bootstrap
runtime/ Page-side runtime (host grid, edit mode, widget loader)
widgets/ Example / 3rd-party widget dev tree
proto/ Shared DBus XML + TS types
scripts/ Build & dev helpers
Dev setup
Requires Node ≥ 20 and pnpm ≥ 9. To install pnpm:
npm install -g pnpm
Then:
pnpm install
pnpm build
Testing discipline
All Shell-side iteration happens inside the
ubuntu2504-test libvirt VM, never on the host GNOME session — a
buggy extension can lock you out of the Wayland session. See the design
doc §17 for the dev loop.
License
TBD.
Description
Languages
TypeScript
90%
CSS
3.3%
JavaScript
2.9%
HTML
2.4%
Shell
1.4%