mirror of
https://github.com/storytold/craft-launcher.git
synced 2026-10-13 23:08:16 +00:00
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>
77 lines
3.4 KiB
Markdown
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.
|