Pixlland

The Pixlland SDK is a thin layer over postMessage that negotiates a session with the portal and exposes a typed Promise API. Every method is safe to call in standalone (no portal) — it degrades to local-only stubs so dev work never requires a server.

Include the SDK

Games loaded via the portal get the SDK for free from pixlland.com/sdk/v1/pixlland.js. For local dev or third-party embedding:

<script src="https://pixlland.com/sdk/v1/pixlland.js" defer></script>

The script auto-exposes window.PixllandSDK. Bundled workflows can instead use the npm package:

import { PixllandSDK } from '@pixlland/sdk';

Lifecycle, end to end

Every hosted game should follow this order. Deviating is not fatal, but it makes your game worse at the behaviours the portal tracks.

  1. await init() — handshake with the portal. Returns { gameId, locale, signedIn }. 4-second standalone fallback when no portal is detected so local dev always resolves.
  2. gameLoadingProgress(r) — drive the progress bar. r is clamped to [0, 1].
  3. gameLoadingFinished() — signal ready-to-play. Call exactly once.
  4. gameplayStart() — user clicked Play / round started. Gates ad breaks (only allowed during an active gameplay session).
  5. gameplayStop() — death, pause, main menu, or tab close. Pair with a previous gameplayStart.

Ad breaks

// Interstitial between rounds. Resolves when the ad finishes
// or instantly when no fill / no consent / standalone.
if (roundsBeaten % 3 === 0) await PixllandSDK.commercialBreak();

// Rewarded — ALWAYS check granted before unlocking the reward.
const { granted, reason } = await PixllandSDK.rewardedBreak();
if (granted) player.coins += 100;

Both calls respect the player's cookie consent. If ads consent is revoked, commercialBreak() resolves immediately and rewardedBreak() returns { granted: false, reason: 'ad_blocked' }.

Accounts + cloud save

// Profile fields only — never email / tokens
const user = await PixllandSDK.account.get();
if (!user) await PixllandSDK.account.signIn();

// Short-lived (60 s) JWT to prove identity to YOUR backend
const token = await PixllandSDK.account.getToken();
fetch('/leaderboard/submit', {
  headers: { Authorization: 'Bearer ' + token },
});

// Cross-device save — JSON serialisable, 64 KB max per key
await PixllandSDK.data.set('progress', { level: 7, coins: 42 });
const progress = await PixllandSDK.data.get('progress');

data.* rows are scoped per-game + per-user — another author cannot read your saves.

Deep links

// Seeds with the current URL params from the portal page.
const url = PixllandSDK.shareableURL({ level: '5' });
// => https://pixlland.com/play/<slug>?level=5

// On cold load, read params the portal forwarded into the iframe.
const level = PixllandSDK.getURLParam('level'); // "5" | null

Observability

try { saveProgress(); }
catch (e) { PixllandSDK.captureError(e); }  // pipes to Sentry

PixllandSDK.measure('progress', 'level', 'completed');
PixllandSDK.happyTime(1);  // seconds of fun delivered this frame

Full reference

Auto-generated TypeDoc site: /sdk-docs/. Source of truth is the TypeScript surface shipped with @pixlland/sdk.

Next steps

SDK Basics · Pixlland Developers