Skip to content

Add developer-mode overlay shell with devLog and triggers - #21

Open
djscruggs wants to merge 8 commits into
mainfrom
feature/dev-mode-overlay
Open

Add developer-mode overlay shell with devLog and triggers#21
djscruggs wants to merge 8 commits into
mainfrom
feature/dev-mode-overlay

Conversation

@djscruggs

@djscruggs djscruggs commented Jun 19, 2026

Copy link
Copy Markdown

Summary

Adds a developer-only overlay shell to @bedrock/vue — a generic, reusable dev
panel that any consuming bedrock web app or library can populate with its own
debugging tools. It is off by default and ships nothing to end users unless a
developer explicitly enables it. Design follows docs/dev-mode-spec.md.

Origin/decisions: this started as a wallet feature in
digitalbazaar/bedrock-vue-wallet#131; review concluded the shell is not
wallet-specific and should live in @bedrock/vue, with the trigger app-owned
(the overlay accepts a toggle signal rather than installing a global listener).
Domain tools (paste-exchange-URL, seed-credentials) stay in the wallet.

What's here

  • Flag gateisDevModeEnabled() reads localStorage['bedrock.devMode'];
    when off, the overlay chunk is never loaded (zero production behavior change).
  • Overlay shellDevModeOverlay.vue, plain Vue + scoped CSS (no Quasar
    dependency), auto-mounted as a sibling of the root app during bootstrap(),
    lazily loaded into a bedrock-vue-devmode chunk. Responsive: right-hand rail
    on tablet/desktop, bottom sheet on phone.
  • Tool registration APIregisterDevTool({id, label, component}),
    unregisterDevTool(), getDevTools(). DevToolExample.vue is an
    unregistered docs sample. (Components are markRaw'd on registration so the
    reactive registry doesn't deep-wrap the component definition.)
  • console.* mirror — there is no separate logging API. When dev mode is
    on, the common console methods (log/info/debug/warn/error) are
    mirrored into a built-in "Log" tool, so existing console.* calls anywhere in
    the stack show up in the overlay with no code changes (calls are still
    forwarded to the real console). Entries render by type — text, collapsible
    JSON, error + stack, dimmed null/undefined — and turn URLs in text into
    clickable links. Other methods (group/table/trace/…) pass through
    untouched. installConsoleMirror() / uninstallConsoleMirror() are exported
    for hosts that want manual control.
  • Triggers (opt-in)createTripleKeyDetector() (desktop key trigger) and
    createTapTrigger() (corner multi-tap for touch devices). The shell installs
    neither; the host app wires whichever to toggleDevOverlay().

Out of scope

Wallet domain tools (paste-exchange-URL, seed-credentials, VC fixtures) and the
QR-code decoded-URL display stay in bedrock-vue-wallet.

Testing

  • npm run lint passes (0 errors).
  • No automated tests — deferred by decision (the repo has no test runner;
    CI is lint-only), so CI passing does not exercise behavior.
  • Behavior verified manually in a standalone Vite + Vue sandbox importing the
    real shell files: overlay mount/toggle, the console.* mirror (including
    pre-existing console calls appearing with no changes), typed rendering
    (text / collapsible JSON / error + stack / dimmed null / clickable + copyable
    URLs), registerDevTool, responsive layouts, and both triggers (key, and
    corner-tap positive + negative cases). No runnable bedrock app exists in this
    repo for an in-repo browser test.

Privacy / security

No customer or personal data. Off by default; no new network surface (the shell
only provides a panel + open/close mechanism — registered tools own their data).

🤖 Generated with Claude Code

Add the spec for the generic dev-mode shell (localStorage flag gate,
overlay panel, and registerDevTool() registration API) that mounts via
@bedrock/vue's beforeMount app-bootstrap hook. The trigger is app-owned
and the overlay accepts a toggle signal rather than installing a global
key listener. Domain tools (e.g. the wallet's paste-exchange-URL and
seed-credentials) are registered by consuming libraries. Spec only; no
implementation in this commit.
Adds the generic dev-mode shell to @bedrock/vue: a localStorage flag
gate (bedrock.devMode), a tool-registration API (registerDevTool), an
overlay panel rendered as a sibling of the root Vue app, and a toggle
signal the host app drives. The overlay is lazily loaded as its own
chunk only when the flag is set, so production builds are unaffected.

An opt-in createTripleKeyDetector helper is provided for apps that want
a key trigger; the shell does not install a global key listener itself.
DevToolExample.vue is a docs-only reference tool and is not registered
automatically. Domain tools (and the data they touch) stay with the
consumer that registers them.
The overlay panel now docks as a right-hand rail on tablet and desktop
widths and becomes a full-width bottom sheet (about 70% height, rounded
top corners) on phone-sized viewports under 600px, via a CSS media
query. No change to the overlay's behavior, registry, or toggle logic.
Adds a console.log-style API, devLog() with devLog.info/warn/error, for
logging values to the dev-mode overlay with no setup. When dev mode is
on, the shell auto-registers a built-in "Log" tool that renders each
entry by type: text for strings and primitives, collapsible pretty JSON
for objects and arrays, message and stack for Errors, and a dimmed
literal for null/undefined. URLs in text entries become clickable links
with a copy button. The buffer keeps the most recent 50 entries;
getDevLogEntries() and clearDevLog() are also exported.

The Log tool is lazily loaded into the existing dev-mode chunk, so it
adds nothing to production when the flag is off.
The triple-key trigger is unusable on mobile, so this adds an opt-in
corner-tap trigger: tapping a configurable screen corner a number of
times in quick succession (default top-right, 5 taps within 2s) fires a
callback the host app wires to toggleDevOverlay(). The corner hit-zone
is small and invisible, so normal taps are unaffected. Like
createTripleKeyDetector(), it is opt-in and not installed by the shell.
@djscruggs
djscruggs requested review from BigBlueHat and dlongley June 19, 2026 00:17
- Make devLog() a true no-op when dev mode is off: _add() now returns
  early instead of building and buffering entries nothing can display,
  matching the documented behavior.
- Simplify value classification: fold the unused "primitive" kind into
  "text" since the renderer treats strings, numbers, and booleans
  identically.
- Note in the trigger detectors that the time window is enforced between
  consecutive presses, not by a timer.
- Add a "superseded by implementation" note to the spec, which still
  described the wallet-era design (wallet.devMode, Quasar, WalletLayout).
- Remove the internal implementation plan doc from the repo; the spec is
  the canonical design record.
Per review, a separate devLog() API was a second way to log: it would
only show calls that explicitly used it, missing the console.* output
that other layers of the stack already emit. Replace it with a console
mirror — when dev mode is on, the common console methods (log, info,
debug, warn, error) are both forwarded to the real console and captured
for the built-in Log tool, so existing console.* calls anywhere appear
in the overlay with no code changes and there is a single way to log.

Other console methods (group, table, trace, ...) are left untouched.
Removes lib/devLog.js; adds lib/consoleMirror.js with
installConsoleMirror()/uninstallConsoleMirror() and the existing
getDevLogEntries()/clearDevLog(). The Log tool now renders each
console call's arguments (varargs) by type.
The dev-tool registry is a reactive Map, which caused Vue to deep-wrap
each registered component definition and emit a "Vue received a
Component that was made a reactive object" warning on first overlay
open. Wrap the component with markRaw() on registration so the registry
still tracks add/remove reactively without making the component itself
reactive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant