
Config Values
What meta.json is
- An optional JSON file at the root of your game bundle, next to
index.html. - It's the only place these values come from. The upload wizard never asks for them.
- Every field is optional.
{}is valid; nometa.jsonat all is valid. An absent field means "nothing declared".
A complete example
{
"title": "Orbit Dash",
"description": "Race your orb around the ring and rack up points before the timer runs out.",
"controls": "Tap to switch direction.",
"logic": "Collect rings for points. One spike hit ends the run.",
"schemaVersion": 1,
"resultSorting": "highestScore",
"config": [
{
"key": "startScore",
"valueType": "number",
"value": 10,
"min": 0,
"max": 100,
"moddable": true,
"description": "Starting score. min/max bound what mods can set."
}
],
"license": "MIT",
"credits": "Music by Jane Doe, sprites by PixelOrb",
"sourceUrl": "https://example.com/assets/pixelorb"
}
Field reference
| Field | Type | Required? | Example |
|---|---|---|---|
title | string | No | "Orbit Dash" |
description | string | No | "Race your orb around the ring." |
controls | string | No | "Tap to switch direction." |
logic | string | No | "One spike hit ends the run." |
schemaVersion | string or number | No | 1 or "1" |
config | array of config entries (max 25, unique keys) | No | see the config section below |
resultSorting | "highestScore", "lowestScore", "fastestTime", or "slowestTime" | No | "highestScore" |
license | string: an SPDX id or "proprietary" | No | "MIT" |
credits | string | No | "Music by Jane Doe" |
sourceUrl | string: must start with http:// or https:// | No | "https://example.com/assets/pixelorb" |
title, description, controls, logic
These seed the project created by your upload:
title: the project's title (trimmed, silently truncated at 50 characters rather than rejected). Rendered as plain text; markdown in it is not. Absent or blank, the project starts as "Untitled Post".description: the body of the project's description.controls: fills the description's Controls section.logic: fills the description's Game Logic section (labelled Rules in the create wizard).
The three description sections are stored as one composed string (Controls, then Game Logic, then body) sharing a combined 2500-character budget. Over budget, the body is trimmed first, then logic, then controls. They render as markdown to players; an absent section simply isn't rendered.
All remain editable in the console. See Writing & formatting your Game description.
What a re-upload changes
- Seed-once:
title,description/controls/logic, andresultSortingare written on the founding upload only. A later re-upload never changes them; edit them in the console instead. - Bundle-owned:
config,schemaVersion,license,credits, andsourceUrlare re-read from the bundle on every upload (re-uploads and repatches included), so they always track your latest ZIP.
schemaVersion
A forward-compatibility hook. Nothing branches on it today. Omit it.
config
A config value is a named, typed setting your game reads at runtime via the SDK's getConfigValue(): a starting score, a difficulty label, a UI color. You declare them in the config array: at most 25 entries, each with a unique key.
Declaring at least one config value is what unlocks Superposting: other creators posting variations of your game (same build, different config values) without touching your code. With no config entries, the "Allow Superposting" toggle in the create wizard stays disabled.
The entry shape
Each entry in config is an object with:
| Field | Required? | Notes |
|---|---|---|
key | Yes | Unique name for the value, trimmed of surrounding whitespace before anything else is checked. |
valueType | Yes | "number", "string", "boolean", or "color" (see below). |
description | No | The human-readable label for this value, up to 100 characters. Over the limit, it's silently dropped rather than failing the entry. |
value / defaultValue | At least one | The value itself. defaultValue is an alias; if both are present, value wins. Native JSON type or its string form both work (10 or "10"). |
range | No | A fixed list of allowed values (see below). |
min / max, minLength / maxLength | No | Bound pairs (see below). |
moddable | No | Tri-state open/locked/unmarked (see below). |
The value types
number: bound withmin/max.string: bound withminLength/maxLength.boolean: no bounds, norange(pin a value withmoddableinstead).color: a hex string (#RRGGBBor#RRGGBBAA). No bound pair; pair withrangefor a fixed swatch list.
range restricts the value to a fixed list instead of a bound window: presets like ["easy", "normal", "hard"] or a small palette. Every member must match the entry's valueType, and value must be one of the members.
Warning:
rangeand bounds are mutually exclusive on a single entry. Declaring both is invalid, and any invalid entry drops the wholeconfigblock, as if you'd declared none.
Warning: Max 25 entries, every
keyunique after trimming. Going over the cap or repeating a key also invalidates the entireconfigblock.
The moddable states
- Open:
"moddable": true. Other creators can change this value in their mods. - Locked:
"moddable": false. Every mod keeps your declared value. - Unmarked:
moddableomitted. Treated as open (back-compatibility).
Locks only apply to other creators. You always have full access to your own values.
A complete config example
{
"schemaVersion": 1,
"config": [
{
"key": "startScore",
"valueType": "number",
"value": 10,
"min": 0,
"max": 100,
"moddable": true,
"description": "Starting score. min/max bound what mods can set; open, so mods can start players off differently."
},
{
"key": "playerName",
"valueType": "string",
"value": "Player",
"description": "Unconstrained string: no range, no length bounds. moddable is omitted, so this is 'unmarked' (still editable by mods, for back-compat)."
},
{
"key": "teamTag",
"valueType": "string",
"value": "QA",
"minLength": 2,
"maxLength": 12,
"description": "String bounded by length instead of a fixed range."
},
{
"key": "hardMode",
"valueType": "boolean",
"value": false,
"moddable": false,
"description": "Locked: every mod of this game keeps hardMode at its declared value."
},
{
"key": "difficulty",
"valueType": "string",
"value": "normal",
"range": ["easy", "normal", "hard"],
"description": "Range-constrained string: a fixed set of presets instead of an open-ended bound."
},
{
"key": "themeColor",
"valueType": "color",
"value": "#f15a24",
"range": ["#f15a24", "#fbb03a", "#38a169"],
"description": "The color valueType, restricted to a swatch list via range."
}
]
}
This example covers every constraint shape and every moddable state.
What you'll see in the console
- With Allow Superposting on, the wizard's Review panel shows one chip per declared key with an open (✓) or locked (✕) state you can tap to toggle. This only controls
moddable. Key, type, value, and bounds come frommeta.json; re-upload to change those. - With no
configentries, the toggle renders disabled with an inline hint.
resultSorting
Preselects the create wizard's Scoring tile (highestScore, lowestScore, fastestTime, or slowestTime). You can still change it before publishing. Omitted → Highest Score wins. (The backend's internal group result type isn't declarable here.)
The two *Time options make the platform treat the reported number as a duration in seconds (fractions allowed), not milliseconds. See Reporting Results.
license, credits, sourceUrl
The licensing trio, covering material in your bundle:
license: the SPDX identifier of the license covering your whole game (e.g."MIT"), or"proprietary"for your own work — never the license of one embedded asset. Even if the only third-party thing in your bundle is, say, a font under the SIL Open Font License, don't setlicenseto"OFL"; that per-asset detail belongs inTHIRD-PARTY-NOTICES.txt(see below), not in this field. Matched by exact string: a typo silently counts as unrecognized (no gate, no warning) yet is still stored and shown verbatim. An omittedlicenseisn't a separate state — per the Minit Games ToS it resolves to"proprietary"(your own content), and the console shows it exactly like an explicit"proprietary": "Own content". Double-check the spelling. The server re-validates against the same policy table the console checks.credits: a freeform credit line shown to players; no length cap.sourceUrl: a link to where the material came from; must start withhttp://orhttps://(case-insensitive; only the prefix is checked). The console renders it as a clickable link only when it also parses as an absolute http(s) URL at display time, otherwise as plain text; in the player app it's always plain, non-clickable text.
Which licenses Minit Games can host, when you need a THIRD-PARTY-NOTICES.txt, and what an absent license means: Licensing third-party content.
Validation is per-field
- Each top-level field is validated independently. An invalid field is silently dropped; the rest of the file still applies.
- A
meta.jsonthat isn't valid JSON at all is treated as if the file weren't there: no error, the upload proceeds. - Within
config, the whole block stands or falls together: one invalid entry drops the entireconfigarray (onlyconfig). Entry-level rules: theconfigsection above.
Tip: Because invalid fields disappear silently, check your project page after uploading. A missing value means the field failed validation.