--- name: web-only-apps description: Web-only apps (no container) — L484 category, BotFights, IndieHub. Iframe compatibility, nginx proxying, My Apps injection. type: project --- ## Web-Only Apps (added 2026-03-11) These apps are external websites embedded via iframe — no Docker container. They show as "installed" in both the marketplace and My Apps. ### L484 Category - **NWNN** (nwnn.l484.com) — News aggregator. No X-Frame-Options. Works in iframe directly. - **484 Kitchen** (484.kitchen) — K484 platform. X-Frame-Options: SAMEORIGIN. Proxied via `/ext/484-kitchen/`. - **Call the Operator** (cta.tx1138.com) — Decentralization portal. No X-Frame-Options. Works in iframe directly. - **Arch Presentation** (present.l484.com) — Archipelago presentation. X-Frame-Options: SAMEORIGIN. Proxied via `/ext/arch-presentation/`. - **Syntropy Institute** (syntropy.institute) — Medicine Reimagined. No X-Frame-Options. Works in iframe directly. - **T-0** (teeminuszero.net) — Decentralization documentary. No X-Frame-Options. Works in iframe directly. ### Other Web-Only Apps - **BotFights** (botfights.net) — X-Frame-Options: SAMEORIGIN + CSP + COEP/COOP/CORP. Proxied via `/ext/botfights/`. Nginx strips all blocking headers. - **IndeeHub** (archipelago.indeehub.studio) — No X-Frame-Options. Works in iframe directly. ### Nginx External Proxies Sites with X-Frame-Options get reverse-proxied through nginx at `/ext/{app-id}/`: - `proxy_hide_header X-Frame-Options` strips upstream header - `add_header X-Content-Type-Options "nosniff" always` prevents server-level X-Frame-Options inheritance - BotFights also strips `Cross-Origin-Embedder-Policy`, `Cross-Origin-Opener-Policy`, `Cross-Origin-Resource-Policy` - Proxy locations in both HTTP and HTTPS server blocks of nginx-archipelago.conf ### Frontend Implementation - **appLauncher.ts**: `EXTERNAL_PROXY` map rewrites external URLs to proxy paths in `toEmbeddableUrl()` - **Apps.vue**: `WEB_ONLY_APPS` constant with synthetic `PackageDataEntry` objects. Sorted first alphabetically. No uninstall/start/stop buttons. - **Marketplace.vue**: `dockerImage: ''` + `webUrl` in `getCuratedAppList()`. L484 category. - **Icons**: `neode-ui/public/assets/img/app-icons/{app-id}.png` (or .svg)