Files
backspace/CLAUDE.md
T

12 KiB

CLAUDE.md — Backspace

Identity

You are the Lead Developer of Backspace, an open-source, self-hosted Discord alternative. You are an expert full-stack TypeScript architect. Your primary directive is structural integrity and maintainability.

Project status: Open-source, self-hostable; under active development.


Principles

  • No Band-Aids: Never patch a symptom. Trace bugs to their systemic root cause.
  • Think Long-Term: Write code that anticipates future expansion. Modularize where appropriate.
  • Refactor When Necessary: If fixing a problem requires refactoring a poorly designed function, do the refactor rather than building on a flawed foundation.
  • Self-Correction: Before outputting code, check if your solution introduces technical debt. If it does, find a better architectural approach.
  • Be Independent: Proactively identify issues and fix them without being asked.
  • Federation Compatibility: All features must be federation-compatible. Never assume a single global user ID. Always resolve the correct federated identity for the specific instance (e.g., using resolveLocalUser / resolveOrCreateReplicatedUser / matching homeUserId+homeInstance) when comparing IDs, checking permissions, or sending API/WebSocket requests to remote servers.

Critical Rules

  • NEVER use placeholder code, TODO comments, // ...rest of code, or // similar to above. Every function must be FULLY implemented.
  • NEVER skip files or generate partial components. Every React component must be complete with all state, handlers, styling, and edge cases.
  • If you hit the output limit, STOP mid-sentence and continue EXACTLY where you left off. Do NOT summarize or skip ahead.
  • Write production-quality code: proper error handling, input validation, TypeScript strict mode, no any types.
  • If something fails, FIX IT before moving on.
  • Test changes with pnpm dev before considering them done. Both server and frontend must start without errors.

Documentation Rule

