Uniplay

Game manifest#

A game describes itself in a unihub.manifest.json at the root of its folder, and the Hub reads nothing else about it: change the manifest and submit a new version to update its listing. package.json stays only to build the game. The JSON Schema unihub.manifest.v1.json holds every rule below; point $schema at it and editors autocomplete and explain each field.

unihub.manifest.json#

{
  "$schema": "https://play.unikia.es/schema/unihub.manifest.v1.json",
  "manifestVersion": 1,
  "id": "heated-heist",
  "title": "Heated Heist",
  "version": "0.1.0",
  "developers": ["cebun"],
  "description": "Rob fictional estates while every sound brings more armed security.",
  "tagline": "Get in. Get rich. Get out.",
  "details": "Steal jewellery and money from rich people's fictional mansions...",
  "genre": "Shooter",
  "tags": ["Top-down shooter", "Heist", "Stealth", "Co-op", "Online co-op", "Arcade", "2D"],
  "players": { "min": 1, "max": 2 },
  "platforms": ["desktop", "mobile"],
  "languages": ["en", "es"],
  "color": "#f382cd",
  "cover": "public/assets/menu-bg.webp",
  "squareCover": "public/assets/square.webp",
  "badge": "public/assets/badge.webp",
  "path": "heist-game",
  "achievements": "public/achievements.json",
  "changelog": "CHANGELOG.md",
  "sdk": "^1.4.0"
}
Field Required Meaning
manifestVersion yes Always 1.
id yes The stable game id (game id): a-z, 0-9 and -, at most 40 characters. Never change it once published.
title yes The game's name in the Hub, at most 40 characters.
version yes Semver, shown in Game details. It wins over package.json's; uniplay validate warns when they differ.
developers yes 1 to 10 Hub nicknames of the people who make the game, shown as its Developers in Game details. Only they can submit it.
description yes One-line pitch shown under the title, at most 160 characters.
tagline yes A short slogan on the artwork, at most 60 characters; the Hub shows it in capitals.
details no Longer text for Game details, at most 600 characters. Defaults to description.
genre yes The one main genre, at most 24 characters, e.g. "Shooter", "Roguelite". Everything else goes in tags.
tags no Up to 12 more descriptors, each at most 24 characters, most important first: sub-genres, modes, setting, style (e.g. "Top-down shooter", "Co-op", "Pixel art", "2D"). Shown as written.
players yes How many can play. A number is exactly that many: 1 for single player, 2 for a game that always needs two. A range { "min": 1, "max": 4 } is a game playable solo or with up to four (co-op or versus). Shown as "1 player", "2 players" or "1–4 players".
platforms no Devices the game is made for: one or more of "desktop" (keyboard, mouse or controller) and "mobile" (touch screens). Shown as icons in the Hub. Defaults to ["desktop"]; list "mobile" only when the game is playable with touch alone.
languages no Languages the game can be played in, as BCP 47 codes such as "en", "es" or "pt-BR", the original language first. Game details lists them by name. Defaults to ["en"].
playthroughs no Whether Game details offers Start a new game, which puts the player's saves aside as another playthrough they can switch back to. Set it to false for a game that keeps its own save slots (characters, save files), so players start over inside the game instead. Playthroughs already put aside stay listed. Defaults to true.
fullscreen no Whether the game asks to be played fullscreen, such as a first-person shooter. When it starts in Uniplay for desktop, the window goes fullscreen, unless the player turned that off in Settings → General, and comes back when they leave the game. On the site the game stays in the page. Defaults to false.
coopAcrossVersions no Whether buds on different versions of the game can play together. By default they can't: the game sees only the peers on its version, and the Hub offers the one behind an update before they join. Set it to true when versions stay compatible. Defaults to false.
color no Accent colour, #rrggbb.
cover one of the two Path to 16:9 key art, .webp, .png or .jpg (1600×900 .webp works best), for the game's page and the list view. The Hub shows it as is, without drawing the title over it, so include the logo in the art.
squareCover one of the two Path to 1:1 key art, .webp, .png or .jpg (1024×1024 .webp works best), for the grid view, with the logo in it too. A game needs cover, squareCover or both: without a square cover the grid crops the middle of the 16:9 one, and without a 16:9 cover the Hub fits the square one over a blurred copy of itself.
badge no Path to the game's platinum badge, .webp, .png or .jpg, 1:1 (a 256×256 .webp with a transparent background works best). Players see it greyed out on their profile and in Game details until they unlock every achievement. Without one, the Hub cuts a round badge from the cover.
entry no The built game's HTML file. Its folder is served at /<path>/. Defaults to dist/index.html.
achievements no Path to the game's achievements.json.
changelog no Path to the game's release notes, in the Keep a Changelog format. Translations sit next to it with a language tag before the extension (CHANGELOG.es.md, CHANGELOG.pt-BR.md); players see the one in their Hub language (or its language without the region), else this one.
sdk no The SDK range the game was built against, e.g. ^1.4.0.
path no URL folder the game's page is at, /<path>/. Defaults to the id. The game itself plays from its version's own address, /g/<id>/<version>/, so load its files by relative URLs (./assets/…), never /<path>/…. admin, api, assets, developers, g, healthz, library, licenses, policy, publisher, schema and uniplay are reserved, and the Hub may assign another one on review to avoid clashes.

Every path is relative to the manifest and stays inside the game's folder. The order of the game list and which games the Store features are the Hub's choice.

The game package#

A game reaches the Hub as one zip: the game's own folder once built, with only what the manifest names. npx -p @unikia/upe-cli uniplay pack writes it for you.

heated-heist.zip
├── unihub.manifest.json         required
├── package.json                 required
├── dist/                        required: the built game, entry at dist/index.html
├── public/assets/menu-bg.webp   the cover, at the path the manifest names
├── public/assets/square.webp    the square cover, likewise, if there is one
├── public/assets/badge.webp     the platinum badge, likewise, if there is one
├── public/achievements.json     optional, see achievements
└── CHANGELOG.md                 optional release notes (Keep a Changelog), CHANGELOG.es.md…