Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| .htaccess | ||
| README.md | ||
| _headers | ||
| package.sh | ||
README.md
Hosting GridCraft for the web
gridcraft-web-<version>.zip (from the GitHub release, or packaging/web/package.sh) holds a
static site in gridcraft-web-<version>/:
| File | What it is |
|---|---|
index.html |
The page. It loads everything through relative URLs. |
gridcraft-web-<hash>.js |
wasm-bindgen glue (generated, ES module) |
gridcraft-web-<hash>_bg.wasm |
The app (compresses to roughly a third with gzip/Brotli) |
_headers, .htaccess |
Sample header rules for Netlify/Cloudflare Pages and Apache |
There is no server-side code. Upload the folder's contents anywhere that serves static files.
Any path works
All URLs in index.html are relative (public_url = "./" in apps/gridcraft-web/Trunk.toml),
so the site works at a domain root (https://example.com/), under a prefix
(https://example.com/tools/gridcraft/) and from a CDN bucket. The asset names carry a content
hash, so they can be cached forever. Only index.html needs revalidation.
Required server settings
- MIME type: serve
.wasmasapplication/wasm. Browsers refuse to stream-compile it under any other type, and the app then loads slowly or not at all. Serve.jsastext/javascript. Most hosts already do both. For nginx, check thatmime.typeshasapplication/wasm wasm;. - Compression: turn on gzip or Brotli for
.wasm,.jsand.html. That cuts the download to roughly a third. You can also precompress (brotli -k *.wasm) and let the server sendContent-Encoding: br. - Caching:
Cache-Control: public, max-age=31536000, immutableon the hashed.wasmand.jsfiles, andno-cacheonindex.html. - HTTPS: WebGPU (and the clipboard) only work in a secure context, which means
https://orhttp://localhost. Over plain HTTP elsewhere, the app falls back to WebGL2. - No special isolation headers: GridCraft doesn't use
SharedArrayBuffer, so it doesn't needCross-Origin-Opener-PolicyorCross-Origin-Embedder-Policy. If your site already sends COEPrequire-corp, also sendCross-Origin-Resource-Policy: same-origin(orcross-originwhen the files live on a CDN) on the app's files.
nginx example:
location /gridcraft/ {
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)
<iframe
src="https://example.com/gridcraft/"
title="GridCraft spreadsheet"
style="width: 100%; height: 720px; border: 0;"
allow="fullscreen; clipboard-read; clipboard-write"
allowfullscreen>
</iframe>
- The app fills the iframe and follows its size, so size the iframe and not the app.
- Keyboard shortcuts go to the iframe after the user clicks into it, as with any embedded app.
- Cross-origin embeds work. Preferences are kept in the iframe's
localStorage. Browsers that partition or block third-party storage may forget them between visits, and the app then starts with defaults. - Sandboxed iframes need at least
sandbox="allow-scripts allow-same-origin allow-downloads allow-popups". Withoutallow-same-originthere's no storage. Withoutallow-downloads, Save and Export (browser downloads) are blocked. - Don't send
X-Frame-Options: DENYor aframe-ancestorsCSP that excludes the embedding page.
Renderer selection
GridCraft's web build is the same egui app as the desktop one, compiled to wasm
(apps/gridcraft-web). It renders with the backend apps/gridcraft-web selects (WebGPU
where available, otherwise WebGL2). If the web app adds URL flags to force a backend (as the
sibling Craft apps do with ?webgl / ?cpu), document them here; they also work on the
iframe src.
A browser with neither WebGPU nor WebGL2 gets a message in place of the app.