# Visual & UX expectations for casino iframe games
Make your casino iframe feel at home in the host. Build around snapshots, theme and locale settings, readable controls, and motion players can dial down.
:::note[Current SDK checkout]
- `@chain-protocol/casino-sdk@0.7.0`
This guidance reflects this checkout and may include unreleased changes.
[Casino changelog](/sdk/casino/changelog/)
:::
## Runtime environment
- The main app embeds your game in an **iframe** with
`sandbox="allow-scripts allow-same-origin"`
(see `packages/web/src/features/casino/CasinoGameFrameClient.tsx`).
Design for a **single-page guest** that does not navigate away or open new windows unless you intentionally handle it (some flows may be limited by sandbox).
- The host owns wallet, Smart Vault, and signing. Your UI should assume **no direct wallet access** — reflect state from **`HostSnapshot`** only.
## Snapshot-driven UI
The host pushes:
- **`wallet`**, **`token`**, **`balances`** (e.g. Smart Vault balance as string)
- **`sessions`** — active/settled sessions with `raw.gameData`, `raw.gameState`, `raw.randomness`, phases
- **`ui.locale`**, **`ui.theme`** — **`light` | `dark` | `system`**
A polished guest should **respect `ui.theme` and `ui.locale`** where practical (CSS variables, `prefers-color-scheme` when `system`, or reading parent theme if you mirror tokens).
## Manifest (`game.manifest.json`)
Served at **`{gameBaseUrl}/game.manifest.json`** (same origin as the game). Validated by `validateCasinoGameManifest` in `/casino-sdk` (`src/manifest.ts`). Required fields include:
- **`presentation`**: `mode` (`full-iframe` | `embedded`), `hostPanels` toggles (whether the host shows open-session / history / status chrome — your layout can leave room accordingly).
- **`capabilities`**: `openSession` must be `true` for betting games; booleans for `submitAction`, `forfeitExpiredSession`, `cancelStuckRandomness`, `resize`.
- **Dynamic height**: call `observeGameContentSize(hostApi)` from `@chain-protocol/casino-sdk/guest` after the bridge resolves so the host can size the iframe to your current content.
Example: [`examples/coinflip-public/game.manifest.json`](/sdk-source/bb67ab463ab7/game.manifest.json.txt).
**Game description**: each `locales[].description` is the catalog's game description for that locale. It is optional. When the platform builds your game, it reads the manifest from the build's preview deployment and copies every non-empty description of 500 characters or fewer into the catalog; a longer one is dropped with a warning in the build log. A player sees the description of their locale, a locale of the same language (`pt-BR` for `pt`), or else the one of `defaultLocale`. A game with no description shows none. A frontend-only update brings in the new build's descriptions.
**Cover image**: `assets.coverUrl` is the game's catalog cover image. It is either a path relative to `game.manifest.json`, which points into the build's preview deployment (for example `cover.webp` in your frontend's public folder), or an absolute `https://` URL. Any other scheme is skipped. The image must be PNG, JPEG or WebP, at most 2 MB, 2:3 portrait (width to height, within about 2%) and at least 230×345. When the platform builds your game, it copies the image into platform storage, so the catalog keeps working if your origin moves. While the manifest names a usable cover image, the submit form shows it read-only and takes no upload. An unreachable or unusable image is a warning in the build log that gives the reason, and the submit form then asks for an upload. A frontend-only update brings in the new build's cover image, or keeps the current one when the new manifest has none.
**`gameId`**: Must match the canonical id derived from on-chain game registration (`canonicalCasinoGameId` in `manifest.ts` — strips trailing `Game`, lowercases, alphanumeric only). Host rejects mismatches.
## Alignment with main web app (if integrated in-repo later)
Internal rules for the Next.js app:
- User-visible strings go through **i18n** (`packages/web/src/i18n/locales/en.json`), not hardcoded English in JSX.
- Follow existing **shadcn / Tailwind** patterns if contributing UI inside `packages/web` (not required for a static guest bundle).
## Motion & accessibility
- Slot games often use heavy animation; prefer **reduced motion** via `prefers-reduced-motion` for accessibility.
- Ensure **tap targets** and contrast work at the height your game reports to the host.
## Assets
`manifest.assets.iconUrl` is optional; used in discovery when provided. `manifest.assets.coverUrl` is the catalog cover image; see "Cover image" above.