Instant Games

Example Game Use Cases

Updated: Mar 25, 2026
Copy for LLM
This page walks through practical examples of using overlay views in Zero Permissions games. Each example shows the XML markup, the JavaScript integration code, and the data structures involved. Use these as starting points for your own implementation.
For a complete reference of available XML components, see Overlay View Components. To experiment interactively, try the Overlay Preview Tool.
Unity developers: The JavaScript examples below show the underlying SDK calls. The Unity Plugin provides equivalent C# APIs — see its overlay views section for Unity-specific usage.
A repository of runnable sample code is available on GitHub: fbsamples/fbinstant-nezp-samples.

Displaying the Current Player’s Profile

The simplest overlay view shows the current player’s name and photo. This is useful for profile cards, game headers, and HUD elements.
XML (overlays/profile_card.xml):
<View className="profileCard">
  <Image src="{{FBInstant.player.photo}}" className="avatar" />
  <Text content="{{FBInstant.player.name}}" className="playerName" />
</View>
JavaScript:
var container = document.getElementById('profileCardContainer');

FBInstant.overlayViews.createOverlayViewAsync(
  'overlays/profile_card.xml',
  container,
  'width: 200px; height: 60px; border: none;',
  'overlays/styles.css'
).then(function(overlay) {
  overlay.showAsync();
});
The {{FBInstant.player.photo}} and {{FBInstant.player.name}} expressions are resolved by Meta at render time. Your game code never sees the actual name or photo URL.

Rendering a Friend List

Friend lists are one of the most common overlay view use cases. There are three architectural approaches, each with different tradeoffs.

Approach 1: Single Overlay with a For Loop

Render the entire friend list inside one overlay iframe. This is the simplest approach and works well for static friend lists.
XML (overlays/friend_list.xml):
<View className="friendList">
  <For source="{{FBInstant.player.connectedPlayers}}" itemName="friend"
       sortKey="name" order="ASC" limit="20">
    <View className="friendRow" onTapEvent="selectFriend_{{friend.id}}">
      <Image src="{{friend.photo}}" className="avatar" />
      <Text content="{{friend.name}}" className="friendName" />
    </View>
  </For>
</View>
JavaScript:
var container = document.getElementById('friendListContainer');

FBInstant.overlayViews.createOverlayViewAsync(
  'overlays/friend_list.xml',
  container,
  'width: 100%; height: 400px; border: none;',
  'overlays/styles.css'
).then(function(overlay) {
  overlay.showAsync();
});

// Handle taps on individual friends
FBInstant.overlayViews.setCustomEventHandler(function(eventStr, overlayID) {
  if (eventStr.startsWith('selectFriend_')) {
    var playerID = eventStr.replace('selectFriend_', '');
    handleFriendSelected(playerID);
  }
});
Tradeoffs: Simple to implement. The entire list renders as one iframe, so layout is consistent. However, you have less control over individual row behavior from your game code.
The following diagram shows how to render everything in a single overlay view frame:
Rendering everything in a single overlay view frame

Approach 2: Individual Overlay per Friend

Create a separate overlay iframe for each friend row. This gives your game full control over row layout and behavior, since each overlay is embedded within your own HTML structure.
XML (overlays/friend_row.xml):
<View className="friendRow">
  <Image src="{{FBInstant.players[{{playerID}}].photo}}" className="avatar" />
  <Text content="{{FBInstant.players[{{playerID}}].name}}" className="friendName" />
</View>
JavaScript:
FBInstant.player.getConnectedPlayersAsync().then(function(players) {
  players.forEach(function(player) {
    var rowContainer = document.createElement('div');
    rowContainer.className = 'friendRowWrapper';
    document.getElementById('friendList').appendChild(rowContainer);

    FBInstant.overlayViews.createOverlayViewAsync(
      'overlays/friend_row.xml',
      rowContainer,
      'width: 100%; height: 50px; border: none;',
      'overlays/styles.css',
      { playerID: player.getID() }
    ).then(function(overlay) {
      overlay.showAsync();
    });

    // Add your own game buttons alongside the overlay
    var challengeBtn = document.createElement('button');
    challengeBtn.textContent = 'Challenge';
    challengeBtn.onclick = function() { challengePlayer(player.getID()); };
    rowContainer.appendChild(challengeBtn);
  });
});
Tradeoffs: Maximum flexibility — you can mix overlay iframes with your own UI elements. However, creating many iframes can impact performance, so this approach works best with smaller friend lists (under ~20 rows).
The following diagram shows how to render each row in its own overlay view iframe:
Rendering each row in its own overlay view iframe

Approach 3: Single Overlay with Custom Player List

Pass a custom list of player IDs as initialData and iterate over them. This approach is useful when you want to display a filtered or custom-ordered list rather than all connected players.
XML (overlays/custom_friend_list.xml):
<View className="friendList">
  <For source="{{players}}" itemName="entry">
    <View className="friendRow" onTapEvent="SendCoins_{{entry.playerID}}">
      <Image src="{{FBInstant.players[{{entry.playerID}}].photo}}" className="avatar" />
      <Text content="{{FBInstant.players[{{entry.playerID}}].name}}" className="friendName" />
      <Button content="Send Coins" className="actionBtn" />
    </View>
  </For>
