Gamero

Creator guide

Set your project up once and every npm run build gives you a gamero.zip with everything the game page needs: the game, its details, cover, screenshots and texts. Upload it, check the preview, publish.

Want a scoreboard or achievements? Add one script tag and your game gets leaderboards and awards, shown right next to it on the game page.

Submit to “Farm or Farming”

1Let your AI assistant set it up

Using Claude Code, Cursor, Copilot or a chat assistant? Paste this prompt into it, inside your game project. It describes everything below: the build, screens/, game.json with every allowed value and this week's challenge rules, the ZIP script, and how to add leaderboards and awards if your game has a score or achievements.

You are helping me publish this web game on Gamero (a weekly game-jam site). Set up the project so that `npm run build` produces a ready-to-upload `gamero.zip` in the project root. When I upload that ZIP, Gamero unpacks the game AND reads a `screens/` folder that fills in the WHOLE game page: title, tagline, genre, controls, cover, screenshots, description, how-to-play. Naming must follow the rules below exactly; anything unexpected makes the upload fail.

This week's challenge is "Farm or Farming". It requires "theme": "Farm". Its requirements:
- Focus on graphic
Use "challengeNotes" in game.json to explain how the game fits.

## 1. The build
- Keep the existing build (Vite, webpack, Phaser template, plain HTML…). Its output folder (e.g. `dist/`) must contain `index.html` at its root.
- All asset paths must be RELATIVE (for Vite set `base: "./"`). The game is served from a sub-path inside a sandboxed iframe: no cookies, no popups, no access to the parent page, no server-side code.
- Total size: ZIP max 100 MB, unpacked max 200 MB, max 3000 files. No .exe/.dll/.sh/.php/.py/.jar or other executable/server files.
- It must work on phones: touch input, resize-aware canvas, no hover-only controls.

## 2. The screens/ folder
Create a `screens/` folder in the PROJECT ROOT (not in public/ or the build output) and commit it. No subfolders. Images: PNG, JPG, WebP or GIF, max 5 MB each. Allowed files:

| File | Used for | Rules |
|---|---|---|
| `game.json` | All game details (see section 3) | Required for the first upload. |
| `cover.png` | Card image + page header | 16:9, at least 630×354 (ideally 1280×720). Center-cropped to 16:9. No important content near the edges. |
| `screenshot-1.png` … `screenshot-8.png` | Screenshot gallery | Ordered by the number. Longest side 320–1920 px. Optional caption after the number in lowercase-kebab-case: `screenshot-2-boss-fight.png` → caption "Boss fight". |
| `description.md` | "About" section | Markdown, max 10 000 characters. What the game is, what makes it fun. Don't repeat the title as a heading. |
| `description-1.png`, `description-2.png` … | Pictures inside the description | Max 10. Reference them as `![alt text](description-1.png)`; any picture you don't reference is appended at the end. |
| `how-to-play.md` | "How to play" section | Markdown, max 3 000 characters. Goal + controls for EVERY supported input (touch, keyboard, mouse, gamepad). |
| `how-to-play-1.png` … | Pictures inside the instructions | Max 10, e.g. a controls diagram. Reference as `![Controls](how-to-play-1.png)`. |

Markdown: no raw HTML, no external images (they are not shown; only screens/ pictures are), links are fine. Keep sentences short; players skim.

Images: use REAL gameplay captures, not mock-ups. If you can run the game, use Playwright (or a similar headless browser) against the built game to capture the cover and 3–5 screenshots of different, interesting moments at 1280×720 (plus a portrait 720×1280 shot if the game supports portrait). If you can't capture them, tell me exactly which shots to take; don't invent placeholder art.

