Skip to main content

Storage Service Guide

Adaptly automatically saves and restores your UI state across browser sessions using localStorage. This guide covers how to configure, customize, and manage persistent storage in your Adaptly applications.

How Storage Works​

Adaptly's storage service automatically:

  • Saves UI changes when components are added, removed, or updated
  • Loads saved state when the application starts
  • Validates stored data against current version
  • Migrates data when version changes

Basic Configuration​

Enable Storage​

Storage is enabled by default, but you can configure it explicitly:

<AdaptlyProvider
apiKey={apiKey}
provider="google"
model="gemini-2.0-flash-exp"
components={components}
adaptlyConfig={adaptlyConfig}
enableStorage={true}
storageKey="my-dashboard"
storageVersion="1.0.0"
/>

Storage Props​

PropTypeDefaultDescription
enableStoragebooleantrueEnable/disable storage
storageKeystring"adaptly-ui"Key prefix for localStorage
storageVersionstring"1.0.0"Version for data migration

Storage Key Naming​

Adaptly creates storage keys using the pattern: {storageKey}_{storageVersion}

// Example configurations
storageKey="my-dashboard" // → "my-dashboard_1.0.0"
storageKey="analytics-app" // → "analytics-app_1.0.0"
storageKey="user-preferences" // → "user-preferences_1.0.0"

Data Structure​

Adaptly stores the complete UI adaptation in localStorage:

{
"adaptation": {
"components": [
{
"id": "metric-1",
"type": "MetricCard",
"props": {
"title": "Revenue",
"value": "$45,231",
"change": "+20.1%"
},
"position": { "x": 0, "y": 0, "w": 2, "h": 1 },
"visible": true
}
],
"layout": "grid",
"spacing": 6,
"columns": 6
},
"timestamp": 1703123456789,
"version": "1.0.0"
}

Version Control​

Automatic Versioning​

When you update storageVersion, Adaptly automatically:

  • Detects version mismatch
  • Clears old data
  • Starts fresh with new version
// Version 1.0.0
<AdaptlyProvider storageVersion="1.0.0" />

// Version 2.0.0 - old data cleared automatically
<AdaptlyProvider storageVersion="2.0.0" />

Manual Version Management​

// Check if stored data exists
const { hasStoredData } = useAdaptiveUI();

if (hasStoredData()) {
console.log("Found saved UI state");
} else {
console.log("No saved state found");
}

Manual Storage Controls​

Save to Storage​

const { saveToStorage } = useAdaptiveUI();

// Manually save current state
const saved = saveToStorage();
if (saved) {
console.log("UI state saved successfully");
}

Load from Storage​

const { loadFromStorage } = useAdaptiveUI();

// Manually load saved state
const savedState = loadFromStorage();
if (savedState) {
console.log("Loaded saved state:", savedState);
}

Clear Storage​

const { clearStorage } = useAdaptiveUI();

// Clear all saved data
const cleared = clearStorage();
if (cleared) {
console.log("Storage cleared successfully");
}

Check Storage Status​

const { hasStoredData } = useAdaptiveUI();

// Check if data exists
if (hasStoredData()) {
console.log("Storage contains saved data");
} else {
console.log("Storage is empty");
}

Advanced Storage Patterns​

Multiple Storage Keys​

Use different storage keys for different parts of your app:

// Dashboard storage
<AdaptlyProvider
storageKey="dashboard-ui"
storageVersion="1.0.0"
// ... other props
/>

// Analytics storage
<AdaptlyProvider
storageKey="analytics-ui"
storageVersion="1.0.0"
// ... other props
/>

Conditional Storage​

const [enableStorage, setEnableStorage] = useState(true);

<AdaptlyProvider
enableStorage={enableStorage}
storageKey="my-app"
// ... other props
/>

// Toggle storage on/off
<button onClick={() => setEnableStorage(!enableStorage)}>
{enableStorage ? "Disable" : "Enable"} Storage
</button>

