Appearance
Sandbox restrictions
Apps run in a blob-URL iframe sandboxed with allow-scripts allow-forms only. Same-origin and top-navigation are off, so several browser APIs throw or silently fail:
- Storage APIs blocked.
localStorage,sessionStorage,IndexedDB, and cookies all throw — there is noallow-same-origin. Don't reach forlocalStorageto survive refresh; it won't work. Persist per-user state in aprivateOfUser(self)table and shared state in a public table. - No top-level URL navigation.
window.location.href = …,location.assign, top-levelwindow.open,target="_top", and cross-originhistory.pushStateall fail. To switch apps, callPoe.open({ typeId, instanceId, openProps? })frompoe-tiles-sdk. Outbound links work via<a target="_blank" rel="noopener">. window.location.originis"null". UsePoe.topOriginfor an absolute host URL.- No cross-frame DOM access. Reading the parent document or any other frame is blocked. Talk to the host via the SDK's
postMessagewrappers. - Web Workers work, but only from a blob or data URL. A worker script has to be embedded in your code, not loaded by path — there is no origin or server behind the iframe, so
new Worker("./worker.js")andnew Worker(new URL("./worker.ts", import.meta.url))both fail (the latter withTypeError: Invalid URL, andpoeTile()rejects it at build time). Bundled apps:import MyWorker from "./worker.ts?worker&inline"— the&inlinematters, since a plain?workerimport compiles to a path nothing serves here (poeTile()rejects that at build time too). No-build apps: blob your worker source yourself, ornew Worker(await Poe.getBundleAssetUrl("worker.js")). Recipes for both are in Vite Plugin → Web Workers. Use classic worker syntax; a module script cannot be fetched from a blob URL here.SharedWorkeris denied to the opaque origin outright, andnavigator.serviceWorker.registeris blocked. A worker inherits the sandbox, so it has no storage or network of its own.