Web Player
Next.js web application for music streaming. Replaces the retired apps/web client โ see
ADR-0011.
๐ Quick Startโ
cd apps/web-player
# Install dependencies (from repo root)
pnpm install
# Start development server
pnpm dev
Application will be available at http://localhost:3001
๐๏ธ Architectureโ
apps/web-player/src follows Feature-Sliced Design (FSD); see
ADR-0002. Imports flow
downward only: app โ views โ widgets โ features โ entities โ shared.
apps/web-player/src/
โโโ app/ # Next.js App Router โ layout.tsx, page.tsx, providers
โโโ views/ # Full-page compositions for one route
โโโ widgets/ # Self-contained sections: Header, Player, Sidebar
โโโ features/ # User interactions: Album, AuthModal, Playlist, Track
โโโ entities/ # Domain objects: Track, User, Player
โโโ shared/ # api/, hooks/, store/, ui/, routes/, constants/, validation/
Route files under app/ are thin adapters that render a view โ see
ADR-0010.
๐ฌ Landing (/)โ
app/(home)/ serves the landing with its own fonts (Unbounded, Inter, JetBrains Mono); auth and
legal pages keep app/(landing)/ with the shared Header and Footer. views/LandingView renders
eleven scenes on the server. Its motion engine (lib/engine/: GSAP scenes, a Three.js stage,
physics, intro, cursor) is imported only on the client after mount. Without WebGL it switches to
2D fallbacks, and with reduced motion it is a static, scrollable page. The landing copy is a
local catalog (en, uk, pl; other locales read English). Styling is Tailwind: lib/styles/landing.styles.ts lists
utilities per marker class in cascade order (context rules as arbitrary variants), and lc()
merges an element's entries with cn; ui/landing.css keeps only keyframes, the html scroll
and cursor locks and the grain data URI. Behaviour and acceptance:
web-player landing spec; motion reference:
pencil/web-player-design/landing/motion-prototype.html.
๐จ Tech Stackโ
- Next.js (App Router) + React 19 + TypeScript
- Tailwind CSS v4 + @bitrate/ui-react โ design tokens, CVA, shadcn-style components (see ADR-0006)
- openapi-fetch + TanStack Query โ typed API client generated from the NestJS Swagger contract (see ADR-0004)
- Zustand โ cross-component client state (see ADR-0005)
- React Hook Form + Zod โ forms (see ADR-0007)
- CMAF + MediaSource Extensions โ first-party adaptive playback over byte ranges (see ADR-0020)
- Native fallback โ without MSE the same CMAF file plays through
<audio>(see ADR-0065)
๐ง API clientโ
// shared/api/client/fetchClient.ts โ openapi-fetch + JWT refresh middleware
export const apiClient = createClient<ApiPaths>({ baseUrl: ... })
// shared/api/client/reactQueryClient.ts โ openapi-react-query
export const { useQuery, useMutation, useSuspenseQuery } = createReactQueryClient(apiClient)
Components call useQuery/useMutation from reactQueryClient โ never raw fetch or Axios.
๐งช Testingโ
pnpm --filter @bitrate/web-player test:unit
pnpm --filter @bitrate/web-player test:int
pnpm --filter @bitrate/web-player test:e2e
pnpm --filter @bitrate/web-player test:screenshot
๐ Build & Deployโ
pnpm --filter @bitrate/web-player build
pnpm --filter @bitrate/web-player start
Related: