# Streambert Scheduled Backup System for User Data: Architecture and Implementation

> Learn how Streambert's scheduled backup system synchronizes user data including preferences and watchlists using a whitelist approach. Explore its architecture and implementation.

- Repository: [true_lock/streambert](https://github.com/truelockmc/streambert)
- Tags: architecture
- Published: 2026-05-21

---

**Streambert's scheduled backup system uses a whitelist-based approach to serialize user preferences, watchlists, and UI state from localStorage into JSON files, triggered by Electron's main process and handled in [`src/utils/backup.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/backup.js).**

Streambert is an Electron-based desktop application for streaming and downloading media, and its **Streambert scheduled backup system user data** functionality ensures that watchlists, viewing progress, and interface customizations survive reinstalls or device migrations. The implementation relies on a controlled registry of storage keys and a strict separation between renderer process data collection and main process file I/O. This article examines the source code architecture, key functions, and integration points that make automatic user data preservation possible.

## Core Architecture of the Backup System

### The BACKUP_KEYS Single Source of Truth

In [`src/utils/backup.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/backup.js) (lines 5-53), the system defines a centralized registry named `BACKUP_KEYS` that enumerates every `localStorage` entry eligible for backup. This array lists all keys prefixed with `streambert_`, including watch history, UI layout configurations, player preferences, subtitle settings, download paths, appearance options, and notification preferences. By maintaining this whitelist in one location, developers ensure that any new persistent setting is automatically included in future backups without scattering key names across the codebase.

### Data Collection with collectBackupData()

The `collectBackupData()` function (lines 55-69) iterates over the `BACKUP_KEYS` array, reads each corresponding value from `localStorage`, parses the JSON, and assembles a plain JavaScript object containing only the defined keys. Invalid or unparsable entries are silently skipped rather than aborting the entire operation, ensuring that a single corrupted preference does not compromise the backup integrity. This method returns a sanitized data payload ready for serialization.

### Safe Restoration via restoreBackupData()

Restoration is handled by `restoreBackupData(data)` (lines 71-83), which validates the incoming object before writing each key back to `localStorage` under the `streambert_` prefix. This validation step prevents arbitrary key injection and ensures that only expected data shapes are reintroduced into the application state. The function guarantees atomicity in restoration—either the recognized keys are restored, or the operation fails gracefully without corrupting existing data.

## Electron Main Process Integration

### Scheduled Backup Trigger Mechanism

The renderer process registers for backup events in [`src/App.jsx`](https://github.com/truelockmc/streambert/blob/main/src/App.jsx) (lines 73-84) by listening for the `onScheduledBackupRequested` event from the main process. When triggered—typically by a cron-like scheduler configured in the application's settings—the handler loads user-defined backup preferences via `window.electron.getScheduledBackupSettings()`, checks that both `scheduledBackupEnabled` and `scheduledBackupPath` are valid, then invokes `collectBackupData()` to gather the current state. The resulting JSON payload is forwarded to the main process through `window.electron.performScheduledBackup({ data, settings })`.

### IPC Communication Flow

The backup system relies on three critical Electron IPC methods:

- **`getScheduledBackupSettings()`**: Retrieves the user's scheduled backup configuration, including the `scheduledBackupEnabled` boolean and `scheduledBackupPath` string.
- **`performScheduledBackup({ data, settings })`**: Accepts the serialized user data and writes it to the specified filesystem path, typically as a timestamped `.json` file.
- **`readBackupFile(filePath)`**: Invoked during restoration, this main-process method reads the backup file from disk and returns the parsed JSON to the renderer.

This architecture respects Electron's security model by keeping filesystem access in the main process while limiting the renderer to data collection and validation.

## Implementation Examples

### Manually Triggering a Backup Export

The following pattern demonstrates how the Settings page initiates an immediate backup:

```javascript
import { collectBackupData } from './utils/backup';

async function exportBackup() {
  // Gather all registered keys from localStorage
  const data = collectBackupData();
  
  // Retrieve user-configured backup destination
  const settings = await window.electron.getScheduledBackupSettings();
  
  if (settings?.enabled && settings?.path) {
    await window.electron.performScheduledBackup({ data, settings });
    console.log('Backup persisted to:', settings.path);
  }
}

```

### Importing and Restoring User Data

When a user selects a previous backup file through the Settings interface, the restoration flow executes:

```javascript
import { restoreBackupData } from './utils/backup';

async function importBackup(filePath) {
  // Main process handles filesystem access
  const backup = await window.electron.readBackupFile(filePath);
  
  if (backup) {
    restoreBackupData(backup);
    // Force UI refresh to reflect restored state
    window.location.reload();
  }
}

```

### Setting Up the Automated Scheduled Listener

The root component establishes the backup listener during mount:

```jsx
useEffect(() => {
  if (!window.electron?.onScheduledBackupRequested) return;
  
  const handler = window.electron.onScheduledBackupRequested(async () => {
    try {
      const settings = await window.electron.getScheduledBackupSettings();
      if (!settings?.enabled || !settings?.path) return;
      
      const data = collectBackupData();
      await window.electron.performScheduledBackup({ data, settings });
    } catch (error) {
      // Silent failure prevents backup errors from blocking the application
    }
  });
  
  return () => window.electron.offScheduledBackupRequested(handler);
}, []);

```

## Key Design Advantages

- **Single source of truth**: The `BACKUP_KEYS` array in [`src/utils/backup.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/backup.js) guarantees that adding a new persistent setting requires updating only one registry, eliminating the risk of missing keys during export.
- **Namespace isolation**: The `streambert_` prefix prevents collisions with other applications that might share the same `localStorage` domain.
- **Graceful degradation**: Both collection and restoration ignore malformed entries, ensuring that data corruption in one key does not invalidate the entire backup.
- **Security boundaries**: File I/O remains restricted to the Electron main process, while the renderer handles only data serialization and validation, adhering to least-privilege principles.

## Summary

- **`BACKUP_KEYS`** in [`src/utils/backup.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/backup.js) defines the canonical list of user data keys eligible for backup.
- **`collectBackupData()`** serializes localStorage values into a portable JSON structure while skipping invalid entries.
- **`restoreBackupData()`** validates and reinstates backed-up values without allowing arbitrary key injection.
- **[`src/App.jsx`](https://github.com/truelockmc/streambert/blob/main/src/App.jsx)** registers the `onScheduledBackupRequested` listener to automate backups based on user-defined schedules.
- The system uses `scheduledBackupEnabled` and `scheduledBackupPath` settings to control automation, stored alongside other user preferences under the `streambert_` prefix.

## Frequently Asked Questions

### What specific user data does Streambert include in scheduled backups?

The backup captures all keys defined in the `BACKUP_KEYS` array, which includes watchlists, viewing progress, UI layout states, player preferences (volume, playback speed), subtitle configurations, download directory paths, appearance themes, and notification settings. Any data stored in `localStorage` with the `streambert_` prefix that is registered in this whitelist is preserved.

### How does the scheduled backup trigger automatically without user intervention?

The Electron main process maintains a timer or cron-like scheduler configured according to the user's `scheduledBackupEnabled` preference. When the interval elapses, the main process emits the `onScheduledBackupRequested` event to the renderer. The handler in [`src/App.jsx`](https://github.com/truelockmc/streambert/blob/main/src/App.jsx) responds by collecting data and returning it via `performScheduledBackup`, where the main process writes the file to `scheduledBackupPath`.

### Can backup files be transferred between different operating systems or installations?

Yes. The backup format is a standard JSON object containing key-value pairs from `localStorage`. Since the restoration logic in `restoreBackupData()` only processes recognized `BACKUP_KEYS`, the file is portable across Windows, macOS, and Linux installations of Streambert, provided the application versions support the same key schema.

### What happens if a backup file becomes corrupted or contains invalid JSON?

During restoration, `collectBackupData()` and `restoreBackupData()` both implement error handling that silently skips unparsable or invalid entries. If a backup file is malformed at the root level, `window.electron.readBackupFile()` will return null or throw, which the import handler catches to prevent application crashes. Users can then attempt to restore from an alternative backup file without data loss.