Makes local dev work on Windows: cross-env for the server dev port, pnpm --parallel to run server+web together (replacing the POSIX-only '&'), PowerShell setup docs, engines widened to Node >=20, and a Node 20 + 24 CI matrix.
CI keeps a stable required 'Build & test' status via an aggregate gate job so the matrix rename doesn't drop the context the main ruleset requires.
Co-authored-by: BadAtCaptchas <2359196+BadAtCaptchas@users.noreply.github.com>
Co-authored-by: Jannis Braun <151788261+TheZwiss@users.noreply.github.com>
Three changes to cut deploy time:
1. deploy.sh: Pi and VM deploy concurrently (wall time = max, not sum)
2. deploy.sh: Build cache capped at 2GB instead of nuked after 24h,
so pnpm install layer is reused between deploys
3. Dockerfile: runtime stage uses --prod (skip devDeps). Moved tsx
from devDependencies to dependencies since it's used in CMD.
Fixes system-wide freeze when Accessibility permissions are enabled.
Two changes to libuiohook/src/darwin/input_hook.c via pnpm patch:
- Switch kCGEventTapOptionDefault to kCGEventTapOptionListenOnly
- Strip mouse move/drag/scroll/left/right-click events from mask
Listen-only taps are passive observers that cannot freeze the system.
Keeps keyboard events and mouse buttons 3+ for PTT side buttons.
Windows and Linux native paths are completely untouched.
Installs uiohook-napi for OS-level non-consuming input hooks, creates
KeybindManager class that receives keybind configs from the renderer,
matches the OS-wide key/mouse event stream, and sends matched actions
back via IPC. Exposes syncKeybinds, onKeybindAction, onAccessibilityStatus,
onKeybindHookError, and checkAccessibility APIs through the preload bridge.
Screen sharing with audio captured the app's own voice playback, causing
users to hear themselves echoed back. Fixed via two layers:
- Add restrictOwnAudio constraint (Chrome 141+/Chromium 144) to exclude
the app's own audio from system audio capture
- Add shareAudio toggle so users can disable system audio entirely
- Remove outdated macOS audio block (now supported via ScreenCaptureKit)
- Upgrade Electron 33→40 (Chromium 130→144) so restrictOwnAudio works
natively in the desktop app
- Add NSAudioCaptureUsageDescription for macOS 14.2+ audio capture
- Add GTK 3 fallback for Linux GNOME compatibility (Electron 36+)
- Dev/prod URL auto-detection (Vite 5173 in dev, server 3000 in prod)
- Typed IPC bridge via preload (notifications, badge, window controls, updates, deep links)
- Native OS notifications via NotificationController with window focus suppression
- Auto-update via electron-updater with UpdateToast UI
- Deep linking (backspace:// protocol) for macOS and Windows/Linux
- Window state persistence (position, size, maximize across restarts)
- Tray icon with graceful fallback when icon asset missing
- Suppress PWA service worker polling/reloads inside Electron
- Platform detection layer (isElectron, getElectronAPI)
- Root workspace scripts (dev:desktop, build:desktop)
- Document BACKSPACE_URL and BACKSPACE_UPDATE_URL env vars
Avatars/banners now resize to max 512px/1920px and convert to WebP before
upload (zero server cost). Chat image uploads generate an 800px-wide WebP
thumbnail via Sharp; the feed shows the thumbnail, click opens the full-res
original. Adds lazy loading to avatars. Federation-compatible: remote
instances without this feature fall back gracefully.
Wire react-easy-crop into CreateSpace so users can crop and zoom before
uploading a space icon. Adds reusable ImageCropModal component and
canvas crop utility for future use in space settings and avatar editing.
- Add Backspace-design-prototype.html: finalized "Aether Drift" design
language with warm matte surfaces and subtle frosted glass accents
- Update CLAUDE.md with DESIGN SYSTEM section and remove Discord clone references
- Rename all Opencord references to Backspace across the full codebase
- Archive outdated design experiments and Discord-specific assets
- Add science-backed accessibility fallback (prefers-reduced-transparency)
- Add MarkdownRenderer with syntax-highlighted code blocks (prism-react-renderer),
GFM tables, and Discord-style theming
- Add MentionBadge that resolves user IDs to display names with role colors
- Add MentionPopover autocomplete triggered by @ in MessageInput
- Fix mention:// URL sanitization — allowlist the scheme in urlTransform so
react-markdown v9 passes it through to the component override
- Highlight messages that mention the current user (amber border)
- Bump rate limit from 60 to 200 req/min
Inject @sapphi-red/web-noise-suppressor into AudioManager's input pipeline
as a toggleable AudioWorkletNode. The worklet is loaded lazily on first
enable, then kept alive — toggling bypasses by rewiring the graph without
destroying the WASM instance. Browser NS is forced off when RNNoise is
active to avoid double-processing. InputGain forced to stereo up-mix to
prevent mono-left-only output from the worklet. Also wires Phase 2 output
device routing (setSinkId) into AppLayout/ChannelSidebar.
Phase 1 - Feature Repair:
- Fix member kick/leave: add missing db.delete() call in servers.ts
- Stabilize invite codes: return existing code instead of regenerating
- Fix user search: use LIKE instead of exact match in social.ts
- Wire DM button on FriendsPage to create/navigate to DM channels
- Add cancel outgoing friend request (DELETE endpoint + frontend)
- Add accept/decline friend request actions with WS real-time events
- Fix replyToId persistence in message creation
- Hydrate reactions and replyTo in message queries
- Add joinByCode to API client and serverStore
- Add friend_request_received/accepted WebSocket events
Phase 2 - Discord UI Overhaul:
- Remove stray borders between layout columns
- Replace shadow-sm with shadow-header on content headers
- Replace all bg-gray-*/text-gray-* with Discord color tokens
- Ensure flat color contrast (#1E1F22, #2B2D31, #313338)
Testing:
- Set up vitest + @testing-library/react + jsdom
- Add 17 tests across InviteModal, JoinServer, FriendsPage (all passing)
- Fix vite resolve.extensions to prefer .tsx over stale .js files