LocalMode
LocalForage

Overview

Cross-browser storage adapter with automatic driver fallback using localForage.

@localmode/localforage

Cross-browser storage adapter using localForage. Automatically falls back from IndexedDB to WebSQL to localStorage, ensuring storage works in every browser environment.

Features

  • 🌐 Auto-Fallback — IndexedDB -> WebSQL -> localStorage, automatically
  • 🔄 Cross-Browser — Works everywhere, including older browsers
  • 📦 ~10KB — Mature, battle-tested library
  • 🔒 Safari Private Browsing — Falls back gracefully when IndexedDB is blocked

Installation

bash pnpm install @localmode/localforage @localmode/core
bash npm install @localmode/localforage @localmode/core
bash yarn add @localmode/localforage @localmode/core
bash bun add @localmode/localforage @localmode/core

Quick Start

import { LocalForageStorage } from '@localmode/localforage';
import { createVectorDB, embed, ingest } from '@localmode/core';
import { transformers } from '@localmode/transformers';

// Create storage — automatically picks best available driver
const storage = new LocalForageStorage({ name: 'my-app' });

// Use with VectorDB
const db = await createVectorDB({
  name: 'documents',
  dimensions: 384,
  storage,
});

// Ingest documents
const model = transformers.embedding('Xenova/bge-small-en-v1.5');

await ingest({
  db,
  model,
  documents: [
    { text: 'Local-first AI is the future', metadata: { source: 'blog' } },
    { text: 'Privacy-preserving machine learning', metadata: { source: 'paper' } },
  ],
});

The ingest() function is part of the RAG pipeline. It chunks, embeds, and stores documents in a single call.

Configuration

Prop

Type

Driver Selection

By default, localForage selects the best available driver automatically. You can override the priority:

import localforage from 'localforage';
import { LocalForageStorage } from '@localmode/localforage';

// Force localStorage only (e.g., for testing)
const storage = new LocalForageStorage({
  name: 'my-app',
  driver: [localforage.LOCALSTORAGE],
});

// Prefer IndexedDB, fall back to localStorage (skip WebSQL)
const storage2 = new LocalForageStorage({
  name: 'my-app',
  driver: [localforage.INDEXEDDB, localforage.LOCALSTORAGE],
});

Auto-Fallback Behavior

localForage handles driver selection transparently:

DriverEnvironmentUsed When
IndexedDBModern browsersDefault, best performance
WebSQLOlder Safari, some mobileIndexedDB unavailable
localStorageAll browsersLast resort fallback

Safari Private Browsing

Safari's private browsing mode blocks IndexedDB. localForage automatically falls back to localStorage, so your app keeps working. Note that localStorage has a ~5MB limit, which may affect large vector databases.

Vector Serialization

LocalForageStorage stores vectors as number[] arrays (not Float32Array) internally. This is required because Float32Array does not survive JSON round-tripping used by the localStorage and WebSQL drivers. Vectors are automatically converted to Float32Array on read and back to number[] on write. This means storage size is ~2-3x larger than binary storage, and the localStorage driver's ~5MB quota limit may be reached with large vector databases.

Storage Fallback

Combine with a try/catch pattern for maximum resilience:

import { MemoryStorage } from '@localmode/core';
import { LocalForageStorage } from '@localmode/localforage';

let storage: LocalForageStorage | MemoryStorage;

try {
  storage = new LocalForageStorage({ name: 'my-app' });
  await storage.open();
} catch (error) {
  console.warn('LocalForageStorage unavailable, falling back to memory:', error);
  storage = new MemoryStorage();
}

Comparison

AdapterPackageBundle SizeTransactionsAuto-FallbackBest For
IndexedDBStorage@localmode/core0KB (built-in)NoNoSimple apps, zero extra deps
DexieStorage@localmode/dexie~15KBYesNoProduction apps needing schema versioning
IDBStorage@localmode/idb~3KBNoNoMinimal bundle size
LocalForageStorage@localmode/localforage~10KBNoYesMax browser compatibility

Next Steps

On this page