Storage with User Authentication​

const [userId, setUserId] = useState(null);

<AdaptlyProvider
storageKey={userId ? `user-${userId}-ui` : "guest-ui"}
storageVersion="1.0.0"
// ... other props
/>

Browser Compatibility​

Supported Browsers​

  • Chrome: 4+ (localStorage support)
  • Firefox: 3.5+ (localStorage support)
  • Safari: 4+ (localStorage support)
  • Edge: 12+ (localStorage support)

Storage Limits​

  • Chrome/Firefox: ~10MB per domain
  • Safari: ~5MB per domain
  • Mobile: Varies by device

Fallback Behavior​

If localStorage is not available, Adaptly gracefully degrades:

// Storage will be disabled automatically
<AdaptlyProvider
enableStorage={true} // Will be ignored if localStorage unavailable
// ... other props
/>

Privacy Considerations​

Data Storage​

  • Data is stored locally in the user's browser
  • No data is sent to external servers
  • Users can clear data through browser settings

Sensitive Data​

Avoid storing sensitive information in component props:

// ❌ Don't store sensitive data
<MetricCard
title="User Revenue"
value="$45,231"
apiKey="secret-key" // ❌ Never store API keys
/>

// ✅ Store only display data
<MetricCard
title="User Revenue"
value="$45,231"
change="+20.1%"
/>

Data Retention​

  • Data persists until manually cleared
  • Users can clear data through browser settings
  • Consider implementing data expiration

Debugging Storage​

Enable Debug Logging​

import { adaptlyLogger } from "adaptly";

// Enable debug logging
adaptlyLogger.setConfig({ enabled: true, level: "debug" });

Check Storage Contents​

// Inspect localStorage directly
const storageKey = "my-dashboard_1.0.0";
const storedData = localStorage.getItem(storageKey);
console.log("Stored data:", JSON.parse(storedData));

Storage Events​

// Listen for storage changes
window.addEventListener("storage", (e) => {
if (e.key === "my-dashboard_1.0.0") {
console.log("Storage changed:", e.newValue);
}
});

Common Issues​

Storage Not Persisting​

Check enableStorage prop:

// ✅ Storage enabled
<AdaptlyProvider enableStorage={true} />

// ❌ Storage disabled
<AdaptlyProvider enableStorage={false} />

Check storage key:

// ✅ Valid key
<AdaptlyProvider storageKey="my-app" />

// ❌ Empty key
<AdaptlyProvider storageKey="" />

Version Mismatch​

Update storage version:

// Old version
<AdaptlyProvider storageVersion="1.0.0" />

// New version - old data cleared
<AdaptlyProvider storageVersion="2.0.0" />

Data Not Loading​

Check localStorage availability:

if (typeof window !== "undefined" && window.localStorage) {
// localStorage is available
} else {
// localStorage not available
}

Best Practices​

1. Use Descriptive Storage Keys​

// ✅ Good
storageKey="dashboard-ui"
storageKey="analytics-dashboard"
storageKey="user-preferences"

// ❌ Avoid
storageKey="ui"
storageKey="data"
storageKey="app"

2. Version Your Storage​

// ✅ Good - versioned
storageVersion="1.0.0"
storageVersion="2.0.0"

// ❌ Avoid - no versioning
storageVersion="1"
storageVersion="latest"

3. Handle Storage Errors​

try {
const saved = saveToStorage();
if (!saved) {
console.warn("Failed to save UI state");
}
} catch (error) {
console.error("Storage error:", error);
}

4. Clean Up Old Data​

// Clear old storage keys
const oldKeys = ["my-app_1.0.0", "my-app_1.1.0"];
oldKeys.forEach(key => localStorage.removeItem(key));

Next Steps​

Example Implementations​


Ready for advanced features? Check out the Advanced Features Guide to learn about custom loaders, component validation, and advanced hooks usage!