# Publishing guide How to get a game onto Bananai. Read [`SUBMISSION-RULES.md`](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// ├── bananai.json ├── index.html ├── css/style.css └── js/ ├── main.js bootstrap: mounts the game, wires the SDK └── .js game logic ``` The `` is lowercase, hyphen-separated, and **permanent** — it appears in URLs, cache keys and score records. ## 2. Load the SDK ```html ``` 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`](arcade-sdk.md) covers the trade-off. ```js await Bananai.init({ gameId: '' }); Bananai.loadingFinished(); Bananai.gameplayStart(); // ... Bananai.gameOver({ score, level, durationMs }); window.addEventListener('bananai:restart', () => resetGame()); ``` Full reference: [`ARCADE-SDK.md`](arcade-sdk.md). ## 3. Technical requirements - **Responsive.** Fill the container, do not assume fixed dimensions. In p5: `createCanvas(el.clientWidth, el.clientHeight)` plus `windowResized()`. - **Touch.** `touchStarted` / `touchMoved` / `touchEnded` must return `false`, 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//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: ```js { id: "", title: "Readable Title", category: "arcade", // arcade | puzzle | azione thumb: "games//assets/thumb.png", path: "games//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//index.html` - [ ] Works inside the shell modal - [ ] Works on mobile: touch, both orientations, 320px width - [ ] SDK lifecycle calls present and correctly sequenced - [ ] `bananai:restart` restarts without a page reload - [ ] Thumbnail visible and legible in the grid - [ ] Search and category filter find the game - [ ] `comingSoon` is `false` **only if** the folder actually exists - [ ] No console errors - [ ] No network requests to external origins - [ ] `CHANGELOG.md` updated Then: ```bash fly deploy ```