Developer guide

Your game. Our platform. One plug.

Game Portal is built to be plugged into. You keep your engine, your hosting and your gameplay — the SDK plugs your game into centralized accounts, anti-cheat leaderboards, cloud saves and the unified coin economy shared by every game here.

🔐 One account, every game🏆 Real-time leaderboards🛡️ Anti-cheat score pipeline💾 Cloud saves◉ Unified wallet & payments🗄️ Isolated per-game data

⚡ The fast path: hand this prompt to your AI copilot

Working with Claude, Cursor, Copilot or any coding assistant? Copy the prompt below into it alongside your game's code. It carries the full integration contract, so your assistant can wire up auth, scores, leaderboards, cloud saves and the wallet — and produce the registration JSON we ask for in the application form at the bottom of this page. Fill in the last line with your game's details.

You are helping me integrate my existing game with Game Portal, a gamification platform whose essence is pluggability: my game keeps its own code and hosting, and plugs into platform services through the @gameportal/sdk npm package.

Platform contract:
- SDK: npm install @gameportal/sdk. Construct once: new GamePortal({ supabaseUrl, supabaseAnonKey, gameId, gameSecret }) — I will provide the four values (issued by the platform's Dev Console when the game is registered).
- Auth: portal.signIn(email, password), portal.signUp(email, password, username), portal.signOut(), portal.onAuthStateChange(callback). Players use ONE platform account across all games — gate gameplay behind a signed-in user; never build separate accounts.
- Scores: at the natural end of a run/level call portal.submitScore(score). The SDK signs the payload (HMAC + one-time nonce + timestamp) and the platform validates it server-side; scores must never be written any other way. Response: { ok, score, rank }, where score is the stored value after the game's score_mode (highest | latest | cumulative) is applied. Impossible scores above the game's max_score are rejected.
- Leaderboard: portal.getLeaderboard(limit) and portal.getMyRank() to render; portal.onLeaderboardChange(callback) fires in real time when any player's score changes.
- Cloud saves: portal.saveProgress(object) / portal.loadProgress() — schemaless JSONB, up to 256 KB per player, isolated in the game's own database schema.
- Unified economy: portal.getWallet(), portal.onWalletChange(callback) (fires in real time when coins are credited, e.g. after an IAP webhook — grant goods there), portal.getItems(), portal.purchaseItem(itemId), portal.getInventory(), portal.transferCoins(username, amount).
- Paid games only: gate with const owned = await portal.ownsGame(); if not owned, offer await portal.purchaseGame() which spends wallet coins atomically.

Your task:
1. Add a sign-in / sign-up screen using the SDK and show the game only when a user is authenticated.
2. Wire score submission at the natural end of a run/level and render a leaderboard panel that updates via onLeaderboardChange.
3. Persist player progress with cloud saves at sensible checkpoints and restore it on load.
4. Display the unified wallet balance and subscribe to wallet changes. If my game is paid, add the ownsGame/purchaseGame paywall before gameplay.
5. Keep ALL of my existing gameplay code intact — the integration must be additive, matching my project's language, style and build setup.
6. Produce a registration JSON for the platform, shaped exactly like:
   { "name": "...", "slug": "my-game", "description": "...", "platforms": ["web"], "play_url": "https://...", "price_coins": 0, "score_mode": "highest", "max_score": 100000 }
   (slug: 3-48 chars of a-z, 0-9, hyphens. score_mode: highest = keep personal best, latest = overwrite, cumulative = sum. max_score: honest ceiling used for anti-cheat.)

My game details: [describe your game, engine/framework, where a run ends in the code, what should be cloud-saved, and whether it is free or coin-priced]

1Create a platform account

Sign up like any player. The moment you register a game, your account becomes a developer account and the Dev Console appears in the top bar.

2Register your game

Register in the Dev Console, or straight from the API. Set the Play URL to wherever your game is hosted — hosting stays entirely yours; the portal just links players to it.

curl -X POST $SUPABASE_URL/functions/v1/register-game \
  -H "Authorization: Bearer $YOUR_JWT" -H "apikey: $ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Game",
    "slug": "my-game",
    "description": "One line that sells it.",
    "platforms": ["web", "pc"],
    "play_url": "https://mygame.example.com",
    "price_coins": 0,
    "score_mode": "highest",
    "max_score": 100000
  }'

