PlayDrop logoPlayDrop Studio
CreatePlayTradeEarnLearnConnectorsAssetsCommunitySupport
PlayDrop logoPlayDrop Studio
CreatePlayTradeEarnLearnConnectorsAssetsCommunitySupport
Sign in
Packaging and .play
Documentation

Start here

OverviewYour first gamePlayDrop gamesFAQ

Create with Cloud

Cloud creationPlans & generations

Connect your AI app

All connectorsClaudeChatGPTClaude CodeCodexCursorGeminiAntigravityGrok BuildGrok BotGrok ChatLovableReplit

Publish and share

Publish from your AI appSimple HTML gamesPackaging and .playPublish & importGame filesVisibility and reachListing art and videoGenres and tagsLocalizationInstant games

Game experience

Loading, pause and audioFull screen and safe areasCloud savesLocal parties and controllers

Play together

Sharing, friends and invitesLeaderboardsAchievementsOnline parties and voiceRealtime game servers

Earn

MonetizationCredits & rewards

Assets

Game assetsAI asset generationCustom formats and player creations

Reference

Client SDKServer SDKcatalogue.jsonErrors and recoveryTroubleshooting
DocumentationPackaging and .play
Publish and share

Package a PlayDrop game with catalogue.json and .play

Lay out a built game folder, ZIP or .play with catalogue.json at its root, declare listing media and servers, and upload it with prepare_catalogue_upload.

A package is the built output of a game plus a catalogue.json that describes it. It is the path for every PlayDrop feature: several files, the SDK, listing images and videos, leaderboards, achievements, assets and a hosted server. Upload it from your AI app as a folder, a ZIP or a .play file.

Lay out the folder

Put catalogue.json at the root, next to the built game. Paths in the catalogue are relative to it.

text
catalogue.json
index.html
assets/sprites.png
assets/music.mp3
listing/icon.png
listing/hero-landscape.png
listing/hero-portrait.png
listing/screenshots/landscape-1.png
listing/videos/portrait-1.mp4
achievements/first-win.png
server/index.mjs

A .play file is this folder zipped with catalogue.json at the archive root, not inside a wrapper folder, and renamed .play. It contains built files only: no node_modules, source maps you do not want public, or .env files. Keep the source project with your human; PlayDrop cannot return it.

Write catalogue.json

json
{
  "apps": [{
    "name": "moon-jump",
    "displayName": "Moon Jump",
    "subtitle": "Lunar platform hopping against the clock",
    "description": "Jump between lunar platforms, collect oxygen and reach the flag.",
    "controls": "Tap or press Space to jump. Swipe or use arrows to steer.",
    "file": "index.html",
    "version": "1.0.0",
    "visibility": "PRIVATE",
    "authMode": "OPTIONAL",
    "tags": ["game-genre/casual", "game-genre/platformer"],
    "types": ["solo"],
    "controller": { "support": "optional", "type": "simpler" },
    "surfaceTargets": { "desktop": true, "mobileLandscape": true, "mobilePortrait": true },
    "primarySurface": "MOBILE_PORTRAIT",
    "sourceLocale": "en",
    "listing": {
      "icon": "listing/icon.png",
      "heroLandscape": "listing/hero-landscape.png",
      "heroPortrait": "listing/hero-portrait.png",
      "screenshotsLandscape": ["listing/screenshots/landscape-1.png"],
      "videosPortrait": ["listing/videos/portrait-1.mp4"]
    },
    "leaderboards": [{ "key": "best-time", "displayName": "Best time", "description": "Fastest run to the flag",
      "scoreType": "TIME_MS", "sort": "ASC" }],
    "achievements": [{ "key": "first-win", "displayName": "First flag", "description": "Reach the flag once",
      "kind": "STANDARD", "icon": "achievements/first-win.png" }],
    "server": { "entry": "server/index.mjs", "rooms": ["game"] }
  }]
}
  • file is the exact path of the page that starts the game. Without it the entry defaults to <name>.html, not index.html.
  • version is a new semantic version for every upload of the same game.
  • surfaceTargets lists the surfaces you have tested; primarySurface is the one the game is designed for.
  • Listing media, achievement icons and the server entry are claimed by the catalogue: a file under listing/ that no field references is not listing media, and files no app claims are refused before anything publishes.
  • server.entry points at one built ES module bundle; see realtime game servers.

