Brewser Docs
Publishing

Manifest Reference

Every field in a Brewser app manifest, and how it's generated

Every Brewser app ships a manifest.json describing its identity, the capabilities it needs, and how it should behave on the console. This page is the field-by-field reference.

You don't hand-write it — Brewser generates it

Here's the part that trips people up: you never author the published manifest by hand. You fill in the submission form on brewser.io, and Brewser builds a validated manifest.json from your answers. The manifest below is what comes out of that process and ships inside your app on the SD card — it's useful to understand, but the form is where you actually set these values.

The submission side validates every field against a strict schema (unknown fields are rejected), so a malformed manifest can't reach the catalogue.

A real manifest, annotated

This is the generated manifest for the Save Demo app (com.natureglass.savedemo), lightly annotated:

{
  "id": "com.natureglass.savedemo",   // reverse-domain id: com.<publisher>.<app>
  "name": "Save Demo",                 // shown in the catalogue
  "version": "1.0.0",                  // semver
  "description": "<p>...</p>",          // rich text (a small HTML allowlist)
  "summary": "A hands-on test harness for the Brewser save & leaderboard APIs.",
  "logo": "assets/appbanner.jpg",      // relative path inside your bundle
  "entry": "index.html",               // the first file Brewser opens
  "categories": ["Apps", "Demos"],     // one or more catalogue categories
  "permissions": [],                    // declared capabilities (see below)
  "compatibility": ["switch", "web"],  // where the app is meant to run
  "allowed_origins": [],                // external hosts the app may reach
  "developer": "Alex Daskalakis",      // your publisher display name
  "license": "MIT",
  "tags": ["Leaderboards", "Save Game"],
  "exitGame": "PLUS",                  // controller button that exits the app
  "fullscreen": true,                   // app owns the whole screen
  "hideMouseDocked": false,             // software-cursor behaviour, docked
  "hideMouseUndocked": false,           //   ... and handheld
  "publishedAt": "2026-08-06T10:20:30Z" // set once, on first publish
}

Field reference

FieldRequiredTypeNotes
idYesstringcom.<publisher>.<app>, lowercase. Stable — don't change it between versions.
nameYesstringUser-facing name. Don't impersonate other products.
versionYesstringSemantic version, e.g. 1.2.0.
descriptionYesstringRich text with a small HTML allowlist (p, br, strong, em, ul/ol/li, code, a).
summaryNostringShort one-liner (≤100 chars) for cards.
logoYesstringRelative path to your icon/banner inside the bundle.
entryYesstringThe first file Brewser opens. Defaults to index.html; must exist in the bundle.
categoriesYesstring[]One or more catalogue categories.
permissionsYesstring[]Declared capabilities — see below. May be empty.
compatibilityYesstring[]Where the app runs: switch, web, mobile.
allowed_originsYesstring[]External https?:// hosts the app is allowed to reach. Empty if it makes no network calls.
developerYesstringYour publisher display name.
licenseYesstringAn SPDX-style license id (MIT, Apache-2.0, GPL-3.0, …).
exitGameYesstringThe controller button that exits the app (see Controls).
fullscreenYesbooleanWhether the app takes over the whole screen.
hideMouseDocked / hideMouseUndockedNobooleanSoftware-cursor visibility per dock state.
freshProcessOnExitNobooleanAsk the runtime for a clean context on exit.
publishedAtYesstringISO timestamp, set once at first publish and carried forward.
tagsNostring[]Free-form tags for discovery.
genre / featuresNostring[]Curated genre and feature labels.
buttonMappingNoobjectMaps keyboard keys to Switch controls — see Controls.

Field values like categories, license, genre and features are validated against curated lists on the platform, so the form offers you the valid choices rather than free text.

Permissions

permissions is a list of the capabilities your app declares up front. Users see them before launching, and the runtime uses them to decide what your app may touch — network access, local storage, device info, account access, and so on. Requesting a capability your app doesn't use just adds friction, so declare the minimum you need. Apps that request nothing skip the permission prompt entirely and offer the smoothest click-to-play experience.

Hardware access (USB, Bluetooth, and the other device APIs covered in Hardware APIs) is declared here too. Declaring a peripheral says "this app talks to hardware of this kind"; choosing a specific device — filtering by USB vendor/product id, or by Bluetooth service UUID — happens in your app's own requestDevice() call, exactly as it does in Chrome. Those filters live in your JavaScript, not in the manifest.

The exact set of permission names is a curated list maintained by Brewser, so it can grow over time. If your app needs a capability you don't see offered, mention it in your submission.

Network needs two things

If your app reaches the internet, it needs both a network capability and every external host listed in allowed_origins:

"allowed_origins": [
  "https://api.example.com",
  "https://cdn.example.com"
]

The security scanner cross-checks the hosts your code actually contacts against this list — an undeclared host is flagged. See Networking in Apps for what the runtime can reach, and Security Review for how the check works.

What doesn't need declaring

Platform features like Saves & Leaderboards need nothing in the manifest — they're not hardware. They work through the brewser.js SDK and only depend on the user being signed in for their cloud parts.

On this page