Wrap values in a small versioned envelope
Instead of saving a bare score such as 240, store a JSON object such as { version: 2, bestScore: 240, settings: { sound: true } }. On load, parse the text, check that it is an object, and inspect its version before using fields. JSON.parse can throw a SyntaxError for invalid JSON, so handle malformed text with a defined fallback rather than allowing startup to stop before the player can begin.
Keep the envelope narrow and document what each version means. Avoid treating the version alone as validation: a value tagged version two can still be incomplete or have the wrong type. Check the fields the current build actually relies on, such as a finite nonnegative bestScore and a boolean sound preference.
Write one migration for each supported old shape
A migration from version one can transform the old number into the new envelope, fill in a default setting, and then save the version-two form. Make migrations sequential when multiple historical versions are supported: version one to two, then two to three. Test each fixture independently, including missing keys, malformed JSON, an unknown future version, and a partially written value. Decide whether unknown data is preserved, ignored, or reset and communicate a recovery message when it matters.
Keep browser storage limitations in scope
MDN describes localStorage as origin-scoped data that can persist across browser sessions, but storage availability and contents should not be treated as a guaranteed account backup. Do not put secrets or trust-sensitive decisions there. If a game cannot read a save, allow a defined fresh start and avoid repeatedly retrying the same broken migration on every launch.
Questions about localStorage game data versioning
Should I clear all saves when the format changes?
Only when that is an explicit product decision. If important values can be mapped safely, a small tested migration can preserve them; otherwise define a clear fallback and explain the reset.
Does a version field make localStorage data reliable?
No. It identifies the expected shape so the game can migrate or reject it. Data can still be missing, malformed, stale, or unavailable, so validate before using it.