# Streambert Watch History Tracking Implementation: A Technical Deep Dive

> Explore the Streambert watch history tracking implementation using a structured localStorage schema. Discover how playback progress and completed episodes are managed efficiently.

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

---

**Streambert persists watch history using a structured localStorage schema that tracks playback progress, completed episodes, and chronological history through four specific keys managed by a centralized storage utility.**

Streambert implements a lightweight yet robust watch history tracking system using the browser's `localStorage` API. The implementation centers around a key registry defined in [`src/utils/storage.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/storage.js) that coordinates data persistence across the Electron main and renderer processes. This architecture enables real-time progress updates, automatic "watched" status detection, and seamless backup functionality without external database dependencies.

## Core Storage Schema and Architecture

### The STORAGE_KEYS Registry

All watch-related data keys are centrally declared in **[`src/utils/storage.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/storage.js)** (lines 35-50) within the exported `STORAGE_KEYS` object. This registry prevents key collisions and provides a single source of truth for storage identifiers throughout the application.

```javascript
// src/utils/storage.js – central key registry
export const STORAGE_KEYS = {
  WATCH_PROGRESS: "progress",
  WATCHED: "watched",
  HISTORY: "history",
  WATCHED_THRESHOLD: "watchedThreshold",
  // …other unrelated keys
};

```

### Data Structure Overview

The system utilizes four primary keys to maintain comprehensive watch state:

- **`WATCH_PROGRESS`** (`"progress"`): Stores the current playback position in seconds for the active episode
- **`WATCHED`** (`"watched"`): Maintains an object mapping episode IDs to boolean `true` values for completed content
- **`HISTORY`** (`"history"`): Contains a chronological array of episode IDs in reverse order (most recent first)
- **`WATCHED_THRESHOLD`** (`"watchedThreshold"`): Defines the percentage (default **95%**) of an episode that must be viewed to trigger automatic "watched" status

## Real-Time Progress Tracking

### IPC Communication Flow

When the video player reports a new playback position, the main process sends updates via the `"update-progress"` IPC channel. According to **[`src/ipc/player.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/player.js)**, the main window emits progress events containing the current percentage and download status:

```javascript
// src/ipc/player.js – update-progress handler (excerpt)
mw.webContents.send("update-progress", {
  percent,
  label: `Downloading… ${mb} MB ${totalMb}`,
});

```