Every field and its limits are in the catalogue.json reference. There is no catalogue version field to set.

Upload a folder

Send prepare_catalogue_upload with a new requestId, expectedCurrentVersion (null for a new game), the complete catalogue object and one descriptor per file. Small text files may be inline text. Every other file is a signed upload: compute its size, SHA-256 (64 lowercase hex characters) and base64 MD5 locally from the exact bytes. This request for a two-file game is complete; replace the two digest placeholders on the icon with the icon's real values.

json
{
  "requestId": "moon-jump-1.0.0",
  "expectedCurrentVersion": { "moon-jump": null },
  "catalogue": {
    "apps": [{
      "name": "moon-jump",
      "displayName": "Moon Jump",
      "file": "index.html",
      "version": "1.0.0",
      "visibility": "PRIVATE",
      "authMode": "OPTIONAL",
      "tags": ["game-genre/casual"],
      "types": ["solo"],
      "controller": { "support": "off" },
      "surfaceTargets": { "desktop": true, "mobileLandscape": false, "mobilePortrait": true },
      "listing": { "icon": "listing/icon.png" }
    }]
  },
  "files": [
    { "path": "index.html",
      "text": "<!doctype html><html><head><meta charset=\"utf-8\"><title>Moon Jump</title></head><body><canvas id=\"game\"></canvas><script>/* built game */</script></body></html>" },
    { "path": "listing/icon.png", "contentType": "image/png", "sizeBytes": 50211,
      "sha256": "REPLACE_WITH_ICON_SHA256_HEX", "md5Base64": "REPLACE_WITH_ICON_MD5_BASE64" }
  ]
}

The response lists an upload URL and headers for listing/icon.png. PUT the icon's exact bytes there with every returned header, then call complete_catalogue_upload with the same requestId. The receipt's url opens the private version.

Upload a ZIP or .play

  • Agents with a file system unpack the archive locally and upload it as a folder, as above.
  • ChatGPT passes the archive it resolved from the conversation as archive, with its real download_url and file_id, and no catalogue or files. The archive may be up to 20 MiB compressed.

Archives must be ordinary ZIP files: no encryption, multiple volumes, ZIP64, symlinks, duplicate paths, absolute paths or ... Empty files and nested catalogue.json files are refused.

Limits

512 files or archive entries (including catalogue.json and directories), 50 MiB per file, 200 MiB unpacked and 1 MiB of catalogue JSON. A hosted server bundle is at most 2 MiB.

Update a package

Read list_games, keep each app's name, raise its version and set expectedCurrentVersion to the current published version. Send the full snapshot: every file and field the new version should have. Unchanged files of a retained version can be sent with reuse: { gameId, version, path } instead of their bytes. Leaderboard and achievement keys cannot be removed or change type; retire one with "status": "RETIRED".

Assets the connector cannot upload yet

PlayDrop runs executable 3D models (MODEL_3D assets with the procedural subcategory or CUSTOM format) in its own tools, but the connector refuses them because the API cannot validate their code. Bake them to a supported format, or reference an asset already published on PlayDrop. Baked procedural images and spritesheets are accepted. See game assets.

Related guides

  • catalogue.jsonThe catalogue.json fields PlayDrop games use: identity, listing, play modes, surfaces, sign-in, Instant, preloading, media, translations, scores and servers.
  • Publish from your AI appHow AI agents publish to PlayDrop through MCP: the simple and package paths, private testing, publish_game_version, updates, limits and recovery.
  • Listing art and videoThe listing images and videos a PlayDrop game can have, their paths, formats and orientations, and how to make art that works in feeds, search and previews.
  • Realtime game serversRun a hosted Colyseus 0.17 server with a MongoDB database for your game, connect from the browser with the SDK, test with two players and know the limits.
PreviousPublish a simple HTML game from your AI appNextPublish a game, upload files, or register a URL
View Markdown
EnglishFrançaisDeutsch日本語한국어EspañolPortuguês (Brasil)Bahasa Indonesia繁體中文简体中文ItalianoPolskiNederlandsSvenskaNorsk bokmålSuomiTürkçeไทยTiếng Việtالعربية

On this page

Lay out the folderWrite catalogue.jsonUpload a folderUpload a ZIP or .playLimitsUpdate a packageAssets the connector cannot upload yet
View Markdown