PickBits SDK Reference
Drop-in JavaScript SDK for games and apps on *.pickbits.ai. Handles authentication, cross-subdomain single sign-on, saved progress, achievements, leaderboards, and premium entitlements. Version 1.x.
Install
Add a single <script> tag. The SDK is served from the main site, exposes window.PickBits, and self-loads the Supabase JS client from CDN.
<script src="https://pickbits.ai/sdk/pickbits-sdk.js"></script>
Initialise
Call PickBits.init() once with a gameSlug matching the slug registered in the achievements table.
PickBits.init({
gameSlug: 'remme',
economy: { // optional
type: 'coins',
name: 'Remme Credits',
icon: 'fa-coins',
getBalance: () => game.getCoins(),
storeUrl: '/store'
}
});
?pb_token= from the URL on init. If present, it exchanges the relay token for a Supabase session and strips the query param via history.replaceState. This is how cross-subdomain SSO lands the user automatically — see SSO.
Auth
| Method | Returns | Notes |
|---|---|---|
PickBits.isAuthenticated() | boolean | Sync. |
PickBits.getUser() | { id, email, username, display_name, avatar_url, level } | null | Sync. Populated after fetchProfile resolves. |
PickBits.onAuthChange(cb) | void | Fires on sign-in / sign-out. Passes the current user object or null. |
PickBits.promptLogin() | void | Redirects to pickbits.ai/dashboard?login=1&redirect=<returnURL>. |
Cross-subdomain SSO
Main-site → subdomain sign-in flow (Phase 1, pb_sso_phase1):
- User is signed in on
pickbits.ai. - Main site calls
window.pbAuth.linkTo('https://feedrunner.pickbits.ai/')— this mints an HMAC-signed relay token (60s TTL, single-use viaconsumed_relay_tokens) via therelay-tokenedge function and redirects with?pb_token=appended. - Destination subdomain loads the SDK, sees
?pb_token=, POSTsaction: "exchange"torelay-token, receives an OTP token hash, and callssupabase.auth.verifyOtp. A native Supabase session materialises in local storage — no additional credential entry.
window.pbAuth.signOut() on the main site calls the revoke-sessions edge function, which invokes supabase.auth.admin.signOut(jwt, "global"). Refresh tokens invalidate immediately; access tokens across subdomains expire within their 1h lifetime. No per-device session UI in v1.
Integrators on subdomains don't need to wire anything for SSO — just include the SDK and the token exchange is automatic. To initiate a cross-domain link from the main site, use pbAuth.linkTo().
Saved progress
| Method | Description |
|---|---|
PickBits.saveProgress(data) | Upserts a JSONB blob into game_progress.save_data for (user_id, game_slug). |
PickBits.loadProgress() | Returns { save_data, high_score, playtime_seconds, last_played_at } | null. |
// Autosave
setInterval(async () => {
if (PickBits.isAuthenticated()) {
await PickBits.saveProgress({ level: 7, inventory: game.getInventory() });
}
}, 30_000);
{ slot } parameters and transparent routing to Vercel Blob for saves > 100 KB. Today's single-slot JSONB call is forward-compatible — calling saveProgress(data) without slot continues to write to slot 0.
Achievements
| Method | Description |
|---|---|
PickBits.unlockAchievement(slug) | Idempotent — calls claim-achievement edge function. Safe to replay. |
PickBits.getAchievements() | Returns this user's unlocks for this game + global achievements. |
PickBits.unlockAchievement('first-win').then(res => {
if (res.ok) toast(`+${res.xp_awarded} XP — ${res.achievement.title}`);
});
Leaderboards
PickBits.submitScore(score) posts to the submit-score edge function, which enforces "only update if higher" on the server. No client-side check required.
PickBits.submitScore(gameOverScore);
Premium entitlements
Phase 4 surface. Call on feature gates to check whether the signed-in user has an active experimenter subscription.
| Method | Returns |
|---|---|
PickBits.isPremium() | Promise<boolean> — cached 60s in-memory. |
PickBits.getTier() | Promise<'free' | 'experimenter' | null> |
isPremium() is a UX optimisation — server-side edge functions re-check via the is_user_premium(uuid) SQL function for anything that costs real money (e.g. premium AI calls).
Analytics bridge
PickBits.trackEvent(name, props) forwards to PostHog if it's loaded on the page, enriching every event with pb_game, pb_authenticated, and pb_user_id.
PickBits.trackEvent('level_complete', { level: 7, duration_s: 142 });
Versioning
The SDK reads its version from PickBits.version (exposed in Phase 3) and sends it as a custom header on edge-function calls for server-side compatibility tracking. Breaking changes cut a major version; the <script> tag pins to the latest by default.
Support
Issues, questions, or integrations: open a ticket against PIC-17 on the internal board, or DM Dex on the agent network. SDK source lives at pickbits.ai/sdk/pickbits-sdk.js — no bundler, no npm publish.