Skip to content

Architecture

Zach Hubbard edited this page Oct 13, 2026 · 1 revision

Architecture

RerunTV has three kinds of process: the Electron main process (Node), the renderer (the on-screen "TV"), and optional isolated plugin processes for plugins that ask for them.

main/
  main.js                    Entry point: window creation, lifecycle, IPC registration
  preload.js                 contextBridge — exposes window.api.* to the renderer
  update-progress-preload.js contextBridge for the separate update-progress.html window
  config/                    config.js channels.json load/save, backups, update-time userData
                             guard · host.js config revisions + command replay · diff.js pure
                             config-summary diffing · window-state.js · window-ref.js
  plugins/                   plugins.js discovery, install/enable, capability approval ·
                             capabilities.js normalization + checked spawn/http/fs primitives ·
                             isolation.js spawns an isolated plugin as its own OS process ·
                             isolation-runtime.js the code running inside that process ·
                             rpc-channel.js RPC used across the isolation boundary
  media/                     media.js folder scanning, codec-compatibility transcode ·
                             dispatch.js routes a channel's `path` to local disk or a plugin's
                             mediaSource capability · bridge.js loopback HTTP server for a
                             mediaSource ref · protocol.js app:// scheme handler (HTTP Range
                             support) · loudness.js · cropdetect.js · ffmpeg-install.js · mime.js
  lan/                       lan.js address/port helpers · security.js pairing-code +
                             session-cookie auth · viewer-server.js LAN viewer HTTP server ·
                             viewer-projection.js config redaction for the viewer ·
                             discovery-server.js auto-discovery · startup-server.js server-mode
                             startup entry · connections.js WATCH ON OTHER DEVICES tracking ·
                             control-browse.js · asset-upload.js · tv-client.js
  updater/                   updater.js background checks, guided/silent install
                             (electron-updater) · state.js pure update-history helpers ·
                             api-cache.js disk cache for third-party API responses
  diagnostics/               diagnostics.js bounded/redacted support-bundle logging ·
                             history.js viewing-history.json (kept out of channels.json)
  library/ personal/ splicer/  library store/scan/migrate, household/DVR service, Video Splicer
  ui/                        dialogs.js file/folder pickers · scale.js interface scaling ·
                             screen-placement.js · cec.js
  util/                      http.js shared readJsonBody()/serveStaticFile() · path-safety.js
plugins/
  <plugin-id>/manifest.json  id, category, capabilities, isolation
  <plugin-id>/main.js        optional — main-process half (IPC handlers, etc.)
  <plugin-id>/renderer.js    optional — renderer half (registers into core via
                             registerChannelType/registerThemePack/registerCoreHook/...)
  <plugin-id>/settings.js    optional — the plugin's own PLUGINS-tab settings UI
  <plugin-id>/style.css      optional
renderer/
  index.html
  css/                       tokens · setup · tv · overlays · guide
  js/
    app.js                   Entry point: init, screen switching, keyboard map
    api-contract.js          Canonical window.api surface, checked against the preload
    browser-api-shim.js      Browser fallback for window.api on the LAN viewer
    core/                    state.js shared state (S) + the viewNow() viewing clock ·
                             schedule.js live-schedule/dayparting math · interstitials.js
                             deterministic break resolver (resolveBreakAt) · commands.js
                             config-edit commands + undo · schedule-query.js · channels.js ·
                             dom.js · keymap.js / key-remap.js · audio.js · config-schema.js ·
                             util.js · perf.js · tagtaxonomy.js · programming-rules.js
    playback/                core.js tuning and primary playback · breaks.js
                             commercial/interstitial state · broadcast-fx.js · order.js ·
                             recovery.js mediaSource fetch/recovery · virtual.js plugin
                             channel rendering · timemachine.js VCR shuttle · power.js ·
                             history.js · bars.js · leveler*.js · recent-channels.js ·
                             dynamic-overlays.js
    guide/                   guide.js banner + time-grid guide · genres.js · model.js ·
                             program-search.js
    timeline/                edits.js · render.js · scrubber.js
    setup/                   Setup screen (index.js entry): channels, schedule/onair,
                             settings, interstitials + flowbuilder, plugins tab, command
                             palette, keyboard nav, drag-drop, backups, overlay editors,
                             onboarding, pin-lock.js (PIN-lock parental control), splicer
    tv/                      TV mode: usage-mode.js, input.js, menu.js, setup.js, details.js
                             (`I` key), touch.js, gamepad.js, client-viewport.js, wizard.js
    remote/                  input.js, profile.js, test.js — remote-button normalization
    display/                 themes.js, eras.js, mode.js, identity.js, contrast.js, audio-output.js
    library/                 sync*.js, relink.js, channel-package.js, curation*.js, airchecks.js
    personal/                dvr.js, dvr-scheduler.js, state.js
    plugin/                  host.js plugin registry + registerX() extension points ·
                             settings-schema.js · diagnostics.js
    update/                  notice.js, progress.js, highlights.js
    ui/                      Shared component kit (button, dialog, field, tabs, toast, ...)

Core stays plugin-agnostic — nothing in main/ or renderer/js/ (outside plugin/host.js itself) names a specific plugin. Every channel and on-screen feature registers itself into core through plugin/host.js's extension points (registerChannelType, registerThemePack, registerCoreHook, registerSettingsPanel, registerInterrupt, and a few more), so installing or removing a plugin folder is the entire surface area of adding or dropping a feature.

The Control Center is one sidebar of sections (Channels, Programming, Library, Picture & Sound, Guide & Theme, Household, System, Plug-ins, Help). The page scrolls between a compact header with global search and a pinned status bar holding save state, undo/redo and Start Watching (Ctrl+Enter). Export and import live under System › Backups.

The renderer is served over a custom app:// scheme rather than file://, because Chromium refuses to load ES modules from a file:// origin. That choice cascades: a non-file:// page also can't load file:// media, so video is streamed through the same handler — which is why serveFile in main/media/protocol.js implements Range requests. The schedule math seeks constantly, so partial requests are load-bearing, not optional.

No bundler and no build step; the modules load natively.

Every "what's airing" calculation reads the clock through viewNow() rather than Date.now(), which is what makes the time machine possible — shifting one offset moves playback, the guide, dayparting, and the on-screen clocks together. Channel anchors deliberately keep using real time, since they record when a folder was scanned.

Design documents

The larger reworks each started as a numbered design document in the repository:

Next: Development · Plugin Development

Clone this wiki locally