The nginx sub_filter rewrite couldn't touch the SPA's runtime-built asset URLs, so the iframed IndeeHub rendered with broken links and images. The real site refuses iframing (X-Frame-Options), so the demo now opens https://indee.tx1138.com/ directly via the demo-external mechanism, whose isDemoExternal() check was previously hardcoded off. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
84 lines
3.1 KiB
TypeScript
84 lines
3.1 KiB
TypeScript
/**
|
|
* Public-demo helpers.
|
|
*
|
|
* The demo build (VITE_DEMO=1) replays the typing splash + intro/onboarding on
|
|
* EVERY fresh boot of the app at '/' (first visit or browser refresh) — see
|
|
* App.vue and RootRedirect.demoRoute. Also exposes the shared demo credentials
|
|
* shown on the login screen.
|
|
*/
|
|
|
|
export const IS_DEMO =
|
|
import.meta.env.VITE_DEMO === '1' || import.meta.env.VITE_DEMO === 'true'
|
|
|
|
/** Memorable shared password for the public demo (must match the mock backend). */
|
|
export const DEMO_PASSWORD = 'entertoexit'
|
|
|
|
/** Forget any legacy per-day gate marker (pre-2026-07 builds stored one). */
|
|
export function clearDemoIntroSeen(): void {
|
|
try {
|
|
localStorage.removeItem('demo_intro_date')
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|
|
|
|
// ── Demoable apps ───────────────────────────────────────────────────────────
|
|
// Only these apps actually do something in the demo (a mock UI or a real
|
|
// external site). Everything else shows "No demo" on a disabled install button
|
|
// and is not launchable.
|
|
// IndeeHub's real site sends X-Frame-Options: SAMEORIGIN, and the old
|
|
// same-origin nginx sub_filter proxy broke its runtime-built asset URLs —
|
|
// so the demo opens the real site directly instead.
|
|
const DEMO_EXTERNAL_URLS: Record<string, string> = {
|
|
indeedhub: 'https://indee.tx1138.com/',
|
|
}
|
|
|
|
// Apps loaded in the in-app iframe via a same-origin path. IndeeHub and Mempool
|
|
// are reverse-proxied by nginx (X-Frame-Options/CSP stripped + asset paths
|
|
// rewritten) so the frame-busting real sites can be embedded.
|
|
const DEMO_MOCK_UI: Record<string, string> = {
|
|
mempool: '/app/mempool/',
|
|
'mempool-web': '/app/mempool/',
|
|
'bitcoin-knots': '/app/bitcoin-knots/',
|
|
'bitcoin-core': '/app/bitcoin-core/',
|
|
bitcoin: '/app/bitcoin-core/',
|
|
'bitcoin-ui': '/app/bitcoin-ui/',
|
|
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/',
|
|
// Static placeholder dashboards served by the mock backend (DEMO_APP_PAGES).
|
|
'btcpay-server': '/app/btcpay-server/',
|
|
grafana: '/app/grafana/',
|
|
nextcloud: '/app/nextcloud/',
|
|
jellyfin: '/app/jellyfin/',
|
|
vaultwarden: '/app/vaultwarden/',
|
|
'nostr-rs-relay': '/app/nostr-rs-relay/',
|
|
searxng: '/app/searxng/',
|
|
'uptime-kuma': '/app/uptime-kuma/',
|
|
}
|
|
|
|
/**
|
|
* Whether a demo app opens externally (new tab / in-app browser) because its
|
|
* real site blocks iframing (X-Frame-Options).
|
|
*/
|
|
export function isDemoExternal(appId: string): boolean {
|
|
return appId in DEMO_EXTERNAL_URLS
|
|
}
|
|
|
|
/** Can this app be launched/installed in the demo? */
|
|
export function isDemoApp(appId: string): boolean {
|
|
return appId in DEMO_EXTERNAL_URLS || appId in DEMO_MOCK_UI
|
|
}
|
|
|
|
/** Resolve the demo launch URL for an app, or null if it isn't demoable. */
|
|
export function demoAppUrl(appId: string): string | null {
|
|
return DEMO_EXTERNAL_URLS[appId] ?? DEMO_MOCK_UI[appId] ?? null
|
|
}
|