You get back a game_id and a signing secret, and the platform provisions an isolated database schema (game_<id>) just for your game — its leaderboard and cloud saves never collide with anyone else's. Choose score_mode: highest (personal best), latest (overwrite) or cumulative (sum). max_score is the server-side sanity cap that rejects impossible submissions.

3Install and initialize the SDK

npm install @gameportal/sdk
import { GamePortal } from "@gameportal/sdk";

const portal = new GamePortal({
  supabaseUrl: "<platform API url>",
  supabaseAnonKey: "<platform anon key>",
  gameId: "<your game_id>",
  gameSecret: "<your signing secret>",
});

That object is your entire integration surface. Everything below is a method on it.

4Let players sign in — once, for every game

Players use the same account in your game as in every other game on the platform. No separate registration, no separate password.

await portal.signIn(email, password);       // or portal.signUp(...)

portal.onAuthStateChange((user) => {
  // show your game when user != null, your sign-in screen otherwise
});

5Submit scores through the anti-cheat pipeline

One call. The SDK signs the payload (HMAC-SHA256 with your secret), adds a one-time nonce and a timestamp, and the platform verifies all of it server-side before the score can touch your leaderboard — replays, tampering and impossible scores are rejected.

const result = await portal.submitScore(finalScore);
// { ok: true, score: 4200, rank: 3 }  — after your game's score_mode is applied

6Show the live leaderboard

const top = await portal.getLeaderboard(15);   // [{ rank, username, score, ... }]
const me  = await portal.getMyRank();          // { rank, score, total_players }

portal.onLeaderboardChange(() => {
  // fires in real time when any player's score changes — re-render here
});

7Cloud saves — free, isolated, schemaless

Every game gets JSONB progress storage in its own schema. Shape it however you want, up to 256 KB per player.

await portal.saveProgress({ level: 7, upgrades: ["shield", "boost"] });
const save = await portal.loadProgress();

8Tap into the unified economy

One wallet across the whole platform. Coins bought anywhere (Stripe, Apple, Google, PayPal — handled by the platform, not by you) can be spent in your game, and wallet credits arrive in your game in real time.

const { balance } = await portal.getWallet();

portal.onWalletChange((w) => {
  // fires instantly when an IAP webhook credits the player — grant the goods here
});

// Sell in-game items you defined in the Dev Console:
const items = await portal.getItems();
await portal.purchaseItem(itemId);

// Premium game? Gate it with two calls:
const owned = await portal.ownsGame();
if (!owned) await portal.purchaseGame();   // spends wallet coins, atomic server-side

9Publish

Flip your game to Published in the Dev Console. It immediately appears in the game library with a ▶ Play now button pointing at your Play URL, a live leaderboard page, and your item store.

See it working — two open examples

Both demo games in this portal are built exactly this way, in ~250 lines of TypeScript each, with no backend of their own:

  • 🪐 Orbital Clicker — free game: auth, signed scores, live leaderboard, wallet (examples/orbital-clicker in the platform repo).
  • 🚀 Nebula Racer — premium game: everything above plus the ownsGame() / purchaseGame() paywall (examples/nebula-racer).

📨 Apply to publish on Game Portal

Ready to plug in? Send us your registration JSON (step 6 of the prompt above, or step 2's shape), any supporting documents, and a short pitch. We review every application and reply with your game credentials and next steps.

Sign in or create an account to submit an application — your submission is tied to your platform account so we can follow up and issue your game credentials.