- Add `is_nsfw` column to `songs` and `playlists` tables
- Implement NSFW checkbox in song/playlist upload and edit forms
- Enforce NSFW content visibility: block unauthenticated users from viewing/streaming NSFW songs/playlists
- Filter NSFW content from public-facing lists (recent, popular, liked, etc.) unless user is logged in
- Add VIP-only visibility option for songs/playlists (admin/VIP users only)
- Display "EXPLICIT" badge on NSFW items in UI
- Add CSS styling for NSFW badge
- Update service layer to handle NSFW flag in CRUD operations and queries
- Enable bulk song selection with custom checkboxes and select-all header row
- Add "Most Popular" section (scored by likes + 2×favorites) alongside Trending
- Improve horizontal scrolling for liked strips with grab/grabbing cursor and drag-to-scroll logic
- Introduce neon divider (`hr.hr-neon`) for visual separation between sections
- Update CSS grid layout for selectable song lists to accommodate checkboxes
- Introduce `vip` visibility level with CSS badge styling
- Update admin routes to restrict VIP setting to admins and VIP users
- Extend visibility logic in public routes (`canView`, `denyAccess`)
- Add VIP-specific SQL queries in playlists, social, and songs services
- Update EJS templates to show VIP badges and radio options for authorized users
- Reveal left panel in NP modal on mobile by stacking content vertically
- Hide record & creator info to preserve space; center sleeve image
- Update song detail layout: full-width cover, stacked metadata, centered controls
- Ensure buttons and share row wrap/center properly on narrow screens
- Add genre and uploader filters to /songs with persistent query params in pagination
- Implement site-wide "Trending" strip showing recently liked songs
- Introduce responsive hamburger nav for mobile with animated icon & ARIA support
- Refactor song row layout: move duration into separate `.song-duration` element
- Update CSS for mobile grid (2 columns), optimized song rows, and facet selects
- Introduce a new "Appears in" section on song pages showing playlists containing the song (public/logged_in visibility)
- Add secondary button styling for Edit links on song and playlist detail pages, visible only to creators
- Implement `getPlaylistsForSong()` service function with guest/user-aware queries
- Update view templates to render edit buttons and playlist appearance cards
- Add database schema for site_settings and generated_songs tables with migration 011_generation.sql
- Implement backend services for settings management and generation workflow (submit/poll ComfyUI)
- Create routes for admin panel (/admin) to configure generation parameters, upload workflow JSON, manage users
- Create generate routes (/generate) with rate limiting (3min cooldown, 10/hour limit), form submission, polling, streaming
- Add frontend UI: generate page with form and rate-limit panel, publish flow for completed generations
- Integrate generation link into header navigation for verified users when enabled
- Add client-side genre dropdown populated from existing genres + option to add new genre via text input
- Introduce resolveGenre() helper to prioritize new-genre input over selection, handling the "__new__" sentinel value
- Update admin routes and form rendering to pass available genres and preserve user selections on validation errors
- Add listGenres() service method and CSS styling for genre field layout
This replaces the simple text input with a more user-friendly dropdown experience while still supporting custom genres.
- Introduces bulk checkboxes on the songs list page to select multiple songs
- Adds a toolbar with dropdown to add selected songs to existing playlists or create a new playlist
- Implements `/songs/bulk-add` POST endpoint for efficient batch addition of tracks to playlists
- Auto-upgrades playlist visibility when adding more-restrictive songs
- Supports preselecting songs via query parameter when creating a new playlist (`?songs=1,2,3`)
- Includes custom-styled checkboxes, toast notifications, and keyboard-friendly UI interactions
- Replace static gradient backdrops with spinning conic-gradient plasma on both lightbox and now-playing overlays
- Add smooth fade animations (`lb-fade-in-synthwave`/`lb-fade-out-synthwave`) using a dark neutral base
- Introduce `overlay-plasma-spin` animation for continuous rotation and scale pulsing
- Ensure proper z-index stacking and overflow handling for plasma layer (`::before`)
- Clean up single-mode toggle logic: clear stale content before switching modes, reset playlist state when queue changes from single to multi-track
- Introduce new `#np-bigroom-view` overlay for single-song playback with centered layout and animated circular spectrum visualizer (`#np-viz-big`)
- Refactor now-playing overlay to toggle between playlist mode and big-room mode based on `meta.singleMode`
- Add real-time canvas-based frequency visualization using analyser node, exposed globally as `window.briTunesAnalyser`
- Update song/playlist pages to support single-song playback via new `data-nowplaying-meta` attribute
- Add smart "Now Playing" reopen button that only appears when matching song/playlist is active, with per-song or per-playlist matching
- Add UI components for notification navigation (btn + badge) and notification list with unread indicators
- Introduce notifications service with CRUD methods for managing user notifications
- Trigger notifications when users like/favorite songs or playlists via social actions
- Add /account/notifications route to view and mark all notifications as read
- Display unread count in header and account page navigation
- Move /admin/* routes to /mymusic/* for clearer user-focused section naming
- Rename admin/ view templates to mymusic/ with updated paths and URLs
- Add cover art preview in song edit form with current cover thumbnail styling
- Update navigation active states to use new /mymusic* paths
- Change now-playing creator link from window.open() to direct navigation
- Introduce dynamic 3D geometry objects (torusKnot, trefoil, hyperboloid, etc.) rendered with Three.js on both sides of the screen when lightbox or now-playing overlay is open; only active on viewports ≥1280px wide.
- Add CSS styling for `.oo-canvas` (z-index 3100) and `.card.playlist-active` to highlight the currently active playlist card with neon-cyan glow effects.
- Extend player.js to track `briTunesActivePlaylistId` and toggle `playlist-active` class on cards via data attributes.
- Add `data-playlist-id` attributes to playlist cards in home, playlists, profile views and play buttons in playlist view for highlighting support.
- Add database migration to create unique `slug` column for users table
- Implement profile routes (`/profiles`, `/profiles/:slug`) with views for:
• listing verified user profiles with avatars, song/playlist counts
• individual profile pages showing user's songs, playlists, liked items
- Add helper functions in `users.js`, `songs.js`, `playlists.js`, and `social.js`
to support public visibility filtering and profile data enrichment
- Enhance now-playing overlay UI with:
• vinyl sleeve animation (sleeve + record peeking behind cover)
• clickable creator info to open profile page if slug exists
• track row click to jump directly to a song in the queue
- Update CSS for profiles grid, detail creator links, and overlay styling
- Add "Profiles" link to header navigation
This enables a full user profile system with vanity URLs and improves the
music player experience with visual polish and direct navigation.
- Introduce a full-screen "Now Playing" overlay modal with left (cover/creator) and right (track list/controls) panels
- Add CSS styles for animated cyan-themed overlay, track list, progress bar, and equalizer visualizer
- Integrate new `now-playing.js` module and update layout to include it
- Refactor playlist action buttons to include a "Now Playing" reopen button that appears when playback starts
- Dispatch `briTunes:queue` event on queue initialization for external UI synchronization
- Add `avatar_path` column to users table via migration 008
- Integrate `cropperjs` and `sharp` for avatar upload, cropping (600×600), and PNG conversion
- Serve avatars at `/media/avatars` with static caching; expose `/static/vendor/cropperjs`
- Add avatar management UI in account settings with modal cropping workflow
- Display creator avatars on song/playlist detail pages (fallback to initial)
- Implement generic image lightbox (`lightbox.js`) for cover art with zoom animations and keyboard support
- Refactor song/playlist detail views to use responsive layout and lightbox-enabled covers
- Adjust `.card` to use flex column layout for proper content stacking
- Introduce `.card-footer` wrapper for creator + social buttons
- Move social buttons below creator info in playlist cards (home & listing)
- Add database tables for song/playlist likes and favorites
- Create `social` service with toggle functions and enrichment helpers
- Implement `/api/:type/:id/(like|favorite)` routes with CSRF protection
- Add like/favorite buttons to player, song lists, playlists, and cards
- Support guest → login redirect via `data-require-login`
- Inject CSRF token into layout for JS API requests
- Introduce repeat button with active state styling and toggle logic in player.js
- Update background grid animation to use faster, distance-scaled flyby passes for more dynamic visuals
- Extend song view model (`songs.js`) to include uploader's display name
- Improve user verification flow (`users.js`) to ensure fresh state after async password check
- Add uploader info line in public song page view
feat(users): implement user disabling functionality with admin controls
- Add `disabled` column to users table via migration
- Update login flow to reject disabled accounts with 403 error
- Introduce new `/admin/users` route for admin-only user management (disable/enable, verify email, delete with content)
- Extend users service to support listing all users, toggling disabled status, admin verification, and cascading deletion of user's songs/playlists
- Add admin UI for managing users with visual indication of disabled accounts (opacity reduction)
- Update navigation to include "Users" link for admins
```
- Display playlist creator name on public and admin playlist views
- Add shuffle playback button for playlists in player UI
- Implement drag-and-drop reordering for playlist tracks with visual feedback
- Improve email verification UX: redirect pending users to verify page with resend option
- Simplify admin routes by removing redundant role checks (user-based filtering already handled)
- Adjust featured playlist count and add "show all" links on home page
- Introduce email_verified column and email_verifications table for token-based verification
- Add nodemailer dependency and create mailer service (SMTP + dev fallback to console)
- On registration, generate 24h verification token and send email (or log URL in dev)
- Add /verify-email GET route to validate tokens and mark user as verified
- Add /resend-verification POST route for logged-in users to re-send link
- Update flash system with new warning style for unverified users
- Update .env.example with APP_BASE_URL and SMTP_* configuration variables
Note: existing users are grandfathered in (email_verified=1) via migration.
- Add public/logged_in/private visibility levels to songs and playlists via database migration (002_visibility.sql)
- Replace old `is_public` boolean with new `visibility` enum in admin forms, API schemas, and services
- Implement access control logic:
- Guests see only public items that don't contain restricted tracks
- Logged-in users see public + logged_in items (excluding private ones)
- Admins see all; regular users manage their own content
- Auto-upgrade playlist visibility when adding more restrictive songs
- Add UI badges for visibility levels and update admin views to reflect new hierarchy
PWA enhancements:
- Update web manifest with proper name, colors, and icon paths
- Add service worker (sw.js) with cache-first for static assets and network-first for HTML
- Register SW at root (/sw.js) with Service-Worker-Allowed header for full origin scope
- Add theme-color meta tag and navigate.js for client-side routing
Other:
- Update admin nav label from "Admin" to "My Music" to reflect role-based access