Files
5chan/.codex/skills/vercel-react-best-practices/rules/client-localstorage-schema.md
T
Tommaso CasaburiandGitHub a92b185a66 chore(ai-workflow): track repo-managed review tooling (#1046)
* chore(ai-workflow): track repo-managed review tooling

* fix(ai-workflow): remove repo-specific path assumptions

Make shared workflow hooks and APK testing guidance resolve paths from the repo and contributor environment so the tooling works for all contributors, not just one machine.
2026-03-10 15:49:15 +08:00

1.9 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Version and Minimize localStorage Data MEDIUM prevents schema conflicts, reduces storage size client, localStorage, storage, versioning, data-minimization

Version and Minimize localStorage Data

Add version prefix to keys and store only needed fields. Prevents schema conflicts and accidental storage of sensitive data.

Incorrect:

// No version, stores everything, no error handling
localStorage.setItem('userConfig', JSON.stringify(fullUserObject))
const data = localStorage.getItem('userConfig')

Correct:

const VERSION = 'v2'

function saveConfig(config: { theme: string; language: string }) {
  try {
    localStorage.setItem(`userConfig:${VERSION}`, JSON.stringify(config))
  } catch {
    // Throws in incognito/private browsing, quota exceeded, or disabled
  }
}

function loadConfig() {
  try {
    const data = localStorage.getItem(`userConfig:${VERSION}`)
    return data ? JSON.parse(data) : null
  } catch {
    return null
  }
}

// Migration from v1 to v2
function migrate() {
  try {
    const v1 = localStorage.getItem('userConfig:v1')
    if (v1) {
      const old = JSON.parse(v1)
      saveConfig({ theme: old.darkMode ? 'dark' : 'light', language: old.lang })
      localStorage.removeItem('userConfig:v1')
    }
  } catch {}
}

Store minimal fields from server responses:

// User object has 20+ fields, only store what UI needs
function cachePrefs(user: FullUser) {
  try {
    localStorage.setItem('prefs:v1', JSON.stringify({
      theme: user.preferences.theme,
      notifications: user.preferences.notifications
    }))
  } catch {}
}

Always wrap in try-catch: getItem() and setItem() throw in incognito/private browsing (Safari, Firefox), when quota exceeded, or when disabled.

Benefits: Schema evolution via versioning, reduced storage size, prevents storing tokens/PII/internal flags.