Beacon is a communication cockpit for the web-based communication services you actually use — WhatsApp, Telegram, Gmail, Google Messages, Messenger, Google Calendar, ChatGPT, plus Slack, Discord, Signal, Instagram, X, LinkedIn, Outlook, and Teams available to enable in Settings — each isolated, pre-loaded, and always warm. Open as many at once as you want in a Wave-Terminal- style tiling layout: drag tiles to dock them anywhere (or use the explicit split buttons), resize freely, magnify one to full-screen, each with its own back/forward/reload chrome. Tabs are isolated profiles — open the same service logged into different accounts in different tabs, each with its own tile layout and an optional emoji icon. Each service can be zoomed independently (e.g. WhatsApp at 90%, Messenger at 150%) and can present a different browser identity (desktop Chrome, mobile Android/iOS, or a custom user-agent string) — useful both for sites with distinct mobile/desktop layouts and for clearing "unsupported browser" warnings some sites show against Electron's default user-agent. Set a static or animated wallpaper that shows through the dock, dialogs, and the services themselves, with adjustable transparency and fit (fill/fit/stretch/ center/tile). The app icon doubles as a menu for Settings, Always on Top, and an About dialog; Beacon can also live in the system tray, minimizing or closing to it instead of quitting. Each dock icon's outline and fill color can be customized independently for contrast against any wallpaper, and the dock grows icons under the cursor like the macOS dock. The flagship feature: chat-bubble notifications — a small always-on-top, draggable bubble appears when a service gets a new message (Messenger-chat-heads-style), with a customizable chime, and clicking it pops open a real mini-browser of that service right next to it to read/reply without switching to Beacon at all. No accounts, no cloud backend, no telemetry: everything lives locally on your machine.
CLAUDE.md— conventions and instructions for working on this codebase (start here before making changes).docs/PLAN.md— the original single-view V1 plan.docs/PLAN_TILING.md— the tiling-layout pivot plan.docs/PLAN_WEBVIEW_MIGRATION.md— the<webview>migration + tabs/title-bar/wallpaper plan.docs/ARCHITECTURE.md— how the app is actually built today, including deviations from all three plans above and the technical detail behind every known gap.TODO.md— the actionable list of what's missing or rough right now.NOT_FOR_V1.md— features intentionally out of scope (and the deliberate scope reversal — see its "scope history" note).
- Node.js 20+ (developed against Node 24 / Electron 42's bundled Node ABI)
- Windows, macOS, or Linux
npm install # also rebuilds better-sqlite3's native binding for Electron's Node ABI
npm run dev # launches the app with hot reload| Script | What it does |
|---|---|
npm run build |
Production build of main, preload, and renderer into out/ |
npm run typecheck |
Type-checks renderer and main/preload independently (they use separate tsconfigs) |
npm run lint |
ESLint over the whole project |
npm run package |
Builds, then packages an installer for the current OS into release/ |
npm run package:win / :linux / :mac |
Same, targeting a specific OS |
src/
├── shared/ Types, IPC channel constants, tab-aware session partition naming, pure tree ops
├── main/ Electron main process: frameless window + custom titlebar config, <webview>
│ attachment security boundary, SQLite persistence, autostart, tray, wallpaper/
│ notification-sound protocols, chat-bubble notification windows
├── preload/ contextBridge surface exposed to the renderer as window.beaconAPI
└── renderer/ React UI: title bar/tabs, dock, tiling layout, the <webview> warm pool, settings,
wallpaper, Zustand stores, Tailwind styling
Each service runs in its own <webview> (a real DOM element, not a separate native view — this
matters: it's what lets Settings/tooltips render above it, drag-and-drop receive events, and the
wallpaper show through it), with its own per-tab session partition
(persist:tab-<tabId>-service-<serviceId>) so logins/cookies survive restarts and never leak
between services or between tabs of the same service. Enabled services stay warm in the
background regardless of whether they currently have an open tile, so notifications keep arriving
— for the active tab by default, or every tab if you turn on "keep all tabs warm" in Settings.
The center area is a tiling layout (ported tree mechanics from Wave Terminal, rebuilt on Zustand
instead of Jotai) — click a dock icon to open a service as a tile, drag tiles by their header to
dock them against any edge of another tile or swap positions (or use the explicit split buttons),
drag the thin dividers to resize, and magnify a tile to fill the layout. Tabs (top bar) are
independent profiles, each with their own tile arrangement and logins. See
docs/ARCHITECTURE.md for how all of this actually works under the hood.
See TODO.md for the actionable list (Inter isn't self-hosted, macOS/Linux are
untested — including the title bar, wallpaper, tray, and chat-bubble features, etc.) and
docs/ARCHITECTURE.md for the technical reasoning
behind each one.