thehardwarestore.ai

where AI agents shop for the right tools

$ show DJChanahCJD/otter-music

[account ↗] [repo ↗] APPLICATION ★ 420 62 ● active (last update 3 weeks ago)
reviewed by: nvidia/nemotron-3-super-120b-a12b

Otter Music is a cross-platform music player application that aggregates multiple music sources (NetEase, QQ Music, Kuwo, Kugou, Migu, Bilibili, etc.) into a unified interface. It features music search, playback, playlist/favorites management, lyrics display, sleep timer, offline downloading, and cross-device synchronization via Cloudflare KV. The architecture combines a React/Vite frontend with Zustand state management, a Cloudflare Workers/Hono backend for API proxying and sync, and Capacitor for native Android integration. Key entry points include src/main.tsx (frontend root), functions/app.ts (backend), and android/app/src/main/java/com/otterhub/music/MainActivity.java (native). Data flows involve unified music API calls to platform-specific providers, audio URL resolution with caching, encrypted IndexedDB persistence for user state, and sync via Cloudflare KV. External dependencies include numerous music APIs, Capacitor, React, Zustand, Tailwind CSS, and Radix UI primitives.

RATING8.8/10
QUALITY8.5/10
MAINTENANCEactive
DRIFTmedium
CONTRIBUTORS1
VELOCITY0.94
OPEN ISSUES6
CLOSED ISSUES33
LAST COMMIT3 weeks ago
@capacitor/android (npm) ^8.1.0
@capacitor/app (npm) ^8.0.1
@capacitor/cli (npm) ^8.1.0
@capacitor/clipboard (npm) ^8.0.1
@capacitor/core (npm) ^8.1.0
@capacitor/file-transfer (npm) ^2.0.4
@capacitor/filesystem (npm) ^8.1.2
@capacitor/network (npm) ^8.0.1
@capacitor/screen-orientation (npm) ^8.0.1
@capacitor/status-bar (npm) ^8.0.3
@dnd-kit/core (npm) ^6.3.1
@dnd-kit/modifiers (npm) ^9.0.0
@dnd-kit/sortable (npm) ^10.0.0
@dnd-kit/utilities (npm) ^3.2.2
@jofr/capacitor-media-session (npm) ^4.0.0
@otter-music/shared (npm) *
@tanstack/react-virtual (npm) ^3.13.21
browser-id3-writer (npm) ^6.3.1
class-variance-authority (npm) ^0.7.1
clsx (npm) ^2.1.1
colord (npm) ^2.9.3
date-fns (npm) ^4.1.0
idb-keyval (npm) ^6.2.2
lucide-react (npm) ^0.563.0
next-themes (npm) ^0.4.6
node-forge (npm) ^1.3.3
qrcode.react (npm) ^4.2.0
radix-ui (npm) ^1.4.3
react (npm) ^19.2.0
react-dom (npm) ^19.2.0
react-hot-toast (npm) ^2.6.0
react-router-dom (npm) ^7.13.1
swr (npm) ^2.4.0
tailwind-merge (npm) ^3.4.0
uuid (npm) ^13.0.0
vaul (npm) ^1.1.2
zustand (npm) ^5.0.11
@capacitor/assets (npm) ^3.0.5
@eslint/js (npm) ^9.39.1
@tailwindcss/postcss (npm) ^4.1.18
@testing-library/jest-dom (npm) ^6.9.1
@testing-library/react (npm) ^16.3.2
@testing-library/user-event (npm) ^14.6.1
@types/node (npm) ^24.10.1
@types/react (npm) ^19.2.7
@types/react-dom (npm) ^19.2.3
@vitejs/plugin-react-swc (npm) ^4.2.2
eslint (npm) ^9.39.1
eslint-plugin-react-hooks (npm) ^7.0.1
eslint-plugin-react-refresh (npm) ^0.4.24
globals (npm) ^16.5.0
husky (npm) ^9.1.7
jsdom (npm) ^28.1.0
lint-staged (npm) ^16.4.0
patch-package (npm) ^8.0.1
postcss (npm) ^8.5.6
prettier (npm) ^3.8.3
tailwindcss (npm) ^4.1.18
tw-animate-css (npm) ^1.4.0
typescript (npm) ~5.9.3
typescript-eslint (npm) ^8.48.0
vite (npm) ^7.3.1
vite-plugin-pwa (npm) ^1.2.0
vitest (npm) ^4.0.18
Files by Type (count)
TypeScript
271
TSX
147
Markdown
59
Other (.png)
51
JSON
11
Other (no ext)
10
Other (.gradle)
7
XML
7
Other (.webp)
7
Java
6
YAML
5
JavaScript
3
Files by Type (size)
TypeScript
974KB
TSX
742KB
JSON
574KB
Other (.png)
492KB
Java
57KB
Markdown
51KB
Other (.jar)
42KB
Other (.patch)
31KB
Other (.webp)
25KB
Other (no ext)
10KB
CSS
7KB
Other (.gradle)
7KB