## 3. screens/game.json
A JSON object. Every property is optional except "title" and "tagline" on the first upload; a property you leave out keeps its current value on the site. Unknown properties are rejected (so don't put the description in here; it goes in description.md).

- "title": string, max 100.
- "tagline": string, max 120, one punchy line shown on the game card.
- "theme": one of "Abstract / Minimal", "Alien invasion", "Ancient Egypt", "Ancient Rome / Greece", "Animals", "Arabian Nights", "Arctic", "Autumn", "Aviation", "Aztec / Maya", "Biopunk", "Cars / Racing", "Castle", "Cave / Underground", "Christmas", "Circus / Carnival", "City / Urban", "Claymation", "Comic book", "Countryside", "Cute / Cozy", "Cyberpunk", "Desert", "Detective / Mystery", "Dieselpunk", "Dinosaurs", "Dragons", "Dreams / Surreal", "Dungeon", "Easter", "Factory / Automation", "Fairy tale", "Fantasy", "Farm", "Feudal Japan", "Food / Candy", "Forest", "Garden", "Ghosts / Haunted", "Halloween", "Hand-drawn", "Heist / Crime", "Horror", "Hospital", "Industrial", "Insects / Bugs", "Island / Tropical", "Jungle", "Kitchen / Cooking", "Low poly", "Magic / Wizards", "Medieval", "Microscopic / Cells", "Military / War", "Mining", "Monochrome", "Monsters", "Music / Concert", "Mythology", "Nature", "Neon / Synthwave", "Ninja / Samurai", "Noir", "Ocean / Sea life", "Office", "Paper / Cardboard", "Pirates", "Pixel art", "Post-apocalyptic", "Prehistoric", "Retro / 8-bit", "Robots", "School", "Sci-fi", "Sky / Clouds", "Solarpunk", "Space", "Sports", "Spring", "Spy / Espionage", "Steampunk", "Suburbia", "Summer", "Superheroes", "Time travel", "Toys", "Trains", "Underwater", "Valentine's", "Vampires", "Victorian", "Vikings", "Volcano", "Voxel", "Watercolor", "Weather / Storms", "Western", "Winter / Holidays", "Witches", "Zombies".
- "category" and "subCategory": pick the category, then optionally one of its sub-categories:
- "Action": "Platform", "Shooter", "First-person shooter", "Third-person shooter", "Shoot 'em up", "Light gun", "Hero shooter", "Arena shooter", "Fighting", "Beat 'em up", "Hack and slash", "Stealth", "Survival", "Rhythm", "Battle royale"
- "Action-adventure": "Survival horror", "Metroidvania", "Soulslike", "Immersive sim"
- "Adventure": "Text adventure", "Graphic adventure", "Point-and-click", "Visual novel", "Interactive movie", "Real-time 3D adventure", "Walking simulator"
- "Puzzle": "Logic", "Tile-matching", "Physics", "Programming", "Hidden object", "Escape room", "Breakout clone", "Trivia"
- "Role-playing": "Action RPG", "MMORPG", "Roguelike", "Roguelite", "Tactical RPG", "Sandbox RPG", "First-person party-based RPG", "Monster tamer", "Dungeon crawler"
- "Simulation": "Construction and management", "City-building", "Business / Tycoon", "Colony management", "Life simulation", "Social simulation", "Pet / Virtual pet", "Dating sim", "Vehicle simulation", "Flight simulator", "Space flight", "Farming"
- "Strategy": "4X", "Artillery", "Auto battler", "MOBA", "Real-time strategy", "Real-time tactics", "Tower defense", "Turn-based strategy", "Turn-based tactics", "Wargame", "Grand strategy", "Deck-building / Card"
- "Sports": "Racing", "Team sports", "Individual sports", "Competitive / Esports", "Sports-based fighting"
- "Massively multiplayer": "MMO", "MMORPG", "MMOFPS"
- "Other": "Casual", "Idle / Incremental", "Party", "Sandbox", "Survival", "Horror", "Educational", "Music", "Board game", "Card game", "Hyper-casual", "Endless runner", "Typing", "Exergame"
- "dimension": one of "2D", "2.5D", "3D".
- "tags": up to 10 short lowercase tags, e.g. ["pixel-art", "roguelike"].
- "inputMethods": the inputs the game ACTUALLY supports, any of "Touch", "Keyboard", "Mouse", "Gamepad".
- "orientation": "Any", "Portrait" or "Landscape".
- "contentWarnings": any that apply of "FlashingLights", "Violence", "Gore", "LoudAudio", "Horror"; [] if none.
- "engine": e.g. "Phaser 3", "Godot 4", "Three.js", "Plain JavaScript". Max 100.
- "videoUrl": optional YouTube link. "sourceCodeUrl": optional repo link. Both http(s) URLs.
- "challengeNotes": how the game fits the weekly challenge, markdown, max 3000.
- "credits": team, music, fonts, asset licenses, markdown, max 3000.
- "aiDisclosure": honestly state what AI was used for (code, art, audio, text), max 1000.
- "awards": optional achievements, the FULL list (awards left out are deleted). Each: "key" (lowercase letters, digits, - and _, max 32, unique), "title" (max 60), "description" (max 200), "icon" (one emoji), "secret" (true hides it until unlocked). Max 50.

Example:
{
  "title": "Neon Drift",
  "tagline": "Race through a city that rebuilds itself every lap",
  "theme": "Neon / Synthwave",
  "category": "Sports",
  "subCategory": "Racing",
  "dimension": "2D",
  "tags": ["racing", "arcade", "neon"],
  "inputMethods": ["Touch", "Keyboard", "Gamepad"],
  "orientation": "Landscape",
  "contentWarnings": ["FlashingLights"],
  "engine": "Phaser 3",
  "videoUrl": "https://youtu.be/xxxxxxxxxxx",
  "sourceCodeUrl": "https://github.com/me/neon-drift",
  "challengeNotes": "The track changes shape every lap, which fits this week's theme.",
  "credits": "Music: Jane Doe (CC-BY 4.0)",
  "aiDisclosure": "Code written with Claude Code; all art and music made by hand."
}

Awards example (inside the same object):
"awards": [
  { "key": "first-win", "title": "First win", "description": "Win a round", "icon": "🏆" },
  { "key": "no-hit", "title": "Untouchable", "description": "Clear a level without getting hit", "icon": "🛡️" },
  { "key": "hidden-room", "title": "Explorer", "description": "Find the hidden room", "icon": "🗝️", "secret": true }
]

## 3b. Leaderboards and awards (optional)
If the game has a score, a time or achievements, integrate the Gamero SDK:
- Add `<script src="http://www.gamero.gg/sdk/gamero.js"></script>` to index.html before the game code. It defines `window.Gamero`.
- Guard every call with `if (window.Gamero?.available)`: outside Gamero (local dev) it is false and calls reject.
- `Gamero.submitScore(value, { board = "main", order = "desc" })` when a run ends. Integers only; for times use milliseconds with order "asc". Only the player's best is kept. Resolves { best, improved, rank, players }.
- `Gamero.getLeaderboard(board, { limit })` resolves { entries: [{ rank, player, value, isMe }], me }.
- `Gamero.unlockAward(key)` for each award in game.json, whenever its condition is met (repeat calls are ignored).
- Calls reject with err.code "signin" for guests: keep the game fully playable, never block on these calls, and catch errors.
- Gamero shows its own leaderboard and award panels and an "Award unlocked" popup, so in-game UI is optional.

## 4. npm run build → gamero.zip
- Add `archiver` as a devDependency and a script `scripts/gamero-zip.mjs` that zips the CONTENTS of the build folder at the ZIP root (index.html must be at the top level, not inside dist/) plus the `screens/` folder as `screens/`.
- Chain it in package.json: `"build": "<existing build command> && node scripts/gamero-zip.mjs"`.
- Add `gamero.zip` to .gitignore.
- The script must fail with a clear message if index.html is missing from the build output.

## 5. Check before you finish
- Run `npm run build` and list the ZIP contents. Confirm: `index.html` at the root, `screens/` next to it, only allowed file names in screens/, game.json is valid JSON with only the properties above, every `![…](file)` reference in the .md files points to an existing `description-N` / `how-to-play-N` picture.
- Serve the build output from a sub-folder (e.g. `npx serve` one level up) and confirm the game loads with no 404s.
- If you added the SDK: the script tag is in the built index.html, every Gamero call is guarded by `Gamero.available` and catches errors, the game is fully playable without it, and every `unlockAward` key exists in game.json "awards".
- Tell me the ZIP size and anything left for me to do. On Gamero I only have to upload the ZIP in step 1 of the submission page, check the preview, and press Publish.

2What goes in the ZIP

gamero.zip
├── index.html              ← your game (must be at the root; add the SDK script here for leaderboards/awards)
├── assets/ …               ← anything your game loads, relative paths
└── screens/                ← game page data, NOT served with the game
    ├── game.json           ← title, tagline, theme, genre, controls, credits, awards…
    ├── cover.png           ← card + page header, 16:9, at least 630×354
    ├── screenshot-1.png    ← gallery, in number order (max 8)
    ├── screenshot-2-boss-fight.png   ← text after the number = caption "Boss fight"
    ├── description.md      ← "About" text (markdown, max 10 000 chars)
    ├── description-1.png   ← pictures for the description
    ├── how-to-play.md      ← "How to play" text (markdown, max 3 000 chars)
    └── how-to-play-1.png   ← pictures for the instructions (controls diagram…)

3screens/game.json

Every field from the submission form. Values must match the site's lists (the AI prompt includes them all), and this week's challenge fixes some of them.

{
  "title": "Neon Drift",
  "tagline": "Race through a city that rebuilds itself every lap",
  "theme": "Neon / Synthwave",
  "category": "Sports",
  "subCategory": "Racing",
  "dimension": "2D",
  "tags": ["racing", "arcade", "neon"],
  "inputMethods": ["Touch", "Keyboard", "Gamepad"],
  "orientation": "Landscape",
  "contentWarnings": ["FlashingLights"],
  "engine": "Phaser 3",
  "videoUrl": "https://youtu.be/xxxxxxxxxxx",
  "sourceCodeUrl": "https://github.com/me/neon-drift",
  "challengeNotes": "The track changes shape every lap, which fits this week's theme.",
  "credits": "Music: Jane Doe (CC-BY 4.0)",
  "aiDisclosure": "Code written with Claude Code; all art and music made by hand."
}

4Images and texts

FileBecomesRules
cover.pngCover (card + page header)16:9, min 630×354, ideally 1280×720. Center-cropped.
screenshot-1.png … -8.pngScreenshot galleryNumber order. Longest side 320–1920 px. screenshot-3-night-level.png → caption “Night level”.
description.mdAboutMarkdown, max 10 000 characters.
description-N.pngPictures in AboutUp to 10. Use ![alt](description-1.png). Unreferenced ones go at the end.
how-to-play.mdHow to playMarkdown, max 3 000 characters. Goal + controls per input.
how-to-play-N.pngPictures in How to playUp to 10, e.g. a controls diagram.

Images can be PNG, JPG, WebP or GIF up to 5 MB each. We convert them to WebP, so they show as still images. Markdown can't contain HTML, and only pictures from screens/ are displayed.

Example description.md

Race through a city that rebuilds itself every lap.

![The city shifting mid-race](description-1.png)

- 12 hand-made tracks
- Ghost replays of your best lap

5Make npm run build create the ZIP

Doing it by hand? Add this script, then chain it after your build in package.json:

// scripts/gamero-zip.mjs: zips the web build + screens/ into gamero.zip
// npm i -D archiver
import { createWriteStream, existsSync } from "node:fs";
import archiver from "archiver";

const BUILD_DIR = "dist"; // folder that contains index.html after the build

if (!existsSync(`${BUILD_DIR}/index.html`)) {
  console.error(`${BUILD_DIR}/index.html not found, did the build run?`);
  process.exit(1);
}

const output = createWriteStream("gamero.zip");
const zip = archiver("zip", { zlib: { level: 9 } });
zip.pipe(output);
zip.directory(BUILD_DIR, false);                                // game files at the ZIP root
if (existsSync("screens")) zip.directory("screens", "screens"); // game page data
await zip.finalize();
await new Promise((resolve) => output.on("close", resolve));
console.log(`gamero.zip ready (${(zip.pointer() / 1024 / 1024).toFixed(1)} MB). Upload it in step 1 of your submission.`);
"scripts": {
  "build": "vite build && node scripts/gamero-zip.mjs"
}

With Vite, set base: "./" so assets load from relative paths. Add gamero.zip to .gitignore.

6Leaderboards & awards

Optional. With the Gamero SDK your game can post scores and unlock awards for the signed-in player. Gamero shows the leaderboard and awards next to the game, plus an “Award unlocked” popup over it, so you don't have to build any UI for them.

Setup

Add this to your index.html, before your game's own scripts. It defines window.Gamero.

<script src="http://www.gamero.gg/sdk/gamero.js"></script>
// After the run ends (integers only: points, or a time in ms)
if (window.Gamero?.available) {
  const { rank, improved } = await Gamero.submitScore(score);
  await Gamero.submitScore(timeMs, { board: "speedrun", order: "asc" }); // lower wins

  // Unlock awards whenever the condition is met; repeats are ignored
  Gamero.unlockAward("first-win").catch(() => {});

  // Show the top 10 in your own UI
  const { entries, me } = await Gamero.getLeaderboard("main", { limit: 10 });
}

Your game runs in a sandboxed iframe and never sees the player's login. The SDK passes each call to the Gamero page, which saves it for the signed-in player. Every method returns a Promise.

Reference

CallWhat it doesResolves
Gamero.availabletrue when running on GameroA boolean, not a Promise. False on your local dev server.
submitScore(value, { board, order })Report a finished run{ best, improved, rank, players }. board defaults to "main".
getLeaderboard(board, { limit })Top scores (default 10, max 100){ key, order, players, entries: [{ rank, player, value, isMe }], me }
unlockAward(key)Unlock an award for the player{ unlocked, award }. unlocked is true only the first time.
getAwards()All awards and the player's progress[{ key, title, description, icon, isSecret, unlockedBy, unlockedAt }]
getItems()Items your game sells for gamecoins[{ key, title, description, icon, price, owned }]
hasItem(key)Whether the player owns an itemtrue or false (always false for guests).
buyItem(key)Ask the player to buy an item{ bought, item }. bought is false if they already owned it.
getPlayer()Who is playing{ displayName }, or null for guests.

Failed calls reject with an Error whose code is "signin" (a guest tried to save progress), "unavailable" (not running on Gamero), "cancelled" (the player declined a purchase), "coins" (not enough gamecoins), "timeout" or "error" (the message says why, e.g. an unknown award key).

Leaderboards

Awards

Define them in step 4 of your submission (Awards), or in screens/game.json. Each award has a key your game uses, a title, an optional description and emoji icon, and can be secret: hidden from players until they unlock it.

"awards": [
  { "key": "first-win", "title": "First win", "description": "Win a round", "icon": "🏆" },
  { "key": "no-hit", "title": "Untouchable", "description": "Clear a level without getting hit", "icon": "🛡️" },
  { "key": "hidden-room", "title": "Explorer", "description": "Find the hidden room", "icon": "🗝️", "secret": true }
]

Shop items (gamecoins)

Your game can sell extras for gamecoins, Gamero's currency: a skin, a bonus level, a power-up. Define them in step 5 of your submission (Shop items) with a key, title, emoji and a price from 10 to 500 coins.

// On start: turn on what the player owns
if (window.Gamero?.available && await Gamero.hasItem("gold-skin")) useGoldSkin();

// From your shop button: Gamero shows the price and asks the player
try {
  await Gamero.buyItem("gold-skin");
  useGoldSkin();
} catch (e) {
  // e.code: "cancelled" (player said no), "coins" (not enough), "signin" (guest)
}

Good to know

7Upload and publish

  1. Open the submission page (here) and upload gamero.zip in step 1. It creates your draft and fills in every step below it.
  2. Check the remaining list in the Publish step, press Test play and look at the preview page.
  3. Using leaderboards or awards? Play a run in Test play and check that your score and awards show up on the preview page.
  4. Press Publish. To update the game later, run npm run build again and upload the new ZIP.

The game runs in a sandboxed iframe on a separate domain: no cookies, popups or parent-page access. Any HTML5 engine works (plain JS, Phaser, PixiJS, Godot single-threaded web export, Unity WebGL…). Test it on a phone too.

Creator guide · Gamero