Read this page as markdown — for coding agents, or for anyone who prefers the source.
Publishing guide
How to get a game onto Bananai. Read
SUBMISSION-RULES.md first — this document covers the
mechanics, that one covers the requirements.
Current process is manual (phase 0–2). The developer portal in phase 4 replaces steps 5 and 6 with an upload form.
1. Create the folder
public/games/<id>/
├── bananai.json
├── index.html
├── css/style.css
└── js/
├── main.js bootstrap: mounts the game, wires the SDK
└── <id>.js game logic
The <id> is lowercase, hyphen-separated, and permanent — it appears in
URLs, cache keys and score records.
2. Load the SDK
<script src="/sdk/v0/bananai-sdk.js"></script>
Root-relative, with no origin in front of it. Your game is served from the
portal's own origin, so this always resolves;
https://bananai.games/sdk/v0/bananai-sdk.js is a cross-origin request everywhere
except live production and is rejected by the checks. You may also vendor a copy
into your folder — ARCADE-SDK.md covers the trade-off.
await Bananai.init({ gameId: '<id>' });
Bananai.loadingFinished();
Bananai.gameplayStart();
// ...
Bananai.gameOver({ score, level, durationMs });
window.addEventListener('bananai:restart', () => resetGame());
Full reference: ARCADE-SDK.md.
3. Technical requirements
- Responsive. Fill the container, do not assume fixed dimensions.
In p5:
createCanvas(el.clientWidth, el.clientHeight)pluswindowResized(). - Touch.
touchStarted/touchMoved/touchEndedmust returnfalse, otherwise the page scrolls under the player's finger. - Self-contained. Libraries and assets live inside the game folder. No external requests.
- Audio silent until interaction. Browsers enforce this anyway.
4. Thumbnail
public/games/<id>/assets/thumb.png (or .svg, or .webp), square, 400×400,
declared in bananai.json.
It lives inside the game folder, not in the portal's shared /assets/. The
submission is then one self-contained directory that can be added or removed as
a unit — no orphaned image left behind when a game is withdrawn.
It has to read clearly at roughly 180px, which is the actual card size in the grid. Check it at that size, not at full resolution.
5. Register in the catalogue
In public/index.html, add to the games array:
{
id: "<id>",
title: "Readable Title",
category: "arcade", // arcade | puzzle | azione
thumb: "games/<id>/assets/thumb.png",
path: "games/<id>/index.html",
featured: false,
comingSoon: false
}
From phase 1 this moves to public/games.json.
If the category is new, add the matching .chip button to the category bar.
6. Update supporting files
- Add the game URL to
public/sitemap.xml - Add an entry to
docs/CHANGELOG.md
The service worker cache version updates itself at build time — nothing to bump.
Pre-deploy checklist
- Works standalone at
/games/<id>/index.html - Works inside the shell modal
- Works on mobile: touch, both orientations, 320px width
- SDK lifecycle calls present and correctly sequenced
-
bananai:restartrestarts without a page reload - Thumbnail visible and legible in the grid
- Search and category filter find the game
-
comingSoonisfalseonly if the folder actually exists - No console errors
- No network requests to external origins
-
CHANGELOG.mdupdated
Then:
fly deploy