diff --git a/index.html b/index.html
index 762a33a..34a8275 100644
--- a/index.html
+++ b/index.html
@@ -310,6 +310,10 @@
diff --git a/js/api.js b/js/api.js
index a3cc3e8..707c841 100644
--- a/js/api.js
+++ b/js/api.js
@@ -575,6 +575,27 @@ export class LosslessAPI {
+ async getSimilarArtists(artistId) {
+ const cached = await this.cache.get('similar_artists', artistId);
+ if (cached) return cached;
+
+ try {
+ const response = await this.fetchWithRetry(`/artist/similar/?id=${artistId}`, { type: 'api' });
+ const data = await response.json();
+
+ // Handle various response structures
+ const items = data.artists || data.items || data.data || (Array.isArray(data) ? data : []);
+
+ const result = items.map(artist => this.prepareArtist(artist));
+
+ await this.cache.set('similar_artists', artistId, result);
+ return result;
+ } catch (e) {
+ console.warn('Failed to fetch similar artists:', e);
+ return [];
+ }
+ }
+
normalizeTrackResponse(apiResponse) {
if (!apiResponse || typeof apiResponse !== 'object') {
return apiResponse;
diff --git a/js/ui.js b/js/ui.js
index 0c8a107..b74a023 100644
--- a/js/ui.js
+++ b/js/ui.js
@@ -938,6 +938,22 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) {
renderSection(`More albums from ${album.artist.name}`, artistData.albums);
renderSection(`EPs and Singles from ${album.artist.name}`, artistData.eps);
+ // Similar Artists
+ this.api.getSimilarArtists(album.artist.id).then(similar => {
+ if (similar && similar.length > 0) {
+ const section = document.createElement('section');
+ section.className = 'content-section album-more-section';
+ section.style.marginTop = '3rem';
+ section.innerHTML = `
+
Fans Also Like
+
+ ${similar.map(a => this.createArtistCardHTML(a)).join('')}
+
+ `;
+ document.getElementById('page-album').appendChild(section);
+ }
+ }).catch(e => console.warn('Failed to load similar artists:', e));
+
} catch (err) {
console.warn('Failed to load "More from artist":', err);
document.querySelectorAll('.album-more-section').forEach(el => el.remove());
@@ -1099,6 +1115,8 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) {
const albumsContainer = document.getElementById('artist-detail-albums');
const epsContainer = document.getElementById('artist-detail-eps');
const epsSection = document.getElementById('artist-section-eps');
+ const similarContainer = document.getElementById('artist-detail-similar');
+ const similarSection = document.getElementById('artist-section-similar');
const dlBtn = document.getElementById('download-discography-btn');
if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}
Download Discography`;
@@ -1110,10 +1128,26 @@ async showFullscreenCover(track, nextTrack, lyricsManager, audioPlayer) {
albumsContainer.innerHTML = this.createSkeletonCards(6, false);
if (epsContainer) epsContainer.innerHTML = this.createSkeletonCards(6, false);
if (epsSection) epsSection.style.display = 'none';
+ if (similarContainer) similarContainer.innerHTML = this.createSkeletonCards(6, true);
+ if (similarSection) similarSection.style.display = 'block';
try {
const artist = await this.api.getArtist(artistId);
+ // Similar Artists
+ if (similarContainer && similarSection) {
+ this.api.getSimilarArtists(artistId).then(similar => {
+ if (similar && similar.length > 0) {
+ similarContainer.innerHTML = similar.map(a => this.createArtistCardHTML(a)).join('');
+ similarSection.style.display = 'block';
+ } else {
+ similarSection.style.display = 'none';
+ }
+ }).catch(() => {
+ similarSection.style.display = 'none';
+ });
+ }
+
imageEl.src = this.api.getArtistPictureUrl(artist.picture, '750');
imageEl.style.backgroundColor = '';
nameEl.textContent = artist.name;