
Saving User Data
Use userData to remember things about a player between plays. The most common use case is skipping the tutorial on their second visit.
The Single-Slot Model
Each Game can optionally declare one userData key in the Minit Games console. That key identifies a single per-player storage slot. Your game can read the slot on startup and write to it when the game ends.
If a Game has no declared key, getUserData() always returns undefined and writes are silently ignored.
Enabling userData in the Console
- Open your Game in console.minit.games.
- Click Edit and check the Store User Data checkbox.
- Enter a 1–64 character key, for example
tutorial-seenorplayer-progress. - Save. The slot is now active.
To disable it, uncheck Store User Data and save. New plays stop reading or writing the slot. Existing data is not deleted; re-enabling with the same key surfaces it again.
You can change the key. Data stored under the old key becomes dormant: players will not see it via the new key. Reverting to the old key surfaces it again.
Mods: the userData setting is inherited from the base Game and cannot be changed in the mod editor. If the base Game has a key, all its mods share the same slot.
SDK API
Make sure @minit-games/sdk is at 1.3.0 or later in your package.json.
import { getUserData, reportResult } from '@minit-games/sdk'
Reading: getUserData()
const value = getUserData() // returns string | undefined
Reads the stored value for the Game's declared key. No argument needed; the slot is identified by the key you set in the console.
undefined: the slot has never been written for this player."": the slot was explicitly stored as an empty string. This is a valid, distinct value; do not treat it as equivalent toundefined.
Writing: reportResult(score, { userData })
Pass an optional userData string as the second argument to reportResult:
reportResult(score, { userData: 'done' })
This writes 'done' to the player's slot for this Game. The write happens atomically with the result; there is no separate "save" call.
Omitting userData leaves the stored value unchanged.
Worked Example: Tutorial-Skip Flag
import { getUserData, reportResult } from '@minit-games/sdk'
// On game start: check the "Store User Data" box in the console and set the key to "tutorial-seen"
const seen = getUserData()
if (seen === undefined) {
showTutorial() // First time: slot not yet written
} else {
skipTutorial() // Returning player: skip straight to the game
}
// When the game ends
function handleGameOver(score) {
reportResult(score, { userData: 'done' })
}
On the player's next visit, getUserData() returns 'done' and the tutorial is skipped.
Cross-Game Sharing
Two Games by the same creator that declare the same key share a slot, by design, and across engines. Use it for cross-game continuity (e.g. unlocking a character across your catalogue once any of your games is completed); use a unique key per Game (towerDefense-highScore, not highScore) when each Game needs its own slot.
Limits
| What | Limit |
|---|---|
| Key length (set in console) | 64 characters |
| Value size (written per play) | 1024 UTF-8 bytes (~1 KB) |
Keep values compact: store flags and small state, not full game replays. If you need to persist multiple values, encode them into a single string:
function handleGameOver(score, level, darkMode) {
const value = JSON.stringify({ level, darkMode })
reportResult(score, { userData: value })
}
function loadPlayerState() {
const raw = getUserData()
if (raw === undefined || raw === '') return { level: 1, darkMode: false }
try {
return JSON.parse(raw)
} catch {
return { level: 1, darkMode: false }
}
}
Testing Locally
During local development (npm run dev), seed getUserData() via a URL parameter so you can test both the first-visit and returning-player paths without deploying.
URL syntax: ?userData=<url-encoded-value>
http://localhost:5173/?userData=done
getUserData() will then return 'done' for that page load.
Use encodeURIComponent for values that contain special characters:
const value = JSON.stringify({ level: 3, darkMode: true })
const encoded = encodeURIComponent(value)
// Open: http://localhost:5173/?userData=<encoded>
Local only. URL params are used as a fallback when no host has injected real player data. In the Minit Games mobile app, the host always provides real data and URL params are ignored.
Data Persists Across Game Updates
The slot is identified by the console key, not the ZIP, so player data survives re-uploading a new version.
Note: userData is only persisted in the Minit Games mobile app. The web preview in the Creator Console does not store userData between sessions.
Deeper Dives
- Game Ready Signal: call
Minit.LoadingDone()when your game finishes booting - Reporting Results: call
Minit.ReportResult()when the game ends