Add mocked UI dev mode (make dev-ui) for backend-free UI development#1008
Open
tehelsper wants to merge 11 commits into
Open
Add mocked UI dev mode (make dev-ui) for backend-free UI development#1008tehelsper wants to merge 11 commits into
tehelsper wants to merge 11 commits into
Conversation
Run the real web UI in a Docker container with a fully mocked backend so UI developers can iterate on templates/CSS/JS without a device, bitcoind, LND, or systemd. Zero changes to production code: a PYTHONPATH shim layer mocks the external touchpoints, a fixture filesystem recreates device paths, and fake binaries absorb shell-outs. Includes a floating dev panel to switch device states (syncing, upgrading, drive missing, ...), toggle warnings, and install/uninstall apps via marker files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
main.html and lnd_watchtower.html built same-origin URLs with location.hostname, which drops the port, so the pin and expand/collapse icons (and the remove-tower link) 404 whenever the UI is served on a port other than 80/443. Use relative URLs instead. URLs that intentionally target other ports are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Simulated reboot now lands on ~300s uptime instead of 0, so after an app install the homepage goes straight to stable rather than sitting on the 'Starting...' page for the full 180s just-booted window. - Default lndhub service state is now 'running' (green) instead of 'stopped' (red) so the out-of-box status page is coherent. - Fake journalctl reflects the service's mock state, so a service shown red (failed/stopped) has a matching error log instead of 'everything is fine'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Rename the make target ui-dev -> dev-ui (+ dev-ui-build/-shell/-clean) so future dev helpers group under 'make dev-*'. - Dev panel label 'myNode' -> 'MyNode' (proper capitalization); serve /dev/overlay.js with no-store so panel edits aren't masked by the app's 24h asset cache. - Default the container to premium edition (product key + healthy check-in) instead of community edition; /dev/edition and /dev/reset go through the shared seed_edition() helper. - Simulated reboot now lands at 170s uptime so the real 'Starting...' screen shows briefly (~10s) before auto-advancing to the stable homepage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The homepage expandable detail panels started pinned (shown by default); seed ui.json with pinned_bitcoin_details/pinned_lightning_details = false so they stay collapsed until the user clicks expand. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New /dev/premium_plus_warning endpoint and a 'Premium+ warning' panel section with expiring soon / expired / none buttons. It sets the premium_plus days_remaining in the mocked check-in data so the homepage subscription-expiration banner (expiring vs expired) can be previewed, and clears any prior dismissal so the banner is not suppressed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Community/Premium control was a single button whose label was the target edition while its highlight tracked the current one, so premium mode showed a highlighted 'community edition' button - reading as if community were stuck on. Replace it with a dedicated 'Edition' section (above Warnings) holding two buttons that highlight whichever edition is actually active. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The app applies a 24h Cache-Control to all 200 responses, which also hit the /dev/* JSON endpoints - so the browser served /dev/status (and the action endpoints) from cache and the panel highlighted stale choices (e.g. 'synced' stayed lit after switching to syncing). Add a blueprint after_request that forces no-store on every /dev/* response, and fetch panel data with cache:'no-store' so already-cached entries are bypassed too. Drops the now-redundant per-route header on /dev/overlay.js. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Panel actions reload the page to re-render server content, which closed the panel each time. Persist the panel's open state and scroll position in sessionStorage (per-tab) and auto-reopen on load, so the panel appears to stay open while tweaking settings. Closing the panel clears the state so it stays closed across reloads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Match the folder and docker compose service/container names to the 'make dev-ui' target (dev-* convention). No behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Besthuvelraju
approved these changes
Jul 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a Docker-based mocked UI dev mode: run the real myNode web UI locally with no device, bitcoind, LND, or systemd, for fast iteration on templates/CSS/JS.
make dev-ui # http://localhost:8888, password: boltEverything lives in a new
dev/dev-ui/directory (see its README for full docs). The only existing files touched are the rootMakefile(newdev-ui*targets) and a small template URL fix (below).How it works
Zero changes to production code — no "ui mode" checks. The container wraps the unmodified app in three mock layers:
dev/dev-ui/mock_pynode/) — sits before/var/www/mynodeand/var/pynodeon the python path. Each mock exec's the real module and patches only the outside-world touchpoints into the real namespace (fake bitcoind RPC client, fixture-backedlnd_get, mocksystemctl_info, mockpam, simulated reboot/upgrade). The real update/caching/formatting code runs unchanged against fixture data./mnt/hddas a real tmpfs mount, settings/marker/version files), since the code reads inline absolute paths./usr/binin-container; fakesystemctlshares state files with the python mock so shell and python views stay consistent.Features
after_requestinjection, no template changes): switch device state (stable,drive_missing,quicksync_*,upgrading,shutting_down, ...), bitcoin sync progress, LND ready/wallet, warnings (undervoltage/fsck/usb), drive-full, upgrade banner, community/premium edition, simulated reboot, and one-click reset. Also scriptable viacurl localhost:8888/dev/....git statusstays clean.dev/ui-dev/fixtures/*.jsonand reloads live.Template fix (second commit)
main.htmlandlnd_watchtower.htmlbuilt same-origin URLs withlocation.hostname, which drops the port — the pin and expand/collapse icons (and remove-tower link) 404 whenever the UI is served on a non-80/443 port (direct Flask on 8000, this dev container on 8888). Switched to relative URLs; the many URLs that intentionally target other ports (:8443,:3021,':'+port) are untouched.Verification
make dev-ui: login (real flow, mocked PAM), fully populated homepage, all major pages (/bitcoin,/lnd,/apps,/marketplace,/settings,/status,/electrum-server,/torin premium mode) render with zero tracebacks/500s across ~800 requests.Note: the UI publishes on host port 8888 because the repo's release file server tooling uses 8000.
🤖 Generated with Claude Code