fix(demo): /app proxy (fixes 404s), mempool iframe, LND UI, icons
- nginx-demo.conf + vite proxy now route every /app/<id>/ to the mock backend, so the per-app mock UIs and the generic "Not available in the demo" notice render (previously only /app/filebrowser was proxied → most apps 404'd). - Mempool and IndeeHub now load in the in-app iframe (not a new tab). - Add an LND Lightning mock UI (channels, balances, routing) with dummy data; lnd/thunderhub are demoable. Notice page reworded to "Not available in the demo". - Fix missing icons: Bitcoin Core → bitcoin-core.png, Mempool → mempool.webp. - Pre-install only Bitcoin Core (drop duplicate Bitcoin Knots; still installable). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c9341baa35
commit
4cc808c73e
@ -72,6 +72,16 @@ http {
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
# Proxy every other app UI (/app/<id>/) to the mock backend, which serves
|
||||
# the per-app mock UIs (bitcoin-ui, electrumx, lnd, fedimint) and the
|
||||
# generic "Not available in the demo" notice for the rest.
|
||||
location /app/ {
|
||||
proxy_pass http://neode-backend:5959;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
|
||||
# Serve AIUI SPA
|
||||
location /aiui/ {
|
||||
alias /usr/share/nginx/html/aiui/;
|
||||
|
||||
@ -757,18 +757,10 @@ function staticApp({ id, title, version, shortDesc, longDesc, license, state, la
|
||||
}
|
||||
}
|
||||
|
||||
// Static dev apps (always shown in My Apps when using mock backend)
|
||||
// Static dev apps (always shown in My Apps when using mock backend).
|
||||
// Only one Bitcoin implementation is pre-installed (Bitcoin Core); Bitcoin Knots
|
||||
// remains installable from the marketplace.
|
||||
const staticDevApps = {
|
||||
'bitcoin-knots': staticApp({
|
||||
id: 'bitcoin-knots',
|
||||
title: 'Bitcoin Knots',
|
||||
version: '27.1',
|
||||
shortDesc: 'Full Bitcoin node',
|
||||
longDesc: 'Validate and relay Bitcoin blocks and transactions with the Archipelago custom node UI.',
|
||||
state: 'running',
|
||||
lanPort: 8334,
|
||||
icon: '/assets/img/app-icons/bitcoin-knots.webp',
|
||||
}),
|
||||
bitcoin: staticApp({
|
||||
id: 'bitcoin',
|
||||
title: 'Bitcoin Core',
|
||||
@ -777,6 +769,7 @@ const staticDevApps = {
|
||||
longDesc: 'Validate every transaction and block. Full consensus enforcement — the bedrock of sovereignty.',
|
||||
state: 'running',
|
||||
lanPort: 8332,
|
||||
icon: '/assets/img/app-icons/bitcoin-core.png',
|
||||
}),
|
||||
lnd: staticApp({
|
||||
id: 'lnd',
|
||||
@ -805,6 +798,7 @@ const staticDevApps = {
|
||||
license: 'AGPL-3.0',
|
||||
state: 'running',
|
||||
lanPort: 4080,
|
||||
icon: '/assets/img/app-icons/mempool.webp',
|
||||
}),
|
||||
lorabell: staticApp({
|
||||
id: 'lorabell',
|
||||
@ -1073,6 +1067,27 @@ app.get(['/app/electrumx/', '/app/electrs/', '/app/archy-electrs-ui/'], (_req, r
|
||||
</div>`))
|
||||
})
|
||||
|
||||
app.get(['/app/lnd/', '/app/lnd-ui/', '/app/archy-lnd-ui/', '/app/thunderhub/'], (_req, res) => {
|
||||
res.type('html').send(demoAppShell('LND — Lightning', '#f7931a', `
|
||||
<div class="hd"><span class="dot"></span><div><h1>LND</h1><div class="sub">Lightning Network Daemon · signet</div></div></div>
|
||||
<div class="grid">
|
||||
<div class="card"><div class="k">Node</div><div class="v"><span class="badge">● Synced to chain</span></div></div>
|
||||
<div class="card"><div class="k">Channel balance</div><div class="v">8,250,000 sat</div></div>
|
||||
<div class="card"><div class="k">On-chain balance</div><div class="v">2,350,000 sat</div></div>
|
||||
<div class="card"><div class="k">Active channels</div><div class="v">4</div></div>
|
||||
<div class="card"><div class="k">Peers</div><div class="v">11</div></div>
|
||||
<div class="card"><div class="k">Routing (30d)</div><div class="v">1,284 sat</div></div>
|
||||
</div>
|
||||
<div class="card"><div class="k" style="margin-bottom:8px">Channels</div>
|
||||
<table><thead><tr><th>Peer</th><th>Capacity</th><th>Local / Remote</th><th>State</th></tr></thead><tbody>
|
||||
<tr><td>ACINQ</td><td>5,000,000</td><td>2,450,000 / 2,550,000</td><td><span class="badge">active</span></td></tr>
|
||||
<tr><td>Wallet of Satoshi</td><td>2,000,000</td><td>1,200,000 / 800,000</td><td><span class="badge">active</span></td></tr>
|
||||
<tr><td>Voltage</td><td>10,000,000</td><td>4,500,000 / 5,500,000</td><td><span class="badge">active</span></td></tr>
|
||||
<tr><td>Kraken</td><td>3,000,000</td><td>1,800,000 / 1,200,000</td><td><span class="badge">active</span></td></tr>
|
||||
</tbody></table>
|
||||
</div>`))
|
||||
})
|
||||
|
||||
app.get(['/app/fedimint/', '/app/fedimintd/'], (_req, res) => {
|
||||
res.type('html').send(demoAppShell('Fedimint — Guardian', '#a78bfa', `
|
||||
<div class="hd"><span class="dot"></span><div><h1>Fedimint Guardian</h1><div class="sub">Archipelago Federation · 4-of-5 consensus</div></div></div>
|
||||
@ -4059,8 +4074,8 @@ p{color:#8b93a7;font-size:14px;line-height:1.5}
|
||||
</style></head><body><div class="card">
|
||||
<img src="/assets/img/app-icons/${id}.png" onerror="this.onerror=null;this.src='/assets/icon/favico-black.svg'" alt="">
|
||||
<h1>${title}</h1>
|
||||
<p>This app isn't interactive in the demo, but it runs fully on a real Archipelago node.</p>
|
||||
<div class="tag">Demo preview</div>
|
||||
<p>Not available in the demo.<br>This app runs fully on a real Archipelago node.</p>
|
||||
<div class="tag">Demo</div>
|
||||
</div></body></html>`)
|
||||
})
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ export function clearDemoIntroSeen(): void {
|
||||
// external site). Everything else shows "No demo" on a disabled install button
|
||||
// and is not launchable.
|
||||
const DEMO_EXTERNAL_URLS: Record<string, string> = {
|
||||
// Real, public sites that we open instead of mocking.
|
||||
// Real, public sites loaded in the in-app iframe.
|
||||
indeedhub: 'https://indee.tx1138.com/',
|
||||
mempool: 'https://mempool.space/testnet',
|
||||
'mempool-web': 'https://mempool.space/testnet',
|
||||
@ -68,14 +68,21 @@ const DEMO_MOCK_UI: Record<string, string> = {
|
||||
electrs: '/app/electrumx/',
|
||||
electrumx: '/app/electrumx/',
|
||||
'archy-electrs-ui': '/app/electrumx/',
|
||||
lnd: '/app/lnd/',
|
||||
'lnd-ui': '/app/lnd/',
|
||||
'archy-lnd-ui': '/app/lnd/',
|
||||
thunderhub: '/app/lnd/',
|
||||
fedimint: '/app/fedimint/',
|
||||
fedimintd: '/app/fedimint/',
|
||||
filebrowser: '/app/filebrowser/',
|
||||
}
|
||||
|
||||
/** Apps that open in a new tab (external real sites) rather than an iframe. */
|
||||
export function isDemoExternal(appId: string): boolean {
|
||||
return appId === 'mempool' || appId === 'mempool-web'
|
||||
/**
|
||||
* Whether a demo app opens in a new tab. Nothing does now — both real external
|
||||
* sites (mempool.space, indee.tx1138.com) load in the in-app iframe.
|
||||
*/
|
||||
export function isDemoExternal(_appId: string): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
/** Can this app be launched/installed in the demo? */
|
||||
|
||||
@ -151,6 +151,11 @@ export default defineConfig({
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
// Demo mock app UIs (electrumx, lnd, fedimint) + generic notice page.
|
||||
'/app/electrumx': { target: process.env.BACKEND_URL || 'http://localhost:5959', changeOrigin: true, secure: false },
|
||||
'/app/electrs': { target: process.env.BACKEND_URL || 'http://localhost:5959', changeOrigin: true, secure: false },
|
||||
'/app/lnd': { target: process.env.BACKEND_URL || 'http://localhost:5959', changeOrigin: true, secure: false },
|
||||
'/app/fedimint': { target: process.env.BACKEND_URL || 'http://localhost:5959', changeOrigin: true, secure: false },
|
||||
// Serve the node's deployed AIUI same-origin like production (set VITE_AIUI_URL=/aiui/)
|
||||
'/aiui': {
|
||||
target: process.env.AIUI_PROXY_TARGET || 'http://127.0.0.1:80',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user