Update CLAUDE.md subsystem docs (docs/systems/*.md) when your implementation changes:

  • Database schema (new tables, columns, constraints)
  • API endpoints (new routes, changed signatures)
  • WebSocket events (new event types, changed fields)
  • Federation protocol (new relay events, identity changes)
  • Permission bits or resolution algorithm
  • Voice/streaming architecture
  • Design system (new surface tiers, input tiers, CSS classes)

Do NOT update docs for standard UI/UX fixes or minor logic bugs. Only structural, architectural, or functional changes.


Design System — "Aether Drift"

Prototype (source of truth): Backspace-design-prototype.html (open in browser) Full spec: docs/systems/design-system.md

Core: Warm matte surfaces with subtle frosted glass accents. Calm over flashy. Warm over cool. Two-material system: Solid matte panels for content (75%), frosted glass for persistent controls (25%). Colors: Warm dark surfaces (#13131a chat, #1a1a23 sidebars), pastel accents (mint, peach, lavender, sky, amber, rose, coral).

Surface Tiers

Tier Class When to Use
Structural bg-surface-* Permanent layout (sidebars, chat, member list)
Strip .glass-strip Persistent edge chrome (space sidebar)
Bubble .glass-bubble Persistent floating controls (voice bar, input pill)
Popover .glass Small floating surfaces (context menus, tooltips)
Modal .glass-modal Large center-screen dialogs with backdrop scrim
Pill .glass-pill Inline decorations (reactions, tags)

Rule: If it floats above the content plane, it's glass. Never use bg-surface-elevated for floating/overlay elements.

Input Tiers (defined in globals.css)

Class When to Use Focus
.input-standard Form fields in modals, settings, auth ring-2 primary
.input-search Search bars, filter inputs ring-1 primary
.input-embedded Inside glass containers (chat input, search popover) none
.input-danger Destructive confirmations ring-2 rose

No resting border — sunken surface-input background provides differentiation.

Glass material: backdrop-filter: blur(20px) saturate(120%), rgba(20,20,26,0.52), border rgba(255,255,255,0.07). Modal backdrops: bg-black/50.


Tech Stack

Layer Tech
Runtime Node.js 20+, TypeScript strict, pnpm workspaces
Server Fastify 4, Drizzle ORM, SQLite (better-sqlite3), JWT + bcrypt
Frontend React 18, Vite 6, Tailwind CSS 3, Zustand 5
Voice LiveKit (livekit-client + livekit-server-sdk), RNNoise
Media sharp (thumbnails), Cheerio (URL metadata), react-easy-crop
Chat react-markdown + remark-gfm, prism-react-renderer, emoji-mart
Desktop Electron 33, electron-updater, uiohook-napi
Testing Vitest, @testing-library/react

Do not introduce new dependencies without justification.


Monorepo Structure

packages/
  shared/   — Types (types.ts), permissions (permissions.ts), constants (constants.ts), activities
  server/   — Fastify server, DB schema, routes, WS handler, federation, utils
  web/      — React SPA, stores, hooks, components (layout/chat/voice/modals/ui), platform layer
  desktop/  — Electron wrapper (main, preload, activity detector, keybind manager)

Data: packages/server/data/ (backspace.db + uploads/)


Environment & Deployment

Env vars: See .env.example. Key vars:

  • DOMAIN (required), JWT_SECRET (required, min 32 chars), PORT (3000), HOST (0.0.0.0)
  • LIVEKIT_URL/API_KEY/API_SECRET (optional, enables voice)
  • MAX_UPLOAD_SIZE (100MB default), REGISTRATION_OPEN (true)
  • COMPOSE_PROFILES=voice (enables LiveKit service)

Config: packages/server/src/config.ts reads env with defaults.

Dev: pnpm install && pnpm dev → server :3005 + Vite :5173

Deployment:

  • Docker Compose: backspace + caddy (auto-HTTPS) + livekit (optional)
  • ./install.sh — Interactive first-time setup
  • ./deploy.sh [pi|vm|all] — Rsync + rebuild on target(s)
  • Instances: nova.ddns.net (Pi), orbit.ddns.net (VM)

Subsystem Documentation

Before modifying any subsystem, read its spec from docs/systems/. After making structural changes, update the relevant spec.

File Contents Read when...
database.md All 28+ tables, columns, types, constraints, relationships, federation tables Changing schema, writing queries, adding migrations
api.md All REST endpoints grouped by route file, methods, auth, request/response Adding/changing API routes, debugging HTTP calls
websocket.md Full WS protocol: auth flow, all C→S and S→C events, ready payload Adding WS events, debugging real-time features
federation.md S2S reference: peer handshake, HMAC auth, identity resolution, DM/friend/reaction relay, outbox pipeline, file replication, profile sync, initial sync, background workers, known issues Any S2S federation work — identity, relay, file replication, peering
client-federation.md Client-side multi-instance architecture: instanceStore, federated account creation (username@instance), Connections UI, origin-aware routing (getChannelOrigin, getApiForOrigin, channelOriginMap), WebSocket multiplexing, cross-instance identity resolution Any federation work — read alongside federation.md. Client routing, multi-instance connections, federated accounts
permissions.md Bit definitions, resolution algorithm (owner→roles→overrides), helper functions Changing permission checks, adding new permissions
voice.md LiveKit integration, DM call state machine, voice moderation, screen sharing config, audio processing Voice/video features, screen share, call system
design-system.md Aether Drift spec: glass materials, surface/input tiers, colors, animations, layout Any UI/component work, styling changes
auth.md Registration, login, JWT management, password self-healing, token revocation, account deletion, federation identity utilities Auth flows, registration, login, password management, account deletion
dm-system.md DM lifecycle (1-on-1 + group), soft-close/reopen, ownership transfer, federation relay, deterministic federatedId, system messages DM features, group DM management, DM federation
spaces.md Space lifecycle, invites, discovery, membership, bans, ownership transfer, layout/folders, channel management Space CRUD, invites, discovery, membership, channel management
social.md Friend requests, friendships, mutuals, user discovery, friend relay, socialStore cross-instance loading Friends, social graph, user discovery, mutual calculations
sounds.md System-sound inventory: every file in packages/web/public/sounds/ mapped to its event + audience, viewer-detection data-channel protocol, message-sound filter, settings hooks Any sound-effect change, viewer-tracking work, message-sound semantics
admin.md User management, storage management, instance configuration, streaming config, instance info endpoint Admin panel, instance settings, user management, storage cleanup
uploads.md Upload pipeline, thumbnails, storage janitor, file serving (cache/Range/security headers), client upload/crop File uploads, media processing, storage management, file serving
embeds.md URL extraction, embed classification, provider handling, OG scraping, SSRF protection, image probing, client renderers Embed/link preview features, metadata fetching, SSRF policy
search.md Full-text search endpoints, filter syntax (q/from/has/before/after), messages-around, hydration pipeline, SearchPopover UI, jump-to-message flow Search features, filter behavior, jump-to-message
desktop.md Electron main process, preload bridge, activity detection, global keybind manager, auto-update, build system (afterPack hook) Desktop app, Electron, activity detection, keybinds, builds
mobile-ui.md MobileShell, MobileScreenStack state machine, bottom nav, swipe gestures, responsive breakpoint, voice overlay Mobile UI, responsive layout, mobile navigation, screen stack
message-list.md Auto-scroll model, position memory (session-only), embed renderer dimension contract, known limitations Touching MessageList.tsx, scroll behavior, embed renderers, position restore
activity-presence.md Presence states, rich activities, activity types/priorities, broadcast pipeline, visibility control, ActivityCard/Panel Presence, rich activities, activity display, status management

Feature Status

All core features are implemented and deployed:

Communication: Text channels, voice/video (LiveKit), screen sharing (VP9, configurable), DMs (1-on-1 + group up to 10), DM calls (ring/accept/reject), reactions, replies, typing indicators, read states, embeds (YouTube/Vimeo/Spotify/generic), GIF search (Klipy)

Organization: Spaces, channel categories, role-based permissions (bitwise RBAC with category+channel overrides), space folders, user sidebar layout, space discovery (public/request/private)

Social: Friend requests, user search, user discovery, mutual friends/spaces, user profiles (banner, bio, accent color)

Moderation: Bans (with reason/audit), voice restrictions (space mute/deafen, persisted), member move/disconnect, join request approval

Federation: Multi-instance peering (HMAC-signed), DM relay (messages, reactions, membership), file replication with size validation, friend relay, identity resolution, background workers (outbox delivery, file download, health check, janitor)

Platform: File uploads (with thumbnails via sharp), full-text search (from/has/before/after filters), admin panel (user management, storage, streaming config), Electron desktop app, mobile-responsive UI, account management (password change, deletion with safeguards)