localStorage without the footguns
localStorage stores strings only, is synchronous, and throws in private mode or when full. Wrap reads in try/catch and never touch it during server rendering.
#storage#browser#json
javascript
function readJSON(key, fallback) {
try {
const raw = localStorage.getItem(key);
return raw ? JSON.parse(raw) : fallback;
} catch {
return fallback;
}
}
function writeJSON(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch {
/* quota exceeded or blocked */
}
}