The frame
What a game can and cannot do inside uloggd's player, how it starts and stops, and the parameters it is launched with.
The game runs in an iframe, on a uloggd page built for that game alone. The page's policy lets the frame hold your origin and nothing else, and the frame stays covered until the SDK completes its handshake.
The sandbox
<iframe
src="https://orbit.example.com/?frame_id=...&instance_id=...&platform=desktop&locale=en&mode=live&protocol=1"
sandbox="allow-scripts allow-same-origin allow-forms"
allow="autoplay; gamepad; ..."
referrerpolicy="strict-origin"
></iframe>| Token | When |
|---|---|
allow-scripts | Always. |
allow-same-origin | Always. The game keeps its own origin, which gives it storage and gives uloggd an origin to verify. It is safe because that origin is never uloggd's. |
allow-forms | Always, so submit events fire. |
allow-pointer-lock | Only when the release declares the pointer-lock capability. |
Never granted: popups, top navigation, modal dialogs, downloads, the Storage Access API, orientation lock and presentation. In practice:
window.open, links withtarget="_blank"andtop.locationfail. In v1 a game cannot open links at all; the store page carries your privacy policy, terms and support links.alert,confirmandpromptdo nothing. Draw your own dialogs.
Permissions
The allow attribute delegates autoplay and gamepad. Everything else is
denied, by the attribute and by the player page's Permissions-Policy: camera,
microphone, geolocation, payments, USB, serial, HID, Bluetooth, screen
capture, WebAuthn and the other credential APIs, local fonts, window
management, idle detection, picture-in-picture, the privacy sandbox APIs, and
local network access. Firefox ignores the Permissions-Policy header.
Local network access is denied on every uloggd page but one: the page of your
development URL, and only when
that URL is on your own machine. There, the page's policy and the frame's
allow let the frame reach that one loopback origin, and nothing else on your
network. The browser may still ask you first.
Fullscreen belongs to uloggd's page, and the game asks for it through the SDK (below).
The first request for your entry URL carries Referer: https://uloggd.com/,
never the page's path.
Storage and cookies
- Storage is partitioned by the top-level site. localStorage, IndexedDB, the Cache API and service workers inside uloggd are separate from the same game opened on your own site, and a player who clears uloggd's site data clears them. Keep anything that matters on your server.
- Cookies are not reliably partitioned. Safari blocks third-party cookies
and Firefox keeps them apart per site, but Chrome still sends your
unpartitioned cookies, and those of every third party the game embeds. Do
not build sessions on cookies: once your server has verified an identity
token, give the game a token of your own and send it in an
Authorizationheader. If you must set a cookie, mark itSameSite=None; Secure; Partitioned. - A service worker you register lives in uloggd's partition and keeps serving what it cached to returning players, whatever your server serves today, and uloggd's checks cannot see it. If you use one, tie its cache to the build.
One document, start to finish
- Any navigation of the frame removes the game: a second
loadevent, a closed message channel, or a navigation the page's policy blocked. The player is told the game restarted, with a button to play again. Multi-page games andlocation.reload()are not supported. - The page's policy admits only your exact origin, so the browser blocks a redirect or a link to any other one.
- Frames you nest inside the game inherit the sandbox, but they follow your own Content-Security-Policy, not uloggd's. Declare every third party you embed in the release.
- Never call
history.back(): from a sandboxed frame it can move the player's whole tab.
Starting, staying alive, closing
- Handshake.
createArcadeSDKsends uloggd a handshake, and uloggd answers with a private message channel. The frame stays covered until then; after 30 seconds the player is told the game did not load. Create the SDK as the first thing the page does, before downloading large assets, so the player sees your own loading screen. - Liveness. uloggd pings the game every second, and the SDK answers. After 2 seconds without an answer the frame is covered again and the player is told the game is not responding; the next answer uncovers it. Keep the main thread free: split long work, or move it to a worker.
- Hidden tab. After 5 minutes hidden (15 with the
background-audiocapability), uloggd sendsCLOSINGand removes the frame. - Closing. When the player presses Close, the game gets
CLOSINGand up to 1 second to save before the frame is removed. Save as you go rather than counting on that second. - Suspension. If uloggd suspends the game, new launches are refused at once, and running frames are closed with code 4010 within 60 seconds.
Fullscreen and pointer lock
- The frame cannot go fullscreen on its own. Call
arcade.commands.requestFullscreen()from a click or a key press: uloggd puts its own container in fullscreen, with its bar still visible, or fills the screen on an iPhone. Without a recent gesture the call fails withrequires_gesture. - Declare the
pointer-lockcapability to userequestPointerLock(). uloggd cannot see a lock your game holds, so for such a release its consent dialog never opens on its own: whenauthorizeasks, the player's bar shows the request with an Answer button and says that Esc releases the pointer, and the dialog opens from that click. Without the capability,authorizeopens the dialog directly.
Launch parameters
uloggd appends its own query to your entry URL:
?frame_id=Q1r9...&instance_id=0b7e...&platform=desktop&locale=en&mode=live&protocol=1| Parameter | Value |
|---|---|
frame_id | 22 base64url characters, used by the SDK in the handshake. |
instance_id | A uuid for this play. |
platform | desktop or mobile. |
locale | pt-BR, en or es. |
mode | live, or test when you open your own release in test mode or your development URL. Reviewers play in live. |
protocol | 1. |
Nothing in it identifies the player, so your logs and analytics may keep it.
The SDK reads it for you, and the same values arrive in context when
ready() resolves.
Limits to know
- Review certifies a moment, not a build. Daily checks, new reviews, player reports and suspension are how uloggd keeps following a game after approval.
- Players' IP addresses reach your servers and every third party the game loads.
- Where a browser does not give cross-site frames a process of their own (Safari, Firefox for Android and Chrome for Android), a game that blocks its main thread also freezes uloggd's page around it, until it yields.
- No header can stop a clipboard write after a gesture. Asking players to paste or run something is against the rules (see Review policy).