Files
Brandon ThomasandClaude Opus 5.5 ec69f0be2c ArtCraft Launcher: install and update the Craft App Suite
A native Rust/egui launcher for the 12 Craft Apps (7 classic + 5 new).

- Grid (icon cards) or sortable table view, filters and search
- Status per app: available, installed and up to date, or update
  available with version and release date
- Installs where each OS keeps apps, from the official release packages:
  /Applications (DMG), Program Files (MSI), deb/rpm via the system
  package manager (Flatpak/AppImage fallback), /usr/local on FreeBSD
- Detects apps installed by hand; updates keep the installed format
- Every download verified against its published SHA-256; running apps
  are never replaced
- Tray/menu-bar mode, start at login, one notification per new version
- GitHub API with ETag cache, falling back to release pages when
  rate-limited; release source is pluggable for a future catalog API
- Web build lists latest releases with per-platform downloads
- Packaging and release workflows for macOS, Windows (x64/x86/arm64),
  Linux (x86_64/aarch64), FreeBSD and web

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:08:24 -04:00

77 lines
3.4 KiB
Markdown

# Hosting ArtCraft Launcher for the web
`artcraft-launcher-web-<version>.zip` (from the GitHub release, or `packaging/web/package.sh`)
holds a static site in `artcraft-launcher-web-<version>/`:
| File | What it is |
|---|---|
| `index.html` | The page. It loads everything through relative URLs. |
| `artcraft-launcher-web-<hash>.js` | wasm-bindgen glue (generated, ES module) |
| `artcraft-launcher-web-<hash>_bg.wasm` | The app (egui, built with the `wasm-release` Cargo profile) |
| `_headers`, `.htaccess` | Sample header rules for Netlify/Cloudflare Pages and Apache |
There is no server-side code and no hand-written JavaScript. Upload the folder's contents anywhere
that serves static files.
## What the web version does
In the browser the launcher can't install anything: it shows the Craft App Suite catalog, the
latest release of each app and the right download for the visitor's platform, and links to the
files on GitHub. Release data comes straight from the GitHub REST API (`api.github.com` allows
cross-origin requests), so the page needs no backend. Unauthenticated visitors share GitHub's
limit of 60 API requests per hour per IP address.
## Any path works
All URLs in `index.html` are relative (`public_url = "./"` in `apps/artcraft-launcher-web/Trunk.toml`),
so the site works at a domain root (`https://example.com/`), under a prefix
(`https://example.com/apps/launcher/`) and from a CDN bucket. The asset names carry a content
hash, so they can be cached forever. Only `index.html` needs revalidation.
`packaging/web/package.sh` fails if the wasm grows past 24 MiB (Cloudflare Pages and Workers
reject any single file over 25 MiB).
## Required server settings
- **MIME type:** serve `.wasm` as `application/wasm`. Browsers refuse to stream-compile it under
any other type. Serve `.js` as `text/javascript`. Most hosts already do both. For nginx, check
that `mime.types` has `application/wasm wasm;`.
- **Compression:** turn on gzip or Brotli for `.wasm`, `.js` and `.html`.
- **Caching:** `Cache-Control: public, max-age=31536000, immutable` on the hashed `.wasm` and
`.js` files, and `no-cache` on `index.html`.
- **Content Security Policy:** if you send one, allow `connect-src https://api.github.com` (and
`https://raw.githubusercontent.com` for the app icons) plus `'wasm-unsafe-eval'` in `script-src`.
- **No special isolation headers:** the app doesn't use `SharedArrayBuffer`, so it doesn't need
`Cross-Origin-Opener-Policy` or `Cross-Origin-Embedder-Policy`.
nginx example:
```nginx
location /launcher/ {
types { application/wasm wasm; text/javascript js; text/html html; }
gzip on;
gzip_types application/wasm text/javascript text/html;
location ~* \.(wasm|js)$ { add_header Cache-Control "public, max-age=31536000, immutable"; }
location ~* index\.html$ { add_header Cache-Control "no-cache"; }
}
```
Local test: `python3 -m http.server 8765` inside the folder, then open http://localhost:8765/.
## Embedding in a page (iframe)
```html
<iframe
src="https://example.com/launcher/"
title="ArtCraft Launcher"
style="width: 100%; height: 640px; border: 0;"
allow="fullscreen"
allowfullscreen>
</iframe>
```
- The app fills the iframe and follows its size, so size the iframe and not the app.
- **Sandboxed iframes** need at least `sandbox="allow-scripts allow-same-origin allow-popups"`;
`allow-popups` lets download links open.
- Don't send `X-Frame-Options: DENY` or a `frame-ancestors` CSP that excludes the embedding page.