Streambert Scheduled Backup System for User Data: Architecture and Implementation

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.

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 (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 (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:

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:

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:

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 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 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →