diff --git a/app/build.gradle b/app/build.gradle
index 1dfaaa1f..1df32dd6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -79,8 +79,10 @@ dependencies {
     implementation project(":shared:song:random")
     implementation project(':feature:album:list')
     implementation project(':feature:album:info')
+    implementation project(':feature:album:favorites')
     implementation project(':feature:artist:list')
     implementation project(':feature:artist:info')
+    implementation project(':feature:artist:favorites')
     implementation project(':feature:playlist:list')
     implementation project(':feature:playlist:info')
     implementation project(":feature:main")
@@ -91,7 +93,7 @@ dependencies {
     implementation project(":feature:server:list")
     implementation project(":feature:search")
     implementation project(":feature:song:info")
-    implementation project(":feature:favorite:list")
+    implementation project(":feature:song:favorites")
     implementation project(":feature:settings")
     implementation project(":feature:about")
     implementation project(":feature:personal")
diff --git a/app/src/main/java/ru/stersh/youamp/Di.kt b/app/src/main/java/ru/stersh/youamp/Di.kt
index 0f9a7c6f..c586ba35 100644
--- a/app/src/main/java/ru/stersh/youamp/Di.kt
+++ b/app/src/main/java/ru/stersh/youamp/Di.kt
@@ -10,9 +10,9 @@ import org.koin.dsl.module
 import ru.stersh.youamp.core.api.provider.ApiProvider
 import ru.stersh.youamp.core.room.roomModule
 import ru.stersh.youamp.feature.album.albumInfoModule
-import ru.stersh.youamp.feature.albums.albumsModule
+import ru.stersh.youamp.feature.albums.albumListModule
 import ru.stersh.youamp.feature.artist.artistInfoModule
-import ru.stersh.youamp.feature.artists.artistsModule
+import ru.stersh.youamp.feature.artists.artistListModule
 import ru.stersh.youamp.feature.main.mainModule
 import ru.stersh.youamp.feature.personal.personalModule
 import ru.stersh.youamp.feature.player.mini.playerMiniModule
@@ -33,9 +33,11 @@ import ru.stersh.youamp.shared.player.playerSharedModule
 import ru.stresh.youamp.core.properties.app.AppProperties
 import ru.stresh.youamp.core.propertiesModule
 import ru.stresh.youamp.feature.about.aboutModule
+import ru.stresh.youamp.feature.album.favorites.albumFavoritesModule
+import ru.stresh.youamp.feature.artist.favorites.artistFavoritesModule
 import ru.stresh.youamp.feature.explore.exploreModule
-import ru.stresh.youamp.feature.favorite.list.favoriteListModule
 import ru.stresh.youamp.feature.library.libraryModule
+import ru.stresh.youamp.feature.song.favorites.songFavoritesModule
 import ru.stresh.youamp.feature.song.random.songRandomModule
 import ru.stresh.youamp.shared.favorites.favoritesSharedModule
 import ru.stresh.youamp.shared.song.random.songRandomSharedModule
@@ -63,22 +65,24 @@ private val feature = listOf(
     playerScreenModule,
     playerQueueScreenModule,
     albumInfoModule,
-    albumsModule,
-    artistsModule,
+    albumFavoritesModule,
+    albumListModule,
+    artistListModule,
     artistInfoModule,
+    artistFavoritesModule,
     serverCreateModule,
     serverListModule,
     playlistListModule,
-    searchModule,
     playlistInfoModule,
-    favoriteListModule,
+    searchModule,
+    songFavoritesModule,
+    songInfoModule,
+    songRandomModule,
     aboutModule,
     personalModule,
     exploreModule,
     mainModule,
-    libraryModule,
-    songInfoModule,
-    songRandomModule
+    libraryModule
 )
 
 private val impl = module {
diff --git a/app/src/main/java/ru/stersh/youamp/main/ui/MainActivity.kt b/app/src/main/java/ru/stersh/youamp/main/ui/MainActivity.kt
index dd3a2ca3..439b5265 100644
--- a/app/src/main/java/ru/stersh/youamp/main/ui/MainActivity.kt
+++ b/app/src/main/java/ru/stersh/youamp/main/ui/MainActivity.kt
@@ -50,10 +50,12 @@ import ru.stersh.youamp.feature.server.create.ui.ServerScreen
 import ru.stersh.youamp.feature.server.list.ui.ServerListScreen
 import ru.stersh.youamp.feature.song.info.ui.SongInfoScreen
 import ru.stresh.youamp.feature.about.ui.AboutScreen
+import ru.stresh.youamp.feature.album.favorites.ui.FavoriteAlbumsScreen
+import ru.stresh.youamp.feature.artist.favorites.ui.FavoriteArtistsScreen
 import ru.stresh.youamp.feature.explore.ui.ExploreScreen
-import ru.stresh.youamp.feature.favorite.list.ui.FavoriteSongsScreen
 import ru.stresh.youamp.feature.library.ui.LibraryScreen
 import ru.stresh.youamp.feature.settings.ui.SettingsScreen
+import ru.stresh.youamp.feature.song.favorites.ui.FavoriteSongsScreen
 import ru.stresh.youamp.feature.song.random.ui.RandomSongsScreen
 
 class MainActivity : ComponentActivity() {
@@ -143,8 +145,8 @@ class MainActivity : ComponentActivity() {
                             onPlaylistClick = { rootNavController.navigate(PlaylistInfo(it)) },
                             onPlaylistsClick = { rootNavController.navigate(Playlists) },
                             onFavoriteSongsClick = { rootNavController.navigate(FavoriteSongs) },
-                            onFavoriteAlbumsClick = {},
-                            onFavoriteArtistsClick = {}
+                            onFavoriteAlbumsClick = { rootNavController.navigate(FavoriteAlbums) },
+                            onFavoriteArtistsClick = { rootNavController.navigate(FavoriteArtists) }
                         )
                     },
                     explore = {
@@ -437,6 +439,40 @@ class MainActivity : ComponentActivity() {
                     )
                 }
             }
+            composable<FavoriteAlbums> {
+                ScreenWithMiniPlayer(
+                    viewModelStoreOwner = viewModelStoreOwner,
+                    onMiniPlayerClick = {
+                        rootNavController.navigate(Player)
+                    }
+                ) {
+                    FavoriteAlbumsScreen(
+                        onBackClick = {
+                            rootNavController.popBackStack()
+                        },
+                        onAlbumClick = {
+                            rootNavController.navigate(AlbumInfo(it))
+                        }
+                    )
+                }
+            }
+            composable<FavoriteArtists> {
+                ScreenWithMiniPlayer(
+                    viewModelStoreOwner = viewModelStoreOwner,
+                    onMiniPlayerClick = {
+                        rootNavController.navigate(Player)
+                    }
+                ) {
+                    FavoriteArtistsScreen(
+                        onBackClick = {
+                            rootNavController.popBackStack()
+                        },
+                        onArtistClick = {
+                            rootNavController.navigate(ArtistInfo(it))
+                        }
+                    )
+                }
+            }
         }
         songInfoProperties?.let { songProperties ->
             ModalBottomSheet(
diff --git a/app/src/main/java/ru/stersh/youamp/main/ui/Navigation.kt b/app/src/main/java/ru/stersh/youamp/main/ui/Navigation.kt
index ac280872..79955395 100644
--- a/app/src/main/java/ru/stersh/youamp/main/ui/Navigation.kt
+++ b/app/src/main/java/ru/stersh/youamp/main/ui/Navigation.kt
@@ -59,4 +59,10 @@ object Playlists
 object FavoriteSongs
 
 @Serializable
-object RandomSongs
\ No newline at end of file
+object RandomSongs
+
+@Serializable
+object FavoriteAlbums
+
+@Serializable
+object FavoriteArtists
\ No newline at end of file
diff --git a/buildscripts/android-feature-module.gradle b/buildscripts/android-feature-module.gradle
index 0c3fad56..bc2c0f72 100644
--- a/buildscripts/android-feature-module.gradle
+++ b/buildscripts/android-feature-module.gradle
@@ -7,6 +7,10 @@ android {
             freeCompilerArgs.add('-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi')
         }
     }
+    composeCompiler {
+        reportsDestination = layout.buildDirectory.dir("compose_compiler")
+        metricsDestination = layout.buildDirectory.dir("compose_compiler")
+    }
     buildFeatures {
         compose true
     }
diff --git a/core/api/src/main/java/ru/stersh/youamp/core/api/Album.kt b/core/api/src/main/java/ru/stersh/youamp/core/api/Album.kt
index f2e49c69..be1e35e9 100644
--- a/core/api/src/main/java/ru/stersh/youamp/core/api/Album.kt
+++ b/core/api/src/main/java/ru/stersh/youamp/core/api/Album.kt
@@ -54,7 +54,9 @@ data class Album(
     @Json(name = "songCount")
     val songCount: Int?,
     @Json(name = "year")
-    val year: Int?
+    val year: Int?,
+    @Json(name = "userRating")
+    val userRating: Int?
 )
 
 @JsonClass(generateAdapter = true)
diff --git a/core/api/src/main/java/ru/stersh/youamp/core/api/Artist.kt b/core/api/src/main/java/ru/stersh/youamp/core/api/Artist.kt
index 965b1caa..81a8f014 100644
--- a/core/api/src/main/java/ru/stersh/youamp/core/api/Artist.kt
+++ b/core/api/src/main/java/ru/stersh/youamp/core/api/Artist.kt
@@ -41,4 +41,6 @@ data class Artist(
     val artistImageUrl: String?,
     @Json(name = "album")
     val albums: List<Album>?,
+    @Json(name = "userRating")
+    val userRating: Int?
 )
diff --git a/feature/favorite/list/.gitignore b/feature/album/favorites/.gitignore
similarity index 100%
rename from feature/favorite/list/.gitignore
rename to feature/album/favorites/.gitignore
diff --git a/feature/album/favorites/build.gradle b/feature/album/favorites/build.gradle
new file mode 100644
index 00000000..c3261f32
--- /dev/null
+++ b/feature/album/favorites/build.gradle
@@ -0,0 +1,22 @@
+plugins {
+    alias(libs.plugins.android.library)
+    alias(libs.plugins.kotlin.android)
+    alias(libs.plugins.kotlin.compose.compiler)
+}
+
+apply from: "${project.rootDir}/buildscripts/android-feature-module.gradle"
+
+android {
+    namespace 'ru.stersh.youamp.feature.album.favorites'
+}
+
+dependencies {
+    implementation project(":core:ui")
+    implementation project(":core:api")
+    implementation project(":shared:player")
+    implementation project(":shared:favorites")
+    implementation(libs.bundles.lifecycle)
+    implementation(libs.coil.compose)
+    implementation(libs.bundles.koin)
+    implementation(libs.timber)
+}
\ No newline at end of file
diff --git a/feature/favorite/list/consumer-rules.pro b/feature/album/favorites/consumer-rules.pro
similarity index 100%
rename from feature/favorite/list/consumer-rules.pro
rename to feature/album/favorites/consumer-rules.pro
diff --git a/feature/favorite/list/proguard-rules.pro b/feature/album/favorites/proguard-rules.pro
similarity index 100%
rename from feature/favorite/list/proguard-rules.pro
rename to feature/album/favorites/proguard-rules.pro
diff --git a/feature/favorite/list/src/main/AndroidManifest.xml b/feature/album/favorites/src/main/AndroidManifest.xml
similarity index 100%
rename from feature/favorite/list/src/main/AndroidManifest.xml
rename to feature/album/favorites/src/main/AndroidManifest.xml
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/Di.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/Di.kt
new file mode 100644
index 00000000..4c3a29ba
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/Di.kt
@@ -0,0 +1,12 @@
+package ru.stresh.youamp.feature.album.favorites
+
+import org.koin.core.module.dsl.viewModel
+import org.koin.dsl.module
+import ru.stresh.youamp.feature.album.favorites.data.FavoriteAlbumsRepositoryImpl
+import ru.stresh.youamp.feature.album.favorites.domain.FavoriteAlbumsRepository
+import ru.stresh.youamp.feature.album.favorites.ui.FavoriteAlbumsViewModel
+
+val albumFavoritesModule = module {
+    single<FavoriteAlbumsRepository> { FavoriteAlbumsRepositoryImpl(get()) }
+    viewModel { FavoriteAlbumsViewModel(get(), get()) }
+}
\ No newline at end of file
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/data/FavoriteAlbumsRepositoryImpl.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/data/FavoriteAlbumsRepositoryImpl.kt
new file mode 100644
index 00000000..0d22398d
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/data/FavoriteAlbumsRepositoryImpl.kt
@@ -0,0 +1,33 @@
+package ru.stresh.youamp.feature.album.favorites.data
+
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import ru.stresh.youamp.feature.album.favorites.domain.Album
+import ru.stresh.youamp.feature.album.favorites.domain.FavoriteAlbumsRepository
+import ru.stresh.youamp.feature.album.favorites.domain.Favorites
+import ru.stresh.youamp.shared.favorites.AlbumFavoritesStorage
+
+internal class FavoriteAlbumsRepositoryImpl(
+    private val albumFavoritesStorage: AlbumFavoritesStorage
+) : FavoriteAlbumsRepository {
+
+    override fun getFavorites(): Flow<Favorites> {
+        return albumFavoritesStorage
+            .flowAlbums()
+            .map { favoriteAlbums ->
+                Favorites(
+                    albums = favoriteAlbums.map { it.toDomain() }
+                )
+            }
+    }
+
+    private fun ru.stresh.youamp.shared.favorites.Album.toDomain(): Album {
+        return Album(
+            id = id,
+            title = title,
+            artist = artist,
+            artworkUrl = artworkUrl,
+            userRating = userRating
+        )
+    }
+}
\ No newline at end of file
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/Album.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/Album.kt
new file mode 100644
index 00000000..5138985c
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/Album.kt
@@ -0,0 +1,9 @@
+package ru.stresh.youamp.feature.album.favorites.domain
+
+internal data class Album(
+    val id: String,
+    val title: String,
+    val artist: String?,
+    val artworkUrl: String?,
+    val userRating: Int?
+)
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/FavoriteAlbumsRepository.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/FavoriteAlbumsRepository.kt
new file mode 100644
index 00000000..ab1e972c
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/FavoriteAlbumsRepository.kt
@@ -0,0 +1,7 @@
+package ru.stresh.youamp.feature.album.favorites.domain
+
+import kotlinx.coroutines.flow.Flow
+
+internal interface FavoriteAlbumsRepository {
+    fun getFavorites(): Flow<Favorites>
+}
\ No newline at end of file
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/Favorites.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/Favorites.kt
new file mode 100644
index 00000000..149bb8dc
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/domain/Favorites.kt
@@ -0,0 +1,5 @@
+package ru.stresh.youamp.feature.album.favorites.domain
+
+internal data class Favorites(
+    val albums: List<Album>
+)
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/FavoriteAlbumsScreen.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/FavoriteAlbumsScreen.kt
new file mode 100644
index 00000000..a21e50af
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/FavoriteAlbumsScreen.kt
@@ -0,0 +1,221 @@
+package ru.stresh.youamp.feature.album.favorites.ui
+
+import android.content.res.Configuration
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.GridItemSpan
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.items
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.ListItem
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.pulltorefresh.PullToRefreshBox
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import org.koin.androidx.compose.koinViewModel
+import ru.stersh.youamp.core.ui.AlbumItem
+import ru.stersh.youamp.core.ui.BackNavigationButton
+import ru.stersh.youamp.core.ui.EmptyLayout
+import ru.stersh.youamp.core.ui.ErrorLayout
+import ru.stersh.youamp.core.ui.HeaderLayout
+import ru.stersh.youamp.core.ui.HeaderTitle
+import ru.stersh.youamp.core.ui.PlayAllButton
+import ru.stersh.youamp.core.ui.PlayShuffledButton
+import ru.stersh.youamp.core.ui.SkeletonLayout
+import ru.stersh.youamp.feature.album.favorites.R
+
+@Composable
+fun FavoriteAlbumsScreen(
+    onAlbumClick: (id: String) -> Unit,
+    onBackClick: () -> Unit
+) {
+    val viewModel: FavoriteAlbumsViewModel = koinViewModel()
+    val state by viewModel.state.collectAsStateWithLifecycle()
+
+    FavoriteAlbumsScreen(
+        state = state,
+        onPlayAll = viewModel::playAll,
+        onPlayShuffled = viewModel::playShuffled,
+        onRetry = viewModel::retry,
+        onRefresh = viewModel::refresh,
+        onAlbumClick = onAlbumClick,
+        onBackClick = onBackClick
+    )
+}
+
+@Composable
+private fun FavoriteAlbumsScreen(
+    state: StateUi,
+    onPlayAll: () -> Unit,
+    onPlayShuffled: () -> Unit,
+    onRetry: () -> Unit,
+    onRefresh: () -> Unit,
+    onAlbumClick: (id: String) -> Unit,
+    onBackClick: () -> Unit
+) {
+    Scaffold(
+        topBar = {
+            TopAppBar(
+                title = {},
+                navigationIcon = {
+                    BackNavigationButton(onClick = onBackClick)
+                }
+            )
+        }
+    ) {
+        PullToRefreshBox(
+            isRefreshing = state.isRefreshing,
+            onRefresh = onRefresh,
+            modifier = Modifier.padding(it)
+        ) {
+            when {
+                state.progress -> {
+                    Progress()
+                }
+
+                state.error -> {
+                    ErrorLayout(onRetry = onRetry)
+                }
+
+                state.data != null && state.data.albums.isEmpty() -> {
+                    EmptyLayout(
+                        modifier = Modifier.verticalScroll(
+                            state = rememberScrollState()
+                        )
+                    )
+                }
+
+                state.data?.albums != null -> {
+                    LazyVerticalGrid(
+                        columns = GridCells.Fixed(2),
+                        contentPadding = PaddingValues(16.dp),
+                        horizontalArrangement = Arrangement.spacedBy(8.dp),
+                        verticalArrangement = Arrangement.spacedBy(8.dp),
+                        modifier = Modifier.fillMaxSize()
+                    ) {
+                        item(
+                            contentType = "header",
+                            key = "header",
+                            span = { GridItemSpan(2) }
+                        ) {
+                            HeaderLayout(
+                                title = {
+                                    HeaderTitle(text = stringResource(R.string.favorite_albums_title))
+                                },
+                                actions = {
+                                    PlayAllButton(
+                                        onClick = onPlayAll
+                                    )
+                                    PlayShuffledButton(
+                                        onClick = onPlayShuffled
+                                    )
+                                }
+                            )
+                        }
+                        items(
+                            items = state.data.albums,
+                            contentType = { "album" },
+                            key = { "album_${it.id}" }
+                        ) { album ->
+                            AlbumItem(
+                                title = album.title,
+                                onClick = { onAlbumClick(album.id) },
+                                artist = album.artist,
+                                artworkUrl = album.artworkUrl
+                            )
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+@Composable
+private fun Progress() {
+    SkeletonLayout {
+        repeat(10) {
+            ListItem(
+                headlineContent = {
+                    Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
+                        SkeletonItem(modifier = Modifier.size(width = 130.dp, height = 16.dp))
+                        SkeletonItem(modifier = Modifier.size(width = 200.dp, height = 16.dp))
+                    }
+                },
+                leadingContent = {
+                    SkeletonItem(modifier = Modifier.size(48.dp))
+                }
+            )
+        }
+    }
+}
+
+@Preview
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun FavoriteAlbumsScreenPreview() {
+    MaterialTheme {
+        val albums = listOf(
+            AlbumUi(
+                id = "1",
+                title = "Best alubm in the world 1",
+                artist = "Best artist in the world 1",
+                artworkUrl = null
+            ),
+            AlbumUi(
+                id = "2",
+                title = "Best alubm in the world 2",
+                artist = "Best artist in the world 1",
+                artworkUrl = null
+            ),
+            AlbumUi(
+                id = "3",
+                title = "Best alubm in the world 3",
+                artist = "Best artist in the world 1",
+                artworkUrl = null
+            ),
+            AlbumUi(
+                id = "4",
+                title = "Best alubm in the world 4",
+                artist = "Best artist in the world 1",
+                artworkUrl = null
+            ),
+            AlbumUi(
+                id = "5",
+                title = "Best alubm in the world 5",
+                artist = "Best artist in the world 1",
+                artworkUrl = null
+            ),
+        )
+        val state = StateUi(
+            progress = false,
+            isRefreshing = false,
+            error = false,
+            data = DataUi(
+                albums = albums
+            )
+        )
+        FavoriteAlbumsScreen(
+            state = state,
+            onPlayAll = {},
+            onPlayShuffled = {},
+            onRetry = {},
+            onRefresh = {},
+            onAlbumClick = {},
+            onBackClick = {}
+        )
+    }
+}
\ No newline at end of file
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/FavoriteAlbumsViewModel.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/FavoriteAlbumsViewModel.kt
new file mode 100644
index 00000000..bdde0a47
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/FavoriteAlbumsViewModel.kt
@@ -0,0 +1,100 @@
+package ru.stresh.youamp.feature.album.favorites.ui
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+import ru.stersh.youamp.shared.player.queue.AudioSource
+import ru.stersh.youamp.shared.player.queue.PlayerQueueAudioSourceManager
+import ru.stresh.youamp.feature.album.favorites.domain.FavoriteAlbumsRepository
+import timber.log.Timber
+
+internal class FavoriteAlbumsViewModel(
+    private val favoriteAlbumsRepository: FavoriteAlbumsRepository,
+    private val playerQueueAudioSourceManager: PlayerQueueAudioSourceManager
+) : ViewModel() {
+    private val _state = MutableStateFlow(StateUi())
+    val state: StateFlow<StateUi>
+        get() = _state
+
+    private var getFavoritesJob: Job? = null
+
+    init {
+        retry()
+    }
+
+    fun playAll() = viewModelScope.launch {
+        playFavorites()
+    }
+
+    fun playShuffled() = viewModelScope.launch {
+        playFavorites(true)
+    }
+
+    fun refresh() {
+        _state.update {
+            it.copy(isRefreshing = true)
+        }
+        getFavorites()
+    }
+
+    fun retry() {
+        _state.update {
+            it.copy(
+                progress = true,
+                isRefreshing = false,
+                error = false,
+                data = null
+            )
+        }
+        getFavorites()
+    }
+
+    private suspend fun playFavorites(shuffled: Boolean = false) {
+        val favorites = runCatching { favoriteAlbumsRepository.getFavorites().first() }
+            .onFailure { Timber.w(it) }
+            .getOrNull()
+            ?: return
+
+        val sources = favorites.albums.map {
+            AudioSource.Album(id = it.id)
+        }
+        playerQueueAudioSourceManager.playSource(*sources.toTypedArray(), shuffled = shuffled)
+    }
+
+    private fun getFavorites() {
+        getFavoritesJob?.cancel()
+        getFavoritesJob = viewModelScope.launch {
+            favoriteAlbumsRepository
+                .getFavorites()
+                .map { it.toUi() }
+                .catch { throwable ->
+                    Timber.w(throwable)
+                    _state.update {
+                        it.copy(
+                            progress = false,
+                            isRefreshing = false,
+                            error = true,
+                            data = null
+                        )
+                    }
+                }
+                .collect { favorites ->
+                    _state.update {
+                        it.copy(
+                            progress = false,
+                            isRefreshing = false,
+                            error = false,
+                            data = favorites
+                        )
+                    }
+                }
+        }
+    }
+}
\ No newline at end of file
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/Mapper.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/Mapper.kt
new file mode 100644
index 00000000..4503d2a3
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/Mapper.kt
@@ -0,0 +1,17 @@
+package ru.stresh.youamp.feature.album.favorites.ui
+
+import ru.stresh.youamp.feature.album.favorites.domain.Album
+import ru.stresh.youamp.feature.album.favorites.domain.Favorites
+
+internal fun Favorites.toUi(): DataUi {
+    return DataUi(
+        albums = albums.map { it.toUi() }
+    )
+}
+
+private fun Album.toUi() = AlbumUi(
+    id = id,
+    title = title,
+    artist = artist,
+    artworkUrl = artworkUrl
+)
\ No newline at end of file
diff --git a/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/StateUi.kt b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/StateUi.kt
new file mode 100644
index 00000000..23a2937c
--- /dev/null
+++ b/feature/album/favorites/src/main/java/ru/stresh/youamp/feature/album/favorites/ui/StateUi.kt
@@ -0,0 +1,22 @@
+package ru.stresh.youamp.feature.album.favorites.ui
+
+import androidx.compose.runtime.Immutable
+
+internal data class StateUi(
+    val progress: Boolean = true,
+    val isRefreshing: Boolean = false,
+    val error: Boolean = false,
+    val data: DataUi? = null
+)
+
+@Immutable
+internal data class DataUi(
+    val albums: List<AlbumUi>
+)
+
+internal class AlbumUi(
+    val id: String,
+    val title: String,
+    val artist: String?,
+    val artworkUrl: String?
+)
\ No newline at end of file
diff --git a/feature/album/favorites/src/main/res/values/strings.xml b/feature/album/favorites/src/main/res/values/strings.xml
new file mode 100644
index 00000000..3b200c84
--- /dev/null
+++ b/feature/album/favorites/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="favorite_albums_title">Favorite albums</string>
+</resources>
\ No newline at end of file
diff --git a/feature/album/list/src/main/java/ru/stersh/youamp/feature/albums/Di.kt b/feature/album/list/src/main/java/ru/stersh/youamp/feature/albums/Di.kt
index 305d109d..eac9449c 100644
--- a/feature/album/list/src/main/java/ru/stersh/youamp/feature/albums/Di.kt
+++ b/feature/album/list/src/main/java/ru/stersh/youamp/feature/albums/Di.kt
@@ -6,7 +6,7 @@ import ru.stersh.youamp.feature.albums.data.AlbumsRepositoryImpl
 import ru.stersh.youamp.feature.albums.domain.AlbumsRepository
 import ru.stersh.youamp.feature.albums.ui.AlbumsViewModel
 
-val albumsModule = module {
+val albumListModule = module {
     single<AlbumsRepository> { AlbumsRepositoryImpl(get()) }
     viewModel { AlbumsViewModel(get(), get()) }
 }
\ No newline at end of file
diff --git a/feature/artist/favorites/.gitignore b/feature/artist/favorites/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/feature/artist/favorites/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/feature/artist/favorites/build.gradle b/feature/artist/favorites/build.gradle
new file mode 100644
index 00000000..95c501cd
--- /dev/null
+++ b/feature/artist/favorites/build.gradle
@@ -0,0 +1,22 @@
+plugins {
+    alias(libs.plugins.android.library)
+    alias(libs.plugins.kotlin.android)
+    alias(libs.plugins.kotlin.compose.compiler)
+}
+
+apply from: "${project.rootDir}/buildscripts/android-feature-module.gradle"
+
+android {
+    namespace 'ru.stersh.youamp.feature.artist.favorites'
+}
+
+dependencies {
+    implementation project(":core:ui")
+    implementation project(":core:api")
+    implementation project(":shared:player")
+    implementation project(":shared:favorites")
+    implementation(libs.bundles.lifecycle)
+    implementation(libs.coil.compose)
+    implementation(libs.bundles.koin)
+    implementation(libs.timber)
+}
\ No newline at end of file
diff --git a/feature/artist/favorites/consumer-rules.pro b/feature/artist/favorites/consumer-rules.pro
new file mode 100644
index 00000000..e69de29b
diff --git a/feature/artist/favorites/proguard-rules.pro b/feature/artist/favorites/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/feature/artist/favorites/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/AndroidManifest.xml b/feature/artist/favorites/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..44008a43
--- /dev/null
+++ b/feature/artist/favorites/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest>
+
+</manifest>
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/Di.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/Di.kt
new file mode 100644
index 00000000..1f1e083e
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/Di.kt
@@ -0,0 +1,12 @@
+package ru.stresh.youamp.feature.artist.favorites
+
+import org.koin.core.module.dsl.viewModel
+import org.koin.dsl.module
+import ru.stresh.youamp.feature.artist.favorites.data.FavoriteArtistsRepositoryImpl
+import ru.stresh.youamp.feature.artist.favorites.domain.FavoriteArtistsRepository
+import ru.stresh.youamp.feature.artist.favorites.ui.FavoriteArtistViewModel
+
+val artistFavoritesModule = module {
+    single<FavoriteArtistsRepository> { FavoriteArtistsRepositoryImpl(get()) }
+    viewModel { FavoriteArtistViewModel(get(), get()) }
+}
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/data/FavoriteArtistsRepositoryImpl.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/data/FavoriteArtistsRepositoryImpl.kt
new file mode 100644
index 00000000..be931fbf
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/data/FavoriteArtistsRepositoryImpl.kt
@@ -0,0 +1,32 @@
+package ru.stresh.youamp.feature.artist.favorites.data
+
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import ru.stresh.youamp.feature.artist.favorites.domain.Artist
+import ru.stresh.youamp.feature.artist.favorites.domain.FavoriteArtistsRepository
+import ru.stresh.youamp.feature.artist.favorites.domain.Favorites
+import ru.stresh.youamp.shared.favorites.ArtistFavoritesStorage
+
+internal class FavoriteArtistsRepositoryImpl(
+    private val artistFavoritesStorage: ArtistFavoritesStorage
+) : FavoriteArtistsRepository {
+
+    override fun getFavorites(): Flow<Favorites> {
+        return artistFavoritesStorage
+            .flowArtists()
+            .map { favoriteAlbums ->
+                Favorites(
+                    artists = favoriteAlbums.map { it.toDomain() }
+                )
+            }
+    }
+
+    private fun ru.stresh.youamp.shared.favorites.Artist.toDomain(): Artist {
+        return Artist(
+            id = id,
+            name = name,
+            artworkUrl = artworkUrl,
+            userRating = userRating
+        )
+    }
+}
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/Artist.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/Artist.kt
new file mode 100644
index 00000000..f0e93e69
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/Artist.kt
@@ -0,0 +1,8 @@
+package ru.stresh.youamp.feature.artist.favorites.domain
+
+internal data class Artist(
+    val id: String,
+    val name: String,
+    val artworkUrl: String?,
+    val userRating: Int?
+)
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/FavoriteArtistsRepository.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/FavoriteArtistsRepository.kt
new file mode 100644
index 00000000..bf638f02
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/FavoriteArtistsRepository.kt
@@ -0,0 +1,7 @@
+package ru.stresh.youamp.feature.artist.favorites.domain
+
+import kotlinx.coroutines.flow.Flow
+
+internal interface FavoriteArtistsRepository {
+    fun getFavorites(): Flow<Favorites>
+}
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/Favorites.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/Favorites.kt
new file mode 100644
index 00000000..53389a49
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/domain/Favorites.kt
@@ -0,0 +1,5 @@
+package ru.stresh.youamp.feature.artist.favorites.domain
+
+internal data class Favorites(
+    val artists: List<Artist>
+)
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/FavoriteArtistScreen.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/FavoriteArtistScreen.kt
new file mode 100644
index 00000000..10aa8241
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/FavoriteArtistScreen.kt
@@ -0,0 +1,215 @@
+package ru.stresh.youamp.feature.artist.favorites.ui
+
+import android.content.res.Configuration
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.GridItemSpan
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.items
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.ListItem
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.pulltorefresh.PullToRefreshBox
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import org.koin.androidx.compose.koinViewModel
+import ru.stersh.youamp.core.ui.ArtistItem
+import ru.stersh.youamp.core.ui.BackNavigationButton
+import ru.stersh.youamp.core.ui.EmptyLayout
+import ru.stersh.youamp.core.ui.ErrorLayout
+import ru.stersh.youamp.core.ui.HeaderLayout
+import ru.stersh.youamp.core.ui.HeaderTitle
+import ru.stersh.youamp.core.ui.PlayAllButton
+import ru.stersh.youamp.core.ui.PlayShuffledButton
+import ru.stersh.youamp.core.ui.SkeletonLayout
+import ru.stersh.youamp.feature.artist.favorites.R
+
+@Composable
+fun FavoriteArtistsScreen(
+    onArtistClick: (id: String) -> Unit,
+    onBackClick: () -> Unit
+) {
+    val viewModel: FavoriteArtistViewModel = koinViewModel()
+    val state by viewModel.state.collectAsStateWithLifecycle()
+
+    FavoriteArtistsScreen(
+        state = state,
+        onPlayAll = viewModel::playAll,
+        onPlayShuffled = viewModel::playShuffled,
+        onRetry = viewModel::retry,
+        onRefresh = viewModel::refresh,
+        onArtistClick = onArtistClick,
+        onBackClick = onBackClick
+    )
+}
+
+@Composable
+private fun FavoriteArtistsScreen(
+    state: StateUi,
+    onPlayAll: () -> Unit,
+    onPlayShuffled: () -> Unit,
+    onRetry: () -> Unit,
+    onRefresh: () -> Unit,
+    onArtistClick: (id: String) -> Unit,
+    onBackClick: () -> Unit
+) {
+    Scaffold(
+        topBar = {
+            TopAppBar(
+                title = {},
+                navigationIcon = {
+                    BackNavigationButton(onClick = onBackClick)
+                }
+            )
+        }
+    ) {
+        PullToRefreshBox(
+            isRefreshing = state.isRefreshing,
+            onRefresh = onRefresh,
+            modifier = Modifier.padding(it)
+        ) {
+            when {
+                state.progress -> {
+                    Progress()
+                }
+
+                state.error -> {
+                    ErrorLayout(onRetry = onRetry)
+                }
+
+                state.data != null && state.data.artists.isEmpty() -> {
+                    EmptyLayout(
+                        modifier = Modifier.verticalScroll(
+                            state = rememberScrollState()
+                        )
+                    )
+                }
+
+                state.data?.artists != null -> {
+                    LazyVerticalGrid(
+                        columns = GridCells.Fixed(2),
+                        contentPadding = PaddingValues(16.dp),
+                        horizontalArrangement = Arrangement.spacedBy(8.dp),
+                        verticalArrangement = Arrangement.spacedBy(8.dp),
+                        modifier = Modifier.fillMaxSize()
+                    ) {
+                        item(
+                            contentType = "header",
+                            key = "header",
+                            span = { GridItemSpan(2) }
+                        ) {
+                            HeaderLayout(
+                                title = {
+                                    HeaderTitle(text = stringResource(R.string.favorite_artists_title))
+                                },
+                                actions = {
+                                    PlayAllButton(
+                                        onClick = onPlayAll
+                                    )
+                                    PlayShuffledButton(
+                                        onClick = onPlayShuffled
+                                    )
+                                }
+                            )
+                        }
+                        items(
+                            items = state.data.artists,
+                            contentType = { "artist" },
+                            key = { "artist_${it.id}" }
+                        ) { album ->
+                            ArtistItem(
+                                name = album.name,
+                                onClick = { onArtistClick(album.id) },
+                                artworkUrl = album.artworkUrl
+                            )
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+@Composable
+private fun Progress() {
+    SkeletonLayout {
+        repeat(10) {
+            ListItem(
+                headlineContent = {
+                    Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
+                        SkeletonItem(modifier = Modifier.size(width = 130.dp, height = 16.dp))
+                        SkeletonItem(modifier = Modifier.size(width = 200.dp, height = 16.dp))
+                    }
+                },
+                leadingContent = {
+                    SkeletonItem(modifier = Modifier.size(48.dp))
+                }
+            )
+        }
+    }
+}
+
+@Preview
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun FavoriteArtistsScreenPreview() {
+    MaterialTheme {
+        val albums = listOf(
+            ArtistUi(
+                id = "1",
+                name = "Artist 1",
+                artworkUrl = null
+            ),
+            ArtistUi(
+                id = "2",
+                name = "Artist 2",
+                artworkUrl = null
+            ),
+            ArtistUi(
+                id = "3",
+                name = "Artist 3",
+                artworkUrl = null
+            ),
+            ArtistUi(
+                id = "4",
+                name = "Artist 4",
+                artworkUrl = null
+            ),
+            ArtistUi(
+                id = "5",
+                name = "Artist 5",
+                artworkUrl = null
+            ),
+        )
+        val state = StateUi(
+            progress = false,
+            isRefreshing = false,
+            error = false,
+            data = DataUi(
+                artists = albums
+            )
+        )
+        FavoriteArtistsScreen(
+            state = state,
+            onPlayAll = {},
+            onPlayShuffled = {},
+            onRetry = {},
+            onRefresh = {},
+            onArtistClick = {},
+            onBackClick = {}
+        )
+    }
+}
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/FavoriteArtistViewModel.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/FavoriteArtistViewModel.kt
new file mode 100644
index 00000000..e976fc5c
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/FavoriteArtistViewModel.kt
@@ -0,0 +1,100 @@
+package ru.stresh.youamp.feature.artist.favorites.ui
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+import ru.stersh.youamp.shared.player.queue.AudioSource
+import ru.stersh.youamp.shared.player.queue.PlayerQueueAudioSourceManager
+import ru.stresh.youamp.feature.artist.favorites.domain.FavoriteArtistsRepository
+import timber.log.Timber
+
+internal class FavoriteArtistViewModel(
+    private val favoriteArtistsRepository: FavoriteArtistsRepository,
+    private val playerQueueAudioSourceManager: PlayerQueueAudioSourceManager
+) : ViewModel() {
+    private val _state = MutableStateFlow(StateUi())
+    val state: StateFlow<StateUi>
+        get() = _state
+
+    private var getFavoritesJob: Job? = null
+
+    init {
+        retry()
+    }
+
+    fun playAll() = viewModelScope.launch {
+        playFavorites()
+    }
+
+    fun playShuffled() = viewModelScope.launch {
+        playFavorites(true)
+    }
+
+    fun refresh() {
+        _state.update {
+            it.copy(isRefreshing = true)
+        }
+        getFavorites()
+    }
+
+    fun retry() {
+        _state.update {
+            it.copy(
+                progress = true,
+                isRefreshing = false,
+                error = false,
+                data = null
+            )
+        }
+        getFavorites()
+    }
+
+    private suspend fun playFavorites(shuffled: Boolean = false) {
+        val favorites = runCatching { favoriteArtistsRepository.getFavorites().first() }
+            .onFailure { Timber.w(it) }
+            .getOrNull()
+            ?: return
+
+        val sources = favorites.artists.map {
+            AudioSource.Artist(id = it.id)
+        }
+        playerQueueAudioSourceManager.playSource(*sources.toTypedArray(), shuffled = shuffled)
+    }
+
+    private fun getFavorites() {
+        getFavoritesJob?.cancel()
+        getFavoritesJob = viewModelScope.launch {
+            favoriteArtistsRepository
+                .getFavorites()
+                .map { it.toUi() }
+                .catch { throwable ->
+                    Timber.w(throwable)
+                    _state.update {
+                        it.copy(
+                            progress = false,
+                            isRefreshing = false,
+                            error = true,
+                            data = null
+                        )
+                    }
+                }
+                .collect { favorites ->
+                    _state.update {
+                        it.copy(
+                            progress = false,
+                            isRefreshing = false,
+                            error = false,
+                            data = favorites
+                        )
+                    }
+                }
+        }
+    }
+}
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/Mapper.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/Mapper.kt
new file mode 100644
index 00000000..96241f66
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/Mapper.kt
@@ -0,0 +1,16 @@
+package ru.stresh.youamp.feature.artist.favorites.ui
+
+import ru.stresh.youamp.feature.artist.favorites.domain.Artist
+import ru.stresh.youamp.feature.artist.favorites.domain.Favorites
+
+internal fun Favorites.toUi(): DataUi {
+    return DataUi(
+        artists = artists.map { it.toUi() }
+    )
+}
+
+private fun Artist.toUi() = ArtistUi(
+    id = id,
+    name = name,
+    artworkUrl = artworkUrl
+)
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/StateUi.kt b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/StateUi.kt
new file mode 100644
index 00000000..e91e1065
--- /dev/null
+++ b/feature/artist/favorites/src/main/java/ru/stresh/youamp/feature/artist/favorites/ui/StateUi.kt
@@ -0,0 +1,21 @@
+package ru.stresh.youamp.feature.artist.favorites.ui
+
+import androidx.compose.runtime.Immutable
+
+internal data class StateUi(
+    val progress: Boolean = true,
+    val isRefreshing: Boolean = false,
+    val error: Boolean = false,
+    val data: DataUi? = null
+)
+
+@Immutable
+internal data class DataUi(
+    val artists: List<ArtistUi>
+)
+
+internal class ArtistUi(
+    val id: String,
+    val name: String,
+    val artworkUrl: String?
+)
\ No newline at end of file
diff --git a/feature/artist/favorites/src/main/res/values/strings.xml b/feature/artist/favorites/src/main/res/values/strings.xml
new file mode 100644
index 00000000..71b90385
--- /dev/null
+++ b/feature/artist/favorites/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="favorite_artists_title">Favorite artists</string>
+</resources>
\ No newline at end of file
diff --git a/feature/artist/list/src/main/java/ru/stersh/youamp/feature/artists/Di.kt b/feature/artist/list/src/main/java/ru/stersh/youamp/feature/artists/Di.kt
index a6986e03..119e51dc 100644
--- a/feature/artist/list/src/main/java/ru/stersh/youamp/feature/artists/Di.kt
+++ b/feature/artist/list/src/main/java/ru/stersh/youamp/feature/artists/Di.kt
@@ -6,7 +6,7 @@ import ru.stersh.youamp.feature.artists.data.ArtistsRepositoryImpl
 import ru.stersh.youamp.feature.artists.domain.ArtistsRepository
 import ru.stersh.youamp.feature.artists.ui.ArtistsViewModel
 
-val artistsModule = module {
+val artistListModule = module {
     single<ArtistsRepository> { ArtistsRepositoryImpl(get()) }
     viewModel { ArtistsViewModel(get()) }
 }
\ No newline at end of file
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/Di.kt b/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/Di.kt
deleted file mode 100644
index 864115bd..00000000
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/Di.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package ru.stresh.youamp.feature.favorite.list
-
-import org.koin.core.module.dsl.viewModel
-import org.koin.dsl.module
-import ru.stresh.youamp.feature.favorite.list.data.FavoriteSongsRepositoryImpl
-import ru.stresh.youamp.feature.favorite.list.domain.FavoriteSongsRepository
-import ru.stresh.youamp.feature.favorite.list.ui.FavoriteSongsViewModel
-
-val favoriteListModule = module {
-    single<FavoriteSongsRepository> { FavoriteSongsRepositoryImpl(get()) }
-    viewModel { FavoriteSongsViewModel(get(), get()) }
-}
\ No newline at end of file
diff --git a/feature/song/favorites/.gitignore b/feature/song/favorites/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/feature/song/favorites/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/feature/favorite/list/build.gradle b/feature/song/favorites/build.gradle
similarity index 91%
rename from feature/favorite/list/build.gradle
rename to feature/song/favorites/build.gradle
index a9e1c1e7..0b8f4889 100644
--- a/feature/favorite/list/build.gradle
+++ b/feature/song/favorites/build.gradle
@@ -7,7 +7,7 @@ plugins {
 apply from: "${project.rootDir}/buildscripts/android-feature-module.gradle"
 
 android {
-    namespace 'ru.stersh.youamp.feature.favorite.list'
+    namespace 'ru.stersh.youamp.feature.song.favorites'
 }
 
 dependencies {
diff --git a/feature/song/favorites/consumer-rules.pro b/feature/song/favorites/consumer-rules.pro
new file mode 100644
index 00000000..e69de29b
diff --git a/feature/song/favorites/proguard-rules.pro b/feature/song/favorites/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/feature/song/favorites/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/feature/song/favorites/src/main/AndroidManifest.xml b/feature/song/favorites/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..44008a43
--- /dev/null
+++ b/feature/song/favorites/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest>
+
+</manifest>
\ No newline at end of file
diff --git a/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/Di.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/Di.kt
new file mode 100644
index 00000000..37ddc6a0
--- /dev/null
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/Di.kt
@@ -0,0 +1,12 @@
+package ru.stresh.youamp.feature.song.favorites
+
+import org.koin.core.module.dsl.viewModel
+import org.koin.dsl.module
+import ru.stresh.youamp.feature.song.favorites.data.FavoriteSongsRepositoryImpl
+import ru.stresh.youamp.feature.song.favorites.domain.FavoriteSongsRepository
+import ru.stresh.youamp.feature.song.favorites.ui.FavoriteSongsViewModel
+
+val songFavoritesModule = module {
+    single<FavoriteSongsRepository> { FavoriteSongsRepositoryImpl(get()) }
+    viewModel { FavoriteSongsViewModel(get(), get()) }
+}
\ No newline at end of file
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/data/FavoriteSongsRepositoryImpl.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/data/FavoriteSongsRepositoryImpl.kt
similarity index 76%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/data/FavoriteSongsRepositoryImpl.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/data/FavoriteSongsRepositoryImpl.kt
index 18360d56..6799ce53 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/data/FavoriteSongsRepositoryImpl.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/data/FavoriteSongsRepositoryImpl.kt
@@ -1,10 +1,10 @@
-package ru.stresh.youamp.feature.favorite.list.data
+package ru.stresh.youamp.feature.song.favorites.data
 
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.map
-import ru.stresh.youamp.feature.favorite.list.domain.FavoriteSongsRepository
-import ru.stresh.youamp.feature.favorite.list.domain.Favorites
-import ru.stresh.youamp.feature.favorite.list.domain.Song
+import ru.stresh.youamp.feature.song.favorites.domain.FavoriteSongsRepository
+import ru.stresh.youamp.feature.song.favorites.domain.Favorites
+import ru.stresh.youamp.feature.song.favorites.domain.Song
 import ru.stresh.youamp.shared.favorites.SongFavoritesStorage
 
 internal class FavoriteSongsRepositoryImpl(
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/FavoriteSongsRepository.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/FavoriteSongsRepository.kt
similarity index 69%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/FavoriteSongsRepository.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/FavoriteSongsRepository.kt
index c1cff606..04503589 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/FavoriteSongsRepository.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/FavoriteSongsRepository.kt
@@ -1,4 +1,4 @@
-package ru.stresh.youamp.feature.favorite.list.domain
+package ru.stresh.youamp.feature.song.favorites.domain
 
 import kotlinx.coroutines.flow.Flow
 
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/Favorites.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/Favorites.kt
similarity index 52%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/Favorites.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/Favorites.kt
index 93a4ffd3..285d73f1 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/Favorites.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/Favorites.kt
@@ -1,4 +1,4 @@
-package ru.stresh.youamp.feature.favorite.list.domain
+package ru.stresh.youamp.feature.song.favorites.domain
 
 internal data class Favorites(
     val songs: List<Song>
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/Song.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/Song.kt
similarity index 73%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/Song.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/Song.kt
index 9f6d25e5..18a167f4 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/domain/Song.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/domain/Song.kt
@@ -1,4 +1,4 @@
-package ru.stresh.youamp.feature.favorite.list.domain
+package ru.stresh.youamp.feature.song.favorites.domain
 
 internal data class Song(
     val id: String,
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/FavoriteSongsScreen.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/FavoriteSongsScreen.kt
similarity index 98%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/FavoriteSongsScreen.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/FavoriteSongsScreen.kt
index 7713ba85..746a2053 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/FavoriteSongsScreen.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/FavoriteSongsScreen.kt
@@ -1,4 +1,4 @@
-package ru.stresh.youamp.feature.favorite.list.ui
+package ru.stresh.youamp.feature.song.favorites.ui
 
 import android.content.res.Configuration
 import androidx.compose.foundation.background
@@ -39,7 +39,7 @@ import ru.stersh.youamp.core.ui.HeaderTitle
 import ru.stersh.youamp.core.ui.PlayAllButton
 import ru.stersh.youamp.core.ui.PlayShuffledButton
 import ru.stersh.youamp.core.ui.SkeletonLayout
-import ru.stersh.youamp.feature.favorite.list.R
+import ru.stersh.youamp.feature.song.favorites.R
 
 @Composable
 fun FavoriteSongsScreen(
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/FavoriteSongsViewModel.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/FavoriteSongsViewModel.kt
similarity index 96%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/FavoriteSongsViewModel.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/FavoriteSongsViewModel.kt
index 9336ddfb..13219cfd 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/FavoriteSongsViewModel.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/FavoriteSongsViewModel.kt
@@ -1,4 +1,4 @@
-package ru.stresh.youamp.feature.favorite.list.ui
+package ru.stresh.youamp.feature.song.favorites.ui
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
@@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.update
 import kotlinx.coroutines.launch
 import ru.stersh.youamp.shared.player.queue.AudioSource
 import ru.stersh.youamp.shared.player.queue.PlayerQueueAudioSourceManager
-import ru.stresh.youamp.feature.favorite.list.domain.FavoriteSongsRepository
+import ru.stresh.youamp.feature.song.favorites.domain.FavoriteSongsRepository
 import timber.log.Timber
 
 internal class FavoriteSongsViewModel(
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/Mapper.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/Mapper.kt
similarity index 56%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/Mapper.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/Mapper.kt
index 488cd084..3534575f 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/Mapper.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/Mapper.kt
@@ -1,7 +1,7 @@
-package ru.stresh.youamp.feature.favorite.list.ui
+package ru.stresh.youamp.feature.song.favorites.ui
 
-import ru.stresh.youamp.feature.favorite.list.domain.Favorites
-import ru.stresh.youamp.feature.favorite.list.domain.Song
+import ru.stresh.youamp.feature.song.favorites.domain.Favorites
+import ru.stresh.youamp.feature.song.favorites.domain.Song
 
 internal fun Favorites.toUi(): DataUi {
     return DataUi(
diff --git a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/StateUi.kt b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/StateUi.kt
similarity index 88%
rename from feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/StateUi.kt
rename to feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/StateUi.kt
index 15736394..95c83791 100644
--- a/feature/favorite/list/src/main/java/ru/stresh/youamp/feature/favorite/list/ui/StateUi.kt
+++ b/feature/song/favorites/src/main/java/ru/stresh/youamp/feature/song/favorites/ui/StateUi.kt
@@ -1,4 +1,4 @@
-package ru.stresh.youamp.feature.favorite.list.ui
+package ru.stresh.youamp.feature.song.favorites.ui
 
 import androidx.compose.runtime.Immutable
 
diff --git a/feature/favorite/list/src/main/res/values-fr-rFR/strings.xml b/feature/song/favorites/src/main/res/values-fr-rFR/strings.xml
similarity index 100%
rename from feature/favorite/list/src/main/res/values-fr-rFR/strings.xml
rename to feature/song/favorites/src/main/res/values-fr-rFR/strings.xml
diff --git a/feature/favorite/list/src/main/res/values-it-rIT/strings.xml b/feature/song/favorites/src/main/res/values-it-rIT/strings.xml
similarity index 100%
rename from feature/favorite/list/src/main/res/values-it-rIT/strings.xml
rename to feature/song/favorites/src/main/res/values-it-rIT/strings.xml
diff --git a/feature/favorite/list/src/main/res/values-ru-rRU/strings.xml b/feature/song/favorites/src/main/res/values-ru-rRU/strings.xml
similarity index 100%
rename from feature/favorite/list/src/main/res/values-ru-rRU/strings.xml
rename to feature/song/favorites/src/main/res/values-ru-rRU/strings.xml
diff --git a/feature/favorite/list/src/main/res/values/strings.xml b/feature/song/favorites/src/main/res/values/strings.xml
similarity index 100%
rename from feature/favorite/list/src/main/res/values/strings.xml
rename to feature/song/favorites/src/main/res/values/strings.xml
diff --git a/settings.gradle b/settings.gradle
index e9de362a..636dc2e0 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -23,6 +23,7 @@ include ':core:properties'
 include ':shared:player'
 include ':feature:album:list'
 include ':feature:album:info'
+include ':feature:album:favorites'
 include ':feature:main'
 include ':feature:player:mini'
 include ':feature:player:screen'
@@ -31,11 +32,11 @@ include ':feature:server:create'
 include ':feature:server:list'
 include ':feature:artist:list'
 include ':feature:artist:info'
+include ':feature:artist:favorites'
 include ':feature:playlist:list'
 include ':feature:playlist:info'
 include ':feature:search'
 include ':feature:song:info'
-include ':feature:favorite:list'
 include ':feature:about'
 include ':feature:settings'
 include ':feature:personal'
@@ -44,3 +45,4 @@ include ':feature:library'
 include ':shared:favorites'
 include ':shared:song:random'
 include ':feature:song:random'
+include ':feature:song:favorites'
diff --git a/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Album.kt b/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Album.kt
index 5a2f9542..f25eef29 100644
--- a/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Album.kt
+++ b/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Album.kt
@@ -5,5 +5,6 @@ data class Album(
     val title: String,
     val artist: String?,
     val artistId: String?,
-    val artworkUrl: String?
+    val artworkUrl: String?,
+    val userRating: Int?
 )
diff --git a/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Artist.kt b/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Artist.kt
index 0eef2522..2f0c549e 100644
--- a/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Artist.kt
+++ b/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/Artist.kt
@@ -3,5 +3,6 @@ package ru.stresh.youamp.shared.favorites
 data class Artist(
     val id: String,
     val name: String,
-    val artworkUrl: String?
+    val artworkUrl: String?,
+    val userRating: Int?
 )
\ No newline at end of file
diff --git a/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/FavoritesStorageImpl.kt b/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/FavoritesStorageImpl.kt
index 91077580..3b487f53 100644
--- a/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/FavoritesStorageImpl.kt
+++ b/shared/favorites/src/main/java/ru/stresh/youamp/shared/favorites/FavoritesStorageImpl.kt
@@ -133,14 +133,16 @@ internal class FavoritesStorageImpl(
                     title = requireNotNull(it.name ?: it.album),
                     artist = it.artist,
                     artistId = it.artistId,
-                    artworkUrl = api.getCoverArtUrl(it.coverArt)
+                    artworkUrl = api.getCoverArtUrl(it.coverArt),
+                    userRating = it.userRating
                 )
             }.orEmpty(),
             artists = newFavorites.starred2Result.artist?.map {
                 Artist(
                     id = it.id,
                     name = it.name,
-                    artworkUrl = api.getCoverArtUrl(it.coverArt)
+                    artworkUrl = api.getCoverArtUrl(it.coverArt),
+                    userRating = it.userRating
                 )
             }.orEmpty()
         )