-
Notifications
You must be signed in to change notification settings - Fork 5
2 Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:
This document provides a high-level overview of the AudioScape system architecture, covering the core frameworks, navigation patterns, state management, and external service integrations that comprise the music streaming application.
For detailed information about specific UI components and screens, see User Interface System. For in-depth coverage of the music playback functionality, see Music Playback System. For data management and persistence details, see Data and State Management.
AudioScape is built on React Native with Expo, implementing a modular architecture that separates concerns across navigation, state management, audio processing, and external service integration.
graph TB
subgraph "Foundation Layer"
EXPO["expo (Framework)"]
RN["react-native"]
ROUTER["expo-router"]
end
subgraph "Navigation Layer"
STACK["Stack Navigator"]
TABS["Tabs Navigator"]
MODALS["Modal Screens"]
end
subgraph "State Management"
REDUX["Redux Store (library.tsx)"]
MUSIC_CTX["MusicPlayerContext"]
LYRICS_CTX["LyricsProvider"]
end
subgraph "Audio Engine"
TRACK_PLAYER["react-native-track-player"]
BG_SERVICE["playbackService"]
end
EXPO --> RN
RN --> ROUTER
ROUTER --> STACK
ROUTER --> TABS
ROUTER --> MODALS
REDUX --> MUSIC_CTX
MUSIC_CTX --> TRACK_PLAYER
TRACK_PLAYER --> BG_SERVICE
Sources: app/_layout.tsx:10-34, app/(tabs)/_layout.tsx:11-14, components/MusicPlayerContext.tsx:10-27, store/library.tsx:9-10
The application follows a provider-based architecture where global contexts wrap the entire app to manage cross-cutting concerns:
graph TD
ROOT["RootLayout (app/_layout.tsx)"] --> PROVIDERS["Global Providers"]
subgraph "Provider Stack"
REDUX_PROV["Redux Provider"]
MUSIC_PROV["MusicPlayerProvider"]
LYRICS_PROV["LyricsProvider"]
SAFE_AREA["SafeAreaProvider"]
GESTURE["GestureHandlerRootView"]
end
PROVIDERS --> REDUX_PROV
REDUX_PROV --> MUSIC_PROV
MUSIC_PROV --> LYRICS_PROV
LYRICS_PROV --> SAFE_AREA
SAFE_AREA --> GESTURE
GESTURE --> NAV_STACK["Navigation Stack"]
subgraph "Navigation Structure"
TABS_SCREEN["(tabs) - Main App"]
PLAYER_MODAL["player - Music Player"]
MODAL_SCREENS["(modals)/* - Action Modals"]
end
NAV_STACK --> TABS_SCREEN
NAV_STACK --> PLAYER_MODAL
NAV_STACK --> MODAL_SCREENS
Sources: app/_layout.tsx:105-181, components/MusicPlayerContext.tsx:97-99, store/library.tsx:265-269
The navigation system uses expo-router with a stack-based approach, implementing both tab navigation for main content and modal presentations for contextual actions.
graph TD
ROOT_LAYOUT["_layout.tsx"] --> MAIN_STACK["Stack Navigator"]
MAIN_STACK --> TABS_GROUP["(tabs)/_layout.tsx"]
MAIN_STACK --> PLAYER["player.tsx"]
MAIN_STACK --> MODALS["(modals)/*"]
subgraph "Tab Navigation"
TABS_GROUP --> HOME_TAB["home/*"]
TABS_GROUP --> FAV_TAB["favorites.tsx"]
TABS_GROUP --> PLAYLIST_TAB["playlists.tsx"]
TABS_GROUP --> DOWNLOAD_TAB["downloads.tsx"]
TABS_GROUP --> FLOATING["FloatingPlayer"]
end
subgraph "Modal System"
MODALS --> QUEUE_M["queue.tsx"]
MODALS --> LYRICS_M["lyrics.tsx"]
MODALS --> MENU_M["menu.tsx"]
MODALS --> PLAYLIST_M["addToPlaylist.tsx"]
MODALS --> DELETE_M["deletePlaylist.tsx"]
end
subgraph "Home Stack"
HOME_TAB --> HOME_INDEX["index.tsx"]
HOME_TAB --> ARTIST["artist/[id].tsx"]
HOME_TAB --> ALBUM["album/[id].tsx"]
HOME_TAB --> SEARCH["search.tsx"]
end
Sources: app/_layout.tsx:118-171, app/(tabs)/_layout.tsx:23-140, app/(modals)/menu.tsx:47
The tab navigation implements a custom design with gradient background and floating player integration:
| Tab | Route | Icon | Component |
|---|---|---|---|
| Home | home |
home/home-outline
|
Home content and search |
| Favorites | favorites |
heart/heart-outline
|
Liked songs |
| Playlists | playlists |
list/list-outline
|
User playlists |
| Downloads | downloads |
download/download-outline
|
Offline content |
Sources: app/(tabs)/_layout.tsx:67-117
The application employs a dual-state approach combining Redux for persistent data and React Context for transient playback state.
graph LR
subgraph "UI Components"
PLAYER_UI["PlayerScreen"]
TAB_UI["Tab Screens"]
MODAL_UI["Modal Components"]
end
subgraph "Context Layer"
MUSIC_CTX["MusicPlayerContext"]
LYRICS_CTX["LyricsProvider"]
end
subgraph "Redux Store"
LIB_STATE["LibraryState"]
FAV_SLICE["favoriteTracks"]
PLAYLIST_SLICE["playlists"]
DOWNLOAD_SLICE["downloadedTracks"]
end
subgraph "Persistence"
FILE_SYS["FileSystem (libraryData.json)"]
MMKV_STORE["MMKV Storage"]
end
subgraph "Audio Engine"
TRACK_PLAYER["TrackPlayer"]
QUEUE_MGR["Queue Management"]
end
PLAYER_UI --> MUSIC_CTX
TAB_UI --> LIB_STATE
MODAL_UI --> MUSIC_CTX
MODAL_UI --> LIB_STATE
MUSIC_CTX --> TRACK_PLAYER
MUSIC_CTX --> QUEUE_MGR
LIB_STATE --> FILE_SYS
MUSIC_CTX --> MMKV_STORE
TRACK_PLAYER --> QUEUE_MGR
Sources: components/MusicPlayerContext.tsx:33-45, store/library.tsx:16-21, store/library.tsx:55-62
The LibraryState interface defines the persistent data model:
interface LibraryState {
favoriteTracks: Song[];
playlists: Record<string, Song[]>;
downloadedTracks: DownloadedSongMetadata[];
activeDownloads: Record<string, { song: Song; progress: number }>;
}Sources: store/library.tsx:16-21, store/library.tsx:26-35
AudioScape integrates with multiple external services for content delivery, lyrics, and app management.
graph TB
subgraph "AudioScape Core"
MUSIC_CTX["MusicPlayerContext"]
DOWNLOAD_SVC["Download Service"]
UPDATE_SVC["Update System"]
end
subgraph "YouTube Integration"
YT_API["YouTube 'po token' API"]
INNERTUBE["innertube Service"]
YT_JS["YouTube.js Library"]
end
subgraph "Content Services"
LRCLIB["LrcLib Lyrics API"]
FIREBASE["Firebase Services"]
end
subgraph "Infrastructure"
GITHUB["GitHub Releases"]
RENDER["Render.com Hosting"]
end
MUSIC_CTX --> YT_API
MUSIC_CTX --> LRCLIB
YT_API --> INNERTUBE
INNERTUBE --> YT_JS
DOWNLOAD_SVC --> YT_API
UPDATE_SVC --> GITHUB
YT_API -.->|"Hosted on"| RENDER
UPDATE_SVC --> FIREBASE
Sources: components/MusicPlayerContext.tsx:18, services/youtube.ts, app/(modals)/menu.tsx:26
| Service | Purpose | Integration Point |
|---|---|---|
| YouTube Music API | Stream audio content |
getInfo(), innertube
|
| LrcLib | Synchronized lyrics | LyricsProvider |
| Firebase | Remote config, messaging | Global initialization |
| GitHub API | App updates | UpdateModal |
Sources: components/MusicPlayerContext.tsx:432-496, app/_layout.tsx:82-84
The system's core functionality emerges from the interaction between the MusicPlayerContext, Redux store, and TrackPlayer:
sequenceDiagram
participant UI as "UI Component"
participant CTX as "MusicPlayerContext"
participant TP as "TrackPlayer"
participant YT as "YouTube API"
participant REDUX as "Redux Store"
UI->>CTX: playAudio(song, playlist?)
CTX->>YT: getInfo(songId)
YT-->>CTX: Track metadata + stream URL
CTX->>TP: add(trackInfo)
CTX->>TP: play()
CTX->>CTX: addPlaylistTracksInBackground()
CTX->>REDUX: Update favorites/playlists
REDUX->>REDUX: saveToFile()
Sources: components/MusicPlayerContext.tsx:507-600, components/MusicPlayerContext.tsx:135-273, store/library.tsx:55-62
The architecture provides clear separation of concerns while maintaining efficient data flow between the UI layer, business logic contexts, persistent storage, and external services. The modular design enables independent testing and maintenance of each subsystem while ensuring consistent user experience across the application.