The renderer-side listener in **[`src/preload.js`](https://github.com/truelockmc/streambert/blob/main/src/preload.js)** forwards these events to the UI layer, enabling the storage utility to persist positions using `storage.set(STORAGE_KEYS.WATCH_PROGRESS, currentSeconds)`.

### Automatic Watched Status Detection

When playback reaches the `WATCHED_THRESHOLD` (default 95% of total duration), Streambert automatically marks the episode as fully watched. The implementation updates both the `WATCHED` object and the `HISTORY` array:

```javascript
// Mark as watched when threshold reached
storage.set(STORAGE_KEYS.WATCHED, {
  ...storage.get(STORAGE_KEYS.WATCHED),
  [episodeId]: true,
});

// Update chronological history
const hist = storage.get(STORAGE_KEYS.HISTORY) || [];
hist.unshift(episodeId);
storage.set(STORAGE_KEYS.HISTORY, hist);

```

## Managing Watch History Data

### Retrieving Watch History

To display a "Recently Watched" list, UI components import the storage utility and retrieve the chronological history array. The most recent entries appear at the beginning of the array due to the `unshift` operation used during updates.

```javascript
import { storage, STORAGE_KEYS } from "./utils/storage";

// Get the chronological watch history
const history = storage.get(STORAGE_KEYS.HISTORY) || [];

// Show the last 5 entries
history.slice(0, 5).forEach((episodeId) => {
  console.log("Recently watched:", episodeId);
});

```

### Manually Marking Episodes as Watched

Applications can programmatically mark content as watched using the same pattern as the automatic threshold detection:

```javascript
import { storage, STORAGE_KEYS } from "./utils/storage";

function markAsWatched(episodeId) {
  const watched = storage.get(STORAGE_KEYS.WATCHED) || {};
  watched[episodeId] = true;
  storage.set(STORAGE_KEYS.WATCHED, watched);

  // Also add to history
  const history = storage.get(STORAGE_KEYS.HISTORY) || [];
  history.unshift(episodeId);
  storage.set(STORAGE_KEYS.HISTORY, history);
}

```

## Clearing and Resetting Watch Data

Streambert provides a complete data purge mechanism through the IPC handler **`clear-watch-data`** implemented in **[`src/ipc/downloads.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/downloads.js)** at line 909. This handler iterates through all watch-related keys and removes them from `localStorage`:

```javascript
ipcMain.handle("clear-watch-data", async () => {
  for (const key of ["progress", "watched", "history", "watchedThreshold"]) {
    storage.remove(key);
  }
});

```

The frontend invokes this handler through the preload bridge exposed in **[`src/preload.js`](https://github.com/truelockmc/streambert/blob/main/src/preload.js)**:

```javascript
// src/preload.js – expose clearWatchData to the renderer
clearWatchData: () => ipcRenderer.invoke("clear-watch-data"),

```

Settings UI components call `window.electron.clearWatchData()` when users request to clear their history:

```javascript
// From a Settings component
window.electron.clearWatchData().then(() => {
  alert("Watch history cleared!");
});

```

## Backup and Restore Integration

Watch history survives application reinstalls through the backup system defined in **[`src/utils/backup.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/backup.js)** (lines 8-28). This file explicitly includes the watch-related keys—`"watched"`, `"progress"`, and `"history"`—in the exportable data set, ensuring user progress continuity across devices or application migrations. When users export their Streambert configuration, these keys serialize to JSON and restore cleanly on import.

## Summary

- **Centralized key registry**: [`src/utils/storage.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/storage.js) defines `STORAGE_KEYS` to maintain consistent localStorage identifiers for watch data
- **Real-time IPC updates**: The `"update-progress"` channel in [`src/ipc/player.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/player.js) coordinates playback position tracking between main and renderer processes
- **Threshold-based completion**: Episodes automatically mark as watched at 95% completion, updating both the watched set and chronological history
- **Complete data management**: The `clear-watch-data` handler in [`src/ipc/downloads.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/downloads.js) provides atomic deletion of all watch-related entries
- **Persistence across installs**: [`src/utils/backup.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/backup.js) includes watch data in export/import operations, ensuring state survival through reinstalls

## Frequently Asked Questions

### Where does Streambert store watch history data?

Streambert stores all watch history data in the browser's `localStorage` under specific keys defined in [`src/utils/storage.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/storage.js). The data includes playback progress (seconds), watched episode IDs, chronological history arrays, and the completion threshold percentage. This design ensures data persistence without requiring external database infrastructure.

### What percentage of an episode must be watched to mark it as complete?

By default, Streambert marks an episode as watched when the user reaches **95%** of the total duration. This threshold is configurable via the `WATCHED_THRESHOLD` key in `localStorage`, allowing users or developers to adjust the completion criteria between 0-100%.

### How can I programmatically clear watch history in Streambert?

Invoke the `clear-watch-data` IPC handler exposed through the Electron context bridge. The frontend calls `window.electron.clearWatchData()`, which triggers the handler in [`src/ipc/downloads.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/downloads.js) to delete the `"progress"`, `"watched"`, `"history"`, and `"watchedThreshold"` keys from localStorage, effectively resetting all watch-related data.

### Is watch history included when backing up Streambert data?

Yes. The backup utility in [`src/utils/backup.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/backup.js) explicitly includes the watch-related keys (`"watched"`, `"progress"`, `"history"`) in the export schema (lines 8-28). This ensures that when users export their settings and data, their watch progress and history serialize to the backup file and restore correctly on import.