</View>
JavaScript:
// Get connected players, then filter or reorder as needed
FBInstant.player.getConnectedPlayersAsync().then(function(connectedPlayers) {
  var playerList = connectedPlayers.slice(0, 10).map(function(p) {
    return { playerID: p.getID() };
  });

  var container = document.getElementById('friendListContainer');

  FBInstant.overlayViews.createOverlayViewAsync(
    'overlays/custom_friend_list.xml',
    container,
    'width: 100%; height: 400px; border: none;',
    'overlays/styles.css',
    { players: playerList }
  ).then(function(overlay) {
    overlay.showAsync();
  });
});

FBInstant.overlayViews.setCustomEventHandler(function(eventStr, overlayID) {
  if (eventStr.startsWith('SendCoins_')) {
    var playerID = eventStr.replace('SendCoins_', '');
    sendCoinsToPlayer(playerID);
  }
});
The following diagram shows how to render friend info in separate overlay view frames:
Rendering friend info in separate overlay view frames

Building a Custom Leaderboard

Since the built-in Global Leaderboards API is deprecated for Zero Permissions games, build leaderboards using your own backend and render player profiles with overlay views. See Global Leaderboards for the full guide.
XML (overlays/leaderboard.xml):
<View className="leaderboard">
  <For source="{{entries}}" itemName="entry">
    <View className="leaderboardRow">
      <Text content="#{{entry.rank}}" className="rank" />
      <Image src="{{FBInstant.players[{{entry.playerID}}].photo}}" className="avatar" />
      <Text content="{{FBInstant.players[{{entry.playerID}}].name}}" className="playerName" />
      <Text content="{{entry.score}}" className="score" />
    </View>
  </For>
</View>
JavaScript:
// Fetch leaderboard from your own backend
fetch('https://yourserver.com/api/leaderboard/top?limit=10')
  .then(function(res) { return res.json(); })
  .then(function(data) {
    // data.entries = [{ rank: 1, playerID: '123', score: 5000 }, ...]
    var container = document.getElementById('leaderboardContainer');

    return FBInstant.overlayViews.createOverlayViewAsync(
      'overlays/leaderboard.xml',
      container,
      'width: 100%; height: 500px; border: none;',
      'overlays/styles.css',
      { entries: data.entries }
    );
  })
  .then(function(overlay) {
    overlay.showAsync();
  });

Sorting by Dynamic Keys

When your score data is stored in a separate object keyed by player ID, use nested template expressions in the sortKey attribute to sort dynamically:
XML:
<View>
  <For source="{{players}}" itemName="player"
       sortKey="{{scores[{{player.id}}]}}" order="DESC">
    <View className="row">
      <Text content="{{player.name}}" />
      <Text content="Score: {{scores[{{player.id}}]}}" />
    </View>
  </For>
</View>
Data structure (passed as initialData):
{
  "players": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" },
    { "id": 3, "name": "Carol" }
  ],
  "scores": { "1": 101, "2": 222, "3": 313 }
}
This renders Carol first (313), then Bob (222), then Alice (101).

Conditional Rendering

Use If, ElseIf, and Else to display different content based on player data or game state:
XML (overlays/game_over.xml):
<View className="gameOver">
  <Image src="{{FBInstant.player.photo}}" className="avatar" />
  <Text content="{{FBInstant.player.name}}" className="playerName" />

  <If>
    <Condition lhs="{{score}}" operator="GREATER_THAN" rhs="{{highScore}}" />
    <View className="newRecord">
      <Text content="New high score: {{score}}!" className="celebration" />
    </View>
    <Else>
      <View>
        <Text content="Score: {{score}}" />
        <Text content="Best: {{highScore}}" className="muted" />
      </View>
    </Else>
  </If>
</View>
JavaScript:
var container = document.getElementById('gameOverContainer');

FBInstant.overlayViews.createOverlayViewAsync(
  'overlays/game_over.xml',
  container,
  'width: 300px; height: 200px; border: none;',
  'overlays/styles.css',
  { score: currentScore, highScore: previousHighScore }
).then(function(overlay) {
  overlay.showAsync();
});

Context Actions from Overlays

You can trigger context switches directly from overlay view buttons, without going through your game’s JavaScript:
<View className="friendList">
  <For source="{{FBInstant.player.connectedPlayers}}" itemName="friend">
    <View className="friendRow">
      <Image src="{{friend.photo}}" className="avatar" />
      <Text content="{{friend.name}}" className="friendName" />
      <Button content="Play" action="{{FBInstant.action.contextCreate({{friend.id}})}}"
              className="playBtn" />
    </View>
  </For>
</View>
When a player taps “Play”, the platform creates a context with that friend and switches to it. To handle the context change in your game code, register a callback:
FBInstant.onContextChange(
  function(contextID) {
    console.log('Switched to context:', contextID);
    // Reload game state for the new context
  },
  function(error) {
    console.log('Context switch failed:', error);
  }
);

Next Steps