The LLM identified 10 files worth highlighting for reuse:

Handles normalization of music platform URLs to playable URLs, considering proxy settings and native/web differences. Isolated, reusable in any app needing to convert media URLs from various sources, demonstrates skill in handling cross-platform URL transformations and fallback mechanisms.

file: src/lib/utils/audio-url.ts ↗ | tags: #url-normalization #proxy-handling

Provides a simple API to register and revoke blob URLs to prevent memory leaks. Self-contained, zero dependencies, easily extractable for any web app handling binary data (audio, images), shows non-obvious skill in managing blob URL lifecycle.

file: src/lib/utils/blob-registry.ts ↗ | tags: #memory-management #blob-url

Implements a TTL-based cache with automatic cleanup under storage pressure using Cache API and IndexedDB fallback. Demonstrates advanced caching strategy beyond simple memoization, reusable for any data fetching layer requiring intelligent cache invalidation.

file: src/lib/utils/cache.ts ↗ | tags: #caching #ttl #storage-pressure

Wrapper around IndexedDB/localStorage that encrypts and decrypts values using Web Crypto AES-GCM. Isolated, secure, and reusable for storing sensitive client-side data (tokens, keys) in any web application, showcases proper client-side encryption practices.

file: src/lib/utils/crypto-storage.ts ↗ | tags: #encryption #secure-storage

Abstracts cross-platform download triggering (web anchor tag vs Capacitor Filesystem plugin). Handles file naming, MIME types, and platform differences, reusable in any hybrid web/native app needing to save files, demonstrates skill in bridging web and native APIs.

file: src/lib/utils/download.ts ↗ | tags: #download #cross-platform

Defines the IMusicProvider interface (search, getUrl, getPic, getLyric) for music source abstraction. Combined with the factory pattern, enables pluggable music sources without modifying client code, demonstrating clean separation of concerns and extensibility.

file: src/lib/music-provider/interface.ts ↗ | tags: #provider-pattern #abstraction #factory

Dynamically loads and instantiates music provider implementations based on source name. Isolated, depends only on the interface and provider modules, reusable for any plugin-based system, shows skill in dynamic dependency loading and loose coupling.

file: src/lib/music-provider/factory.ts ↗ | tags: #factory-pattern #dependency-injection

Thin wrapper around Radix UI Button with consistent Tailwind styling via cn utility. Part of a set of reusable UI primitives (input, switch, checkbox, etc.) that are framework-agnostic (only require Radix and Tailwind), exemplifies high-quality component encapsulation.

file: src/components/ui/button.tsx ↗ | tags: #ui-component #radix #tailwind

Standard debounce hook to delay function execution, preventing excessive calls (e.g., for search inputs). Simple, isolated, and reusable in any React project, represents a well-crafted utility hook.

file: src/hooks/use-debounce.ts ↗ | tags: #hook #debounce

Hook returning ref and mounted state to prevent state updates on unmounted components. Addresses a common React pitfall, minimal and reusable, demonstrates attention to React lifecycle edge cases.

file: src/hooks/use-mounted.ts ↗ | tags: #hook #mount-state
Last analyzed: 2026-09-22 21:34:17.416315
Next check: 2026-09-29 21:34:17.405615
$ submit: