A permanent desktop dashboard for macOS, pinned to the right edge of your widescreen monitor.
How it works · Widgets · Setup · Customization
Widescreen monitors have too much horizontal space. Most of it sits empty while you work in the center. This project turns that dead zone into a glanceable dashboard with everything you care about: calendar, tasks, music, system stats, clipboard history, recent files.
It's always visible, never steals focus, and disappears automatically when you undock your laptop.
The sidebar is a Svelte + Tailwind app running inside a Hammerspoon webview pinned to the right 300px of your external display.
┌───────────────────────────────────┐
│ Your monitor │
│ │
│ ┌───────────────────┐ ┌───────┐ │
│ │ App windows │ │Sidebar│ │
│ │ (2260px usable) │ │(300px)│ │
│ │ │ │ │ │
│ └───────────────────┘ └───────┘ │
└───────────────────────────────────┘
hs.screen.watcher detects dock/undock and auto-hides the sidebar when your external monitor disconnectswebkit.messageHandlers, Lua pushes data back via evaluateJavaScript()http://localhost:5174 (Vite dev server with HMR)bun run build, then Hammerspoon loads file:///path/to/dist/index.html directly| Widget | Data source | Update interval |
|---|---|---|
| Calendar | Static (date + mini month grid) | On load |
| Todoist | Todoist API v1 (direct fetch) | 2 min |
| Now Playing | hs.spotify |
5s |
| Clipboard | hs.pasteboard |
2s |
| Screenshots | ~/Desktop/Screenshot*.png |
30s |
| Downloads | ~/Downloads (recent files) |
30s |
| Quick Note | Saves to Obsidian vault via Lua | On submit |
| System Stats | hs.host.cpuUsage, hs.host.vmStat, df, hs.battery |
10s |
| Top Processes | ps aux |
10s |
brew install --cask hammerspoon)git clone https://github.com/sasha-computer/sidebar.git
cd sidebar
bun install
Edit hammerspoon/sidebar.lua:
SIDEBAR_WIDTH (default: 300)EXTERNAL_DISPLAY (default: "LG UltraFine") - change to match your monitor nameNOTES_PATH - path to your notes directoryUSE_DEV - true for dev server, false for production buildEdit hammerspoon/init.lua:
io.popen line with your own token source, or hardcode it (not recommended).ln -sf "$(pwd)/hammerspoon/init.lua" ~/.hammerspoon/init.lua
bun run dev # Start Vite on :5174
# Hammerspoon auto-reloads when .lua files change
bun run build # Outputs to dist/
# Set USE_DEV = false in sidebar.lua
# Reload Hammerspoon
CapsLock is remapped to Hyper (ctrl+alt+cmd+shift) via Karabiner. Hammerspoon binds:
| Shortcut | Action |
|---|---|
| Hyper + Left | Left half (sidebar-aware) |
| Hyper + Right | Right half (sidebar-aware) |
| Hyper + Up | Maximize (sidebar-aware) |
| Hyper + Down | Center 60% |
| Hyper + Return | Toggle fullscreen |
| Hyper + S | Toggle sidebar |
When undocked (no external monitor), splits use the full screen width.
src/widgets/MyWidget.sveltesrc/lib/stores.ts if neededsrc/App.sveltehammerspoon/sidebar.lua and push data via pushToWebview()Colors are defined in src/app.css using Catppuccin Mocha. Change the @theme block to use your palette.
Change EXTERNAL_DISPLAY in sidebar.lua to match your monitor's name. Find yours with:
hs -c 'for _, s in ipairs(hs.screen.allScreens()) do print(s:name()) end'
hs.webview (WKWebView)MIT