These docs are a work in progress. Some pages may be incomplete or out of date while we continue updating them.

Meet Platform

Technical reference for the Meet platform. This covers the APIs and integration points for developers building custom content or integrations.


Overview

Meet is a timeline-based platform for team-focused, competitive learning experiences. It features:

  • Real-time scoring — Points are tracked and persisted to a database
  • Team registration — Participants create teams with names and avatars
  • Live leaderboard — Scores update in real-time across all participants
  • Admin controls — Manage teams, view data, and control the experience

PostMessage API

Games and screens communicate with the Meet platform using the PostMessage API. This handles scoring, progression, and data exchange.

Sending messages

From within an iframe (game or screen), send messages to Meet:

window.parent.postMessage({
  message: "messageType",
  // ... additional data
}, "*")

Message types

updateScore

Updates the team's score.

window.parent.postMessage({
  message: "updateScore",
  value: 50,              // Points to add (can be negative)
  choice: "option_a",     // Optional: identifier for the choice
  type: "NORMAL"          // "NORMAL" or "BONUS"
}, "*")

Payload sent to backend:

{
  "points": 50,
  "choice": "option_a",
  "type": "NORMAL",
  "level": "current_level_id",
  "activity": "activity_name",
  "timeline": "current_timeline_id"
}

finish / finished

Marks the current activity as completed.

window.parent.postMessage({ message: "finish" }, "*")

restartLevel

Resets all points for the current level.

window.parent.postMessage({ message: "restartLevel" }, "*")

restartTimeline

Resets all points for the entire timeline.

window.parent.postMessage({ message: "restartTimeline" }, "*")

Requesting data

Request data from Meet and receive a response message.

getTeamData

window.parent.postMessage({ message: "getTeamData" }, "*")

Response:

{
  message: "teamData",
  data: {
    avatarId: "avatar-123",
    avatarImage: "/avatars/dragon.png",
    avatarName: "Dragon",
    teamInitials: "DRG",
    teamName: "Dragon Warriors",
    score: 450,
    points: [/* point records */]
  }
}

getLevelData

window.parent.postMessage({ message: "getLevelData" }, "*")

Response:

{
  message: "levelData",
  data: {
    levelId: "level-2",
    timelineId: "timeline-1",
    totalPoints: 150,
    normalPoints: 100,
    bonusPoints: 50
  }
}

getTimelineData

window.parent.postMessage({ message: "getTimelineData" }, "*")

Response:

{
  message: "timelineData",
  data: {
    timelineId: "timeline-1",
    totalPoints: 450,
    normalPoints: 350,
    bonusPoints: 100
  }
}

Listening for responses

window.addEventListener("message", (event) => {
  const data = event.data
  
  switch (data.message) {
    case "teamData":
      console.log("Team:", data.data.teamName)
      break
    case "levelData":
      console.log("Level points:", data.data.totalPoints)
      break
    case "timelineData":
      console.log("Timeline points:", data.data.totalPoints)
      break
  }
})

Teams API

REST API for accessing team data. Requires admin authentication.

Get all teams

GET /api/admin-api/teams

Returns all teams sorted by score (highest first).

Query parameters:

ParameterTypeDescription
groupstringFilter by avatar name (case-insensitive partial match)

Example:

// All teams
const response = await fetch("/api/admin-api/teams")

// Filter by avatar name
const response = await fetch("/api/admin-api/teams?group=dragon")

Response:

{
  "teams": [
    {
      "id": "team-123",
      "teamName": "Dragon Warriors",
      "teamInitials": "DRG",
      "avatarId": "avatar-1",
      "avatarImage": "/avatars/dragon.png",
      "avatarName": "Dragon",
      "score": 450,
      "points": [
        {
          "id": "point-1",
          "points": 50,
          "level": "level-2",
          "timeline": "timeline-1",
          "activity": "quiz-1",
          "teamId": "team-123",
          "choice": "option_a",
          "createdAt": "2024-01-15T10:30:00Z",
          "type": "NORMAL"
        }
      ]
    }
  ]
}

Get teams by level

GET /api/admin-api/teams/level?level=level-2

Returns team data for a specific level.

Query parameters:

ParameterTypeRequiredDescription
levelstringYesThe level ID to filter by

Custom admin screens

Add custom screens to the admin dashboard for specialised functionality.

Configuration

Add to your project config:

{
  "admin": [
    {
      "path": "/admin/custom-leaderboard/index.html",
      "name": "Custom Leaderboard",
      "id": "custom-leaderboard",
      "param": "leaderboard"
    }
  ]
}

Properties

PropertyTypeDescription
pathstringFile path to the custom screen HTML
namestringDisplay name in the admin menu
idstringUnique identifier
paramstringURL parameter for routing

Access

Custom screens are accessible at /admin/custom/:param

Example screen

<!DOCTYPE html>
<html>
<head>
  <title>Custom Leaderboard</title>
</head>
<body>
  <div id="leaderboard"></div>
  
  <script>
    async function loadTeams() {
      const response = await fetch("/api/admin-api/teams")
      const data = await response.json()
      
      document.getElementById("leaderboard").innerHTML = data.teams
        .map((team, i) => `
          <div class="team">
            <span>${i + 1}.</span>
            <span>${team.teamName}</span>
            <span>${team.score} pts</span>
          </div>
        `)
        .join("")
    }
    
    loadTeams()
  </script>
</body>
</html>

Admin routes

Built-in admin routes:

RouteDescription
/avt-adminMain admin dashboard
/avt-admin/leaderboardLive leaderboard view
/avt-admin/signupTeam registration management
/avt-admin/usersUser management
/avt-admin/custom/:idCustom admin screens

Was this page helpful?