Skip to main content
Rehydra works seamlessly in browsers without special configuration. This guide covers browser-specific considerations.

Basic Example

<!DOCTYPE html>
<html>
<head>
  <title>PII Anonymization</title>
</head>
<body>
  <script type="module">
    import { 
      createAnonymizer, 
      InMemoryKeyProvider,
      decryptPIIMap,
      rehydrate
    } from './node_modules/rehydra/dist/browser.js';
    
    async function demo() {
      const keyProvider = new InMemoryKeyProvider();
      const anonymizer = createAnonymizer({
        ner: { 
          mode: 'quantized',
          onStatus: (s) => console.log('NER:', s),
          onDownloadProgress: (p) => console.log(`Download: ${p.percent}%`)
        },
        semantic: { enabled: true },
        keyProvider
      });
      
      await anonymizer.initialize();
      
      const result = await anonymizer.anonymize(
        'Contact Maria Schmidt at [email protected] in Berlin.'
      );
      
      console.log('Anonymized:', result.anonymizedText);
      
      // Rehydrate
      const key = await keyProvider.getKey();
      const piiMap = await decryptPIIMap(result.piiMap, key);
      const original = rehydrate(result.anonymizedText, piiMap);
      
      console.log('Rehydrated:', original);
      
      await anonymizer.dispose();
    }
    
    demo().catch(console.error);
  </script>
</body>
</html>

Bundler Setup

Vite

No special configuration needed:
// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  // Standard config - Rehydra works out of the box
});
// Your app code
import { createAnonymizer } from 'rehydra';
// Automatically uses browser-safe build

Webpack

Webpack 5+ handles conditional exports automatically:
// webpack.config.js
module.exports = {
  // Standard config - Rehydra works out of the box
};

esbuild

esbuild src/index.ts --bundle --outdir=dist --format=esm
# Browser build is automatically selected

First-Use Downloads

On first initialization, Rehydra downloads:
DataSizeStorage
NER Model (quantized)~280 MBOPFS
Semantic Data~12 MBIndexedDB
Show download progress to users:
const anonymizer = createAnonymizer({
  ner: {
    mode: 'quantized',
    onStatus: (status) => {
      document.getElementById('status').textContent = status;
    },
    onDownloadProgress: (progress) => {
      const percent = Math.round(progress.percent);
      document.getElementById('progress').style.width = `${percent}%`;
    }
  }
});

Storage in Browsers

Model Storage (OPFS)

Large model files use the Origin Private File System:
  • Persistent across sessions
  • Not visible in DevTools
  • Quota managed by browser
  • Cleared with “Clear site data”

PII Map Storage (IndexedDB)

For session-based storage:
import { 
  createAnonymizer,
  IndexedDBPIIStorageProvider,
  InMemoryKeyProvider,
} from 'rehydra';

const storage = new IndexedDBPIIStorageProvider('my-app-pii');

const anonymizer = createAnonymizer({
  ner: { mode: 'quantized' },
  keyProvider: new InMemoryKeyProvider(),
  piiStorageProvider: storage,
});

ONNX Runtime

The NER model requires onnxruntime-web. It’s loaded automatically:
// Automatic: CDN fallback if not bundled
const anonymizer = createAnonymizer({
  ner: { mode: 'quantized' }
});
For explicit bundling:
npm install onnxruntime-web
// Will use bundled version
import 'onnxruntime-web';
import { createAnonymizer } from 'rehydra';

Browser Compatibility

BrowserMinimum VersionNotes
Chrome86+Full support
Edge86+Full support
Firefox89+Full support
Safari15.4+Full support
Required APIs:

Offline Support

After initial download, everything works offline:
// First visit: downloads ~290 MB
await anonymizer.initialize();

// Subsequent visits: instant (data cached)
await anonymizer.initialize();  // ~100ms

Memory Considerations

The NER model uses ~200-300 MB RAM when loaded. For memory-constrained environments:
// Dispose when not needed
await anonymizer.dispose();

// Or use regex-only mode
import { anonymizeRegexOnly } from 'rehydra';
const result = await anonymizeRegexOnly(text);  // ~5 MB RAM

Web Workers

For non-blocking UI, run Rehydra in a Web Worker:
// worker.ts
import { createAnonymizer } from 'rehydra';

let anonymizer;

self.onmessage = async (e) => {
  if (e.data.type === 'init') {
    anonymizer = createAnonymizer({ ner: { mode: 'quantized' } });
    await anonymizer.initialize();
    self.postMessage({ type: 'ready' });
  }
  
  if (e.data.type === 'anonymize') {
    const result = await anonymizer.anonymize(e.data.text);
    self.postMessage({ type: 'result', result });
  }
};

// main.ts
const worker = new Worker('./worker.ts', { type: 'module' });
worker.postMessage({ type: 'init' });

CSP Considerations

If using Content Security Policy, ensure these are allowed:
script-src 'wasm-unsafe-eval';  # For ONNX WebAssembly
connect-src https://huggingface.co;  # For model downloads

What’s NOT Available in Browser

The browser build excludes:
  • SQLitePIIStorageProvider (use IndexedDBPIIStorageProvider)
  • Node.js fs, path, os modules
  • Direct file system access

Next Steps