Every frontend developer knows localStorage
. It’s our trusty, simple, no-fuss tool for persisting data in the browser. A user's theme preference? A dismissed notification? localStorage
is often the first and best answer. Its beauty is its simplicity: setItem
, getItem
, done.
But modern applications demand more. Users have multiple devices, multiple browser tabs, and they expect their experiences to be seamless and instantaneous. This is where we inevitably hit the "glass ceiling" of localStorage
, a tool designed for a simpler, single-browser world.
So, what happens when your state needs to escape the confines of a single browser? This is where Vaultrice's NonLocalStorage
comes in. It's not just a replacement for localStorage
; it's a complete evolution. It keeps the simplicity you love but adds the powerful, real-time, and cross-device capabilities that modern apps require.
Let's break down the key differences.
API: Familiar Ground, New Power
The best part about adopting NonLocalStorage
is that the API is designed to feel immediately familiar. The learning curve is practically flat, making the switch effortless.
localStorage
:
// Set a value
localStorage.setItem('user-theme', 'dark');
// Get a value
const theme = localStorage.getItem('user-theme'); // 'dark'
NonLocalStorage
:
import { NonLocalStorage } from '@vaultrice/sdk';
const userSettings = new NonLocalStorage(credentials, 'optional-user-id');
// Set a value (and sync it to the edge-cloud)
await userSettings.setItem('theme', 'dark');
// Get a value
const themeItem = await userSettings.getItem('theme');
console.log(themeItem?.value); // 'dark'
As you can see, the core methods are nearly identical. But what happens under the hood is worlds apart.
An Even Simpler API: SyncObject
For developers who love modern, reactive patterns, Vaultrice offers an even higher-level abstraction: SyncObject
.
Instead of calling methods, SyncObject
uses a JavaScript Proxy
to make your remote state behave exactly like a local object.
NonLocalStorage
:
// The familiar, method-based approach
await userSettings.setItem('theme', 'dark');
console.log(await userSettings.getItem('theme')) // 'dark' also on a different device...
SyncObject
:
import { createSyncObject } from '@vaultrice/sdk';
const userSettings = await createSyncObject(credentials, 'optional-user-id');
// Just set the property directly!
// The change is automatically synced to the edge-cloud.
userSettings.theme = 'dark';
console.log(userSettings.theme) // 'dark' also on a different device...
This eliminates the boilerplate of setItem
/getItem
and provides a seamless, "it just works" experience that integrates beautifully with frameworks like React and Vue.
Core Difference #1: Data Scope (A Single Island vs. The Global edge-cloud)
This is the most fundamental difference. localStorage
is, by definition, local and isolated.
-
localStorage
: The data is tied to a single browser on a single device and is strictly confined by the Same-Origin Policy. Data saved onapp.yourdomain.com
is completely inaccessible fromblog.yourdomain.com
. A user's settings on their laptop are invisible to their phone. -
NonLocalStorage
: Your data lives in the edge-cloud and is scoped to a shared object ID. Any client, from any device, tab, or domain, that initializes with the same object ID shares the exact same data. This instantly solves the cross-device and cross-domain state problem without any brittle hacks or workarounds.
Core Difference #2: Data Sync (Static vs. Real-Time)
localStorage
is a silent neighbor. If a user has two tabs open, one tab has no idea when the other tab writes a new value.
-
localStorage
: Data is static. To see an updated value, the user must reload the page or you have to build a complexBroadcastChannel
system to sync tabs. -
NonLocalStorage
: Data is live. It's built on a real-time WebSocket connection. When one client callssetItem
, the new value is instantly pushed to every other connected client.
// This listener will fire on every device when the theme is changed
userSettings.on('setItem', 'theme', ({ value }) => {
console.log(`Theme updated to: ${value}`);
// Instantly update the UI everywhere
document.body.className = value;
});
This simple event listener is the key to building modern, collaborative user interfaces.
Beyond Storage: The NonLocalStorage Superset
Here’s where the comparison ends, because NonLocalStorage
is much more than just a key-value store. It's a complete toolkit for real-time applications, offering a superset of features that localStorage
was never designed for.
Presence: Know Who's Online
Want to build a "who's online" list like in Google Docs or Figma? With NonLocalStorage
, it's a built-in feature of the same API.
// Announce your presence
await userSettings.join({ name: 'Alice', avatar: 'alice.png' });
// Get a list of everyone else who has joined
const connections = await userSettings.getJoinedConnections();
console.log(`${connections.length} users are currently online.`);
// and also messaging...
userSettings.on('message', (msg) => {});
userSettings.send({ /* my message */ });
Atomic Operations: Safe Counters
Ever tried to build a "like" button? localStorage
requires a read-increment-write
pattern that is unsafe with multiple concurrent users. NonLocalStorage
solves this with atomic operations.
// Safely increment a counter without race conditions
await pageStats.incrementItem('like-count', 1);
Offline-First Support
While localStorage
works offline by nature, it doesn't help you sync when the connection returns. Vaultrice provides a dedicated offline-first API that does exactly that.
import { createOfflineNonLocalStorage } from '@vaultrice/sdk';
const offlineStore = await createOfflineNonLocalStorage(credentials, 'user-notes-123');
// This change is saved locally, even on an airplane
await offlineStore.setItem('note1', 'Remember to buy milk.');
// When the user comes back online, the data is synced to the edge-cloud automatically.
Changes are queued in a local "outbox" and synchronized seamlessly upon reconnection.
Built-in Security
NonLocalStorage
is a professional tool with professional security features, including optional End-to-End Encryption (E2EE) for maximum confidentiality.
const secretStore = new NonLocalStorage(credentials, {
id: 'my-secret-diary',
passphrase: 'a-very-strong-secret'
});
// Data is now encrypted on the client before being sent to the server
From Theory to Practice: The React Ecosystem
While the core SDK is powerful on its own, we've made it even easier to integrate Vaultrice into modern web frameworks. For React developers, we provide two key packages:
-
@vaultrice/react
: A library of custom hooks (useNonLocalState
,useNonLocalCounter
,useMessaging
) that handle all the boilerplate of fetching data, managing component state, and subscribing/unsubscribing from real-time events automatically within the React lifecycle. -
@vaultrice/react-components
: A set of pre-built, drop-in UI components like<Voting />
that allow you to add complex real-time features to your app with just a few lines of JSX.
Conclusion: When Should You Make the Switch?
localStorage
remains a great tool for simple, device-specific data. But you should choose NonLocalStorage
as soon as your state needs to be:
- Shared across different domains or subdomains.
- Synced across multiple devices for the same user.
- Live and updated in real-time across multiple tabs or users.
- Resilient to network interruptions.
- Secure with production-grade features like E2EE.
The best part? You don't have to choose. You can use both. And with Vaultrice's free tier, you can start upgrading your state management today without any commitment.
Top comments (0)