2026-03-12 12:56:59 +00:00

4.2 KiB

name, description, disable-model-invocation, allowed-tools, argument-hint
name description disable-model-invocation allowed-tools argument-hint
add-web-app Add an external website as a web-only app to Archipelago (no container needed) true Bash, Read, Write, Edit, Glob, Grep [app-id] [url]

Add an external website ($ARGUMENTS) as a web-only app to Archipelago.

Web-only apps are external websites embedded in the Archipelago UI via iframe. They have no Docker container — they're bookmarks to public websites with full app-like detail pages.

Architecture

External websites that set X-Frame-Options or CSP headers blocking iframe embedding are proxied through nginx on dedicated ports (one port per site). This approach:

  • Strips X-Frame-Options so the iframe works
  • Serves the site at root / so SPA routing works correctly
  • Does NOT use subpath proxying (/ext/app/) which breaks SPAs
  • Optionally injects NIP-07 nostr-provider.js for Nostr login

Steps

1. Choose a port

Pick an unused port in the 8900-8999 range. Current allocations:

  • 8901: botfights.net
  • 8902: 484.kitchen
  • 8903: present.l484.com

2. Add nginx proxy server block

Add a new server block to image-recipe/configs/nginx-archipelago.conf at the end:

server {
    listen {PORT};
    server_name _;
    location / {
        proxy_pass https://{DOMAIN};
        proxy_http_version 1.1;
        proxy_set_header Host {DOMAIN};
        proxy_set_header Accept-Encoding "";
        proxy_ssl_server_name on;
        proxy_hide_header X-Frame-Options;
        proxy_hide_header Content-Security-Policy;
        proxy_hide_header Cross-Origin-Embedder-Policy;
        proxy_hide_header Cross-Origin-Opener-Policy;
        proxy_hide_header Cross-Origin-Resource-Policy;
        sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
        sub_filter_once on;
    }
    location = /nostr-provider.js {
        alias /opt/archipelago/web-ui/nostr-provider.js;
    }
}

3. Add to appLauncher.ts EXTERNAL_PROXY_PORT

In neode-ui/src/stores/appLauncher.ts, add the domain-to-port mapping:

const EXTERNAL_PROXY_PORT: Record<string, number> = {
  // ... existing entries
  '{DOMAIN}': {PORT},
}

4. Add to Apps.vue WEB_ONLY_APP_URLS and WEB_ONLY_APPS

In neode-ui/src/views/Apps.vue:

  1. Add to WEB_ONLY_APP_URLS: '{app-id}': 'https://{DOMAIN}'
  2. Add to WEB_ONLY_APPS with a synthetic PackageDataEntry:
    • state: 'running'
    • manifest with id, title, version, description
    • static-files with icon path

5. Add to dummyApps.ts

In neode-ui/src/utils/dummyApps.ts, add a full PackageDataEntry with:

  • Long description (for detail page)
  • Website URL in manifest
  • Icon path

6. Add to AppDetails.vue WEB_ONLY_APP_URLS

In neode-ui/src/views/AppDetails.vue, add to the WEB_ONLY_APP_URLS map.

7. Add app icon

Place icon at neode-ui/public/assets/img/app-icons/{app-id}.{png|webp|svg}

8. Deploy

# Build frontend
cd neode-ui && npm run build

# Deploy nginx config
scp image-recipe/configs/nginx-archipelago.conf archipelago@192.168.1.228:/tmp/
ssh archipelago@192.168.1.228 "sudo cp /tmp/nginx-archipelago.conf /etc/nginx/sites-available/archipelago && sudo nginx -t && sudo systemctl reload nginx"

# Deploy frontend
rsync -az --delete --exclude aiui --exclude claude-login.html web/dist/neode-ui/ archipelago@192.168.1.228:/opt/archipelago/web-ui/

9. Verify

  1. Open Archipelago UI
  2. Web-only app appears in My Apps (sorted alphabetically before container apps)
  3. Click app card -> detail page with title, description, launch button, no container buttons
  4. Click Launch -> iframe loads the external website correctly
  5. All assets load (no 404s in Network tab)
  6. window.nostr available in iframe console (NIP-07)

Files Modified

File What to add
image-recipe/configs/nginx-archipelago.conf New server block with proxy
neode-ui/src/stores/appLauncher.ts EXTERNAL_PROXY_PORT entry
neode-ui/src/views/Apps.vue WEB_ONLY_APP_URLS + WEB_ONLY_APPS entries
neode-ui/src/views/AppDetails.vue WEB_ONLY_APP_URLS entry
neode-ui/src/utils/dummyApps.ts Full PackageDataEntry for detail page
neode-ui/public/assets/img/app-icons/ App icon file