The dashboard finally has live content. `runtime.ts` now imports
`defineWidget` from `@dashward/widget-sdk` (added as a workspace
dependency of the container), defines a tabular-numerals clock widget
inline, and mounts it onto the 12-column grid via a generic
`mountWidget` + `createContext` pair that produces the SDK's
config/system/lifecycle/shell APIs.
container/runtime/runtime.ts
- mountWidget(def, parent, instanceId, size): creates a grid card,
applies grid-column/row span, builds the widget context, calls
def.mount; wraps in try/catch so a mount failure visibly degrades
the card (red border + error label) instead of breaking the page.
- createContext: localStorage-backed config (persists per
instanceId), theme reads dataset.theme and subscribes to the
dashward:ThemeChanged CustomEvent (DBus signal forwarded from
shell), shell.call delegates to window.__dashShell__. onMount
fires via microtask; onUnmount handlers stored; visibility is a
no-op until P7 (edit mode / workspace tracking).
- clockDef: defineWidget<ClockConfig>; shadow DOM root, large
tabular-numerals time string, re-renders on tick + config.onChange.
container/runtime/styles.css
- Real card style: half-transparent backdrop-filter blur with a
light/dark variant, rounded 18px corners, subtle border and shadow.
- .widget-error fallback for failed mount.
- grid-auto-rows: minmax(120px, auto) so widgets have a sensible
minimum row height.
container/package.json
- `@dashward/widget-sdk` is now a runtime dependency. esbuild
bundles it into runtime.js.
Verified on ubuntu2504-test VM: clock card renders top-left at 4-wide
× 2-tall, ticks every second, follows system theme live via the P4
bridge (light → glass-white card, dark → glass-black card).
Layout persistence, edit mode, dynamic disk loading of widget bundles,
and iframe crash isolation per design §11 / §14 land in P6+.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the workspace-warden.ts stub with a real implementation matching
design §5:
- On enable: snapshot org.gnome.mutter::dynamic-workspaces and
org.gnome.desktop.wm.preferences::num-workspaces, persist to
~/.local/state/dashward/workspace-warden.json, then disable dynamic
mode and append a new workspace as the dashboard slot. num-workspaces
is updated to match the new count so external observers stay in sync.
- Position invariant: connect to workspace-manager's workspaces-reordered,
workspace-added, and workspace-removed signals; whenever the dashboard
is no longer last, reorder it back. If something external removes the
dashboard, append a replacement.
- Defensive guards: external changes to num-workspaces or
dynamic-workspaces are clamped back; a `suppressGuard` flag avoids
feedback loops between our own writes and our own signal handlers.
- On disable: remove the dashboard workspace, restore both gsettings,
delete the state file.
Supporting infrastructure:
- util/logger.ts: console.log/warn/error wrappers with [Dashward] prefix.
- util/state-store.ts: load/save/clear JSON state under XDG_STATE_HOME.
- types/globals.d.ts: minimal Shell.Global declaration covering
workspace_manager / display / get_current_time().
Build chain fixes uncovered while wiring P1:
- Replace placeholder @girs/* versions in extension/ and container/
package.json with real published versions from npm (gnome-shell@50.0.0,
meta-16@16.0.0-4.0.0, etc.). Add the required @girs/gio/glib/gobject
packages so resolution actually succeeds.
- Set tsconfig `types` arrays to include each girs `/ambient` entry so
the `gi://*` and `resource:///*` module specifiers resolve.
- Add `override` modifiers on Extension.enable/disable (required under
the base tsconfig's noImplicitOverride).
- Fix workspace iteration to use get_workspace_by_index in a loop
instead of the non-existent get_workspaces() — Meta 16 doesn't expose
the bulk getter.
Verified: `pnpm -r build` and `pnpm -r exec tsc --noEmit` are both clean.
Functional verification against a real GNOME session is pending P2 — the
extension cannot be loaded yet because we haven't packaged it for the
test VM.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bootstrap the Dashward repo per arch/UBUNTU-DASHBOARD-SPACE.md:
- pnpm-workspaces monorepo (sdk, extension, container, widgets-builtin/*)
- GNOME extension stub (metadata.json, src/*.ts placeholders for warden,
guard, supervisor, entry UX, DBus service)
- WebKit container stub (GJS main + page-side runtime + dashboard.html)
- TypeScript widget SDK (defineWidget + types)
- Builtin clock widget as the first SDK consumer example
- DBus interface XML (proto/shell.iface.xml) and shared types
- esbuild configs for extension and container; tsc for SDK
- Design doc copied in at repo root for discoverability
No functional logic yet -- all components are placeholders that compose
in extension.ts so the build chain can be exercised. P1 (workspace
warden) starts next.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>