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:
- Add to
WEB_ONLY_APP_URLS:'{app-id}': 'https://{DOMAIN}' - Add to
WEB_ONLY_APPSwith a syntheticPackageDataEntry:- state:
'running' - manifest with id, title, version, description
- static-files with icon path
- state:
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
- Open Archipelago UI
- Web-only app appears in My Apps (sorted alphabetically before container apps)
- Click app card -> detail page with title, description, launch button, no container buttons
- Click Launch -> iframe loads the external website correctly
- All assets load (no 404s in Network tab)
window.nostravailable 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 |