Refactor RegisterPage into a two-step flow: credentials first, then
personalization (display name, avatar upload, avatar color). Replace the
dual-panel sliding layout with conditional rendering and CSS keyframe
animations to eliminate overflow-hidden clipping of focus rings.
Supporting changes:
- Server accepts avatarColor on registration
- Auth store resets all user-scoped stores on login/register/logout
- Voice store gains resetSession() for full session cleanup
- Sync presence status to federated instances
- Propagate presence_update to socialStore regardless of origin
Add avatarColor as a stored, user-selectable field (mint, sky, lavender,
coral, rose, teal, amber). Randomly assigned on registration, changeable
in profile settings. Existing users keep hash-based fallback until they
choose a color. Includes DB migration, API validation, gradient map,
live preview in settings, and banner fallback integration.
Move instance-level administration out of Space Settings into its own
modal. Adds admin UI for instance name, registration toggle, and
discovery toggle. Streaming limits panel relocated from SpaceSettings.
- Add InstanceAdminSettings type and GET/PATCH /api/settings/instance
- Add registration_open DB column (nullable, env var fallback)
- Auth registration and instance info now check DB override
- New InstanceSettings modal with General and Streaming tabs
- Admin shield button in UserAreaPanel (visible to admins only)
- Remove Streaming tab from SpaceSettings
- Fix DM welcome header avatar using home identity for correct gradient color
- Register DM channel IDs in channelOriginMap so federated DM operations
(reactions, messages, typing) route to the correct instance
- Pass origin when creating DM channels from friends list and WS events
- Add server discovery/explore page with public server listings
- Add server visibility and description fields
Store the original home snowflake ID (homeUserId) during federation replication
so that avatar gradient colors resolve identically across instances. Previously,
replicated users got new snowflake IDs on each instance, causing different
gradient colors. Now Avatar, UserProfilePopout, VoiceUser, StreamTile, and
VoiceChannel all resolve through homeUserId when available. Includes backfill
logic for existing federated users missing the field.
Add multi-instance support foundation: shared federation types
(ReplicatedInstance, InstanceInfoResponse, VerifyPasswordRequest),
database schema changes (home_instance, replicated_instances on users,
instance_name on settings), public instance info endpoint, auth
registration with homeInstance and username@domain collision fallback,
password verification endpoint, and replicatedInstances sync on user
profile. Extract duplicated sanitizeUser into shared utility across
8 server files.
- 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 a server-side instance_settings table (single-row, CHECK(id=1))
that stores admin-configurable streaming bounds: bitrate min/max/step,
allowed resolutions, and allowed framerates.
Backend:
- New instance_settings schema + migrations (is_admin on users, default
settings row, first-registered-user promoted to admin)
- GET/PATCH /api/settings/streaming endpoints with admin-only writes
and full input validation including cross-field checks
Frontend:
- settingsStore fetches limits on WebSocket ready, exposes isAdmin flag
- ScreenShareSettingsPopover reads bounds from store instead of
hardcoded constants, auto-clamps stale localStorage values
- buildScreenShareOptions() clamps bitrate to server limits at build
time as enforcement backstop
- ServerSettings modal gains a "Streaming" tab (admin-only) with
bitrate range sliders, resolution/framerate toggles, and save/reset