126 lines
4.2 KiB
Markdown
126 lines
4.2 KiB
Markdown
---
|
|
name: add-web-app
|
|
description: Add an external website as a web-only app to Archipelago (no container needed)
|
|
disable-model-invocation: true
|
|
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
|
|
argument-hint: "[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:
|
|
|
|
```nginx
|
|
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:
|
|
|
|
```typescript
|
|
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
|
|
|
|
```bash
|
|
# 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 |
|