Index: frontend/src/components/PlaylistDropdown.tsx
===================================================================
--- frontend/src/components/PlaylistDropdown.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
+++ frontend/src/components/PlaylistDropdown.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -0,0 +1,252 @@
+import { useEffect, useRef, useState } from "react";
+import { createPortal } from "react-dom";
+import axiosInstance from "../api/axiosInstance";
+import { useCreatedPlaylists } from "../context/playlistContext";
+
+interface PlaylistDropdownProps {
+  songId: number;
+  isOpen: boolean;
+  onClose: () => void;
+  position?: { top: number; left: number };
+
+  usePortal?: boolean;
+
+  direction?: "above" | "below";
+
+  onCreateNewPlaylist?: () => void;
+}
+
+const PlaylistDropdown = ({
+  songId,
+  isOpen,
+  onClose,
+  position,
+  usePortal = false,
+  direction = "above",
+  onCreateNewPlaylist,
+}: PlaylistDropdownProps) => {
+  const { createdPlaylists, refreshPlaylists } = useCreatedPlaylists();
+  const [containingPlaylistIds, setContainingPlaylistIds] = useState<number[]>(
+    [],
+  );
+  const [loading, setLoading] = useState(false);
+  const [processingPlaylistId, setProcessingPlaylistId] = useState<
+    number | null
+  >(null);
+  const dropdownRef = useRef<HTMLDivElement>(null);
+
+  useEffect(() => {
+    if (isOpen && songId) {
+      const fetchPlaylistIds = async () => {
+        setLoading(true);
+        setContainingPlaylistIds([]);
+        try {
+          const response = await axiosInstance.get<number[]>(
+            `/playlists/song/${songId}`,
+          );
+          setContainingPlaylistIds(response.data);
+        } catch (error) {
+          console.error("Failed to fetch song presence:", error);
+        } finally {
+          setLoading(false);
+        }
+      };
+      fetchPlaylistIds();
+    } else {
+      setContainingPlaylistIds([]);
+    }
+  }, [isOpen, songId]);
+
+  useEffect(() => {
+    const handleClickOutside = (event: MouseEvent) => {
+      if (
+        dropdownRef.current &&
+        !dropdownRef.current.contains(event.target as Node)
+      ) {
+        onClose();
+      }
+    };
+
+    if (isOpen) {
+      document.addEventListener("mousedown", handleClickOutside);
+    }
+    return () => document.removeEventListener("mousedown", handleClickOutside);
+  }, [isOpen, onClose]);
+
+  const handleTogglePlaylist = async (playlistId: number, songId: number) => {
+    if (processingPlaylistId !== null) return;
+
+    setProcessingPlaylistId(playlistId);
+
+    try {
+      const response = await axiosInstance.post<{
+        playlistId: number;
+        isSongAddedToPlaylist: boolean;
+      }>(`/playlists/${playlistId}/song/${songId}`);
+
+      const { playlistId: returnedPlaylistId, isSongAddedToPlaylist } =
+        response.data;
+
+      if (isSongAddedToPlaylist) {
+        setContainingPlaylistIds((prev) =>
+          prev.includes(returnedPlaylistId)
+            ? prev
+            : [...prev, returnedPlaylistId],
+        );
+      } else {
+        setContainingPlaylistIds((prev) =>
+          prev.filter((id) => id !== returnedPlaylistId),
+        );
+      }
+    } catch (error) {
+      console.error("Failed to toggle playlist:", error);
+    } finally {
+      refreshPlaylists(true);
+      setTimeout(() => {
+        setProcessingPlaylistId(null);
+      }, 500);
+    }
+  };
+
+  const handleCreateNew = () => {
+    onCreateNewPlaylist?.();
+    onClose();
+  };
+
+  if (!isOpen) return null;
+
+  const inlinePositionClass =
+    direction === "below"
+      ? "absolute left-0 top-full mt-2"
+      : "absolute right-0 bottom-full mb-2";
+
+  const dropdownContent = (
+    <div
+      ref={dropdownRef}
+      className={`${usePortal ? "fixed" : inlinePositionClass} w-56 bg-[#282828] rounded-lg shadow-2xl py-2 z-[9999] border border-white/10 max-h-60 overflow-y-auto custom-scrollbar`}
+      style={
+        usePortal && position
+          ? {
+              top: position.top,
+              left: position.left,
+              transform:
+                direction === "below" ? undefined : "translateY(-100%)",
+            }
+          : undefined
+      }
+      onClick={(e) => e.stopPropagation()}
+    >
+      <div className="px-4 py-2 text-xs font-bold text-gray-400 uppercase tracking-wider border-b border-white/5 mb-1">
+        Add to playlist
+      </div>
+
+      {loading ? (
+        <div className="flex items-center justify-center py-4">
+          <div className="w-5 h-5 border-2 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
+        </div>
+      ) : createdPlaylists && createdPlaylists.length > 0 ? (
+        createdPlaylists.map((playlist) => {
+          const isProcessing = processingPlaylistId === playlist.id;
+          const isChecked = containingPlaylistIds.includes(playlist.id);
+
+          return (
+            <label
+              key={playlist.id}
+              className={`flex items-center px-4 py-2 hover:bg-white/10 transition-colors group/item ${
+                isProcessing ? "pointer-events-none" : "cursor-pointer"
+              }`}
+              onClick={(e) => e.stopPropagation()}
+            >
+              <div className="relative flex items-center justify-center">
+                <input
+                  type="checkbox"
+                  className="peer sr-only"
+                  checked={isChecked}
+                  disabled={processingPlaylistId !== null}
+                  onChange={() => handleTogglePlaylist(playlist.id, songId)}
+                />
+                <div
+                  className={`w-5 h-5 border-2 rounded bg-[#181818] transition-all ${
+                    isProcessing
+                      ? "border-[#1db954] animate-pulse"
+                      : isChecked
+                        ? "bg-[#1db954] border-[#1db954]"
+                        : "border-gray-500"
+                  }`}
+                >
+                  {isProcessing && (
+                    <div className="absolute inset-0 flex items-center justify-center">
+                      <div className="w-3 h-3 border-2 border-transparent border-t-[#1db954] rounded-full animate-spin"></div>
+                    </div>
+                  )}
+                </div>
+                <svg
+                  className={`absolute w-3 h-3  transition-opacity ${
+                    isChecked && !isProcessing ? "opacity-100" : "opacity-0"
+                  }`}
+                  fill="none"
+                  stroke="currentColor"
+                  strokeWidth="3"
+                  viewBox="0 0 24 24"
+                >
+                  <path
+                    strokeLinecap="round"
+                    strokeLinejoin="round"
+                    d="M5 13l4 4L19 7"
+                  />
+                </svg>
+              </div>
+              <span
+                className={`ml-3 text-sm truncate transition-all ${
+                  isProcessing
+                    ? "text-[#1db954] animate-pulse"
+                    : "text-gray-200 group-hover/item:text-white"
+                }`}
+              >
+                {playlist.name}
+              </span>
+              {isProcessing && (
+                <span className="ml-auto text-xs text-[#1db954] animate-pulse">
+                  •••
+                </span>
+              )}
+            </label>
+          );
+        })
+      ) : (
+        <div className="px-4 py-3 text-sm text-gray-500 italic">
+          No playlists created
+        </div>
+      )}
+
+      <button
+        onClick={(e) => {
+          e.stopPropagation();
+          handleCreateNew();
+        }}
+        className="w-full text-left px-4 py-2 mt-1 text-sm text-[#1db954] hover:bg-white/5 transition-colors border-t border-white/5 flex items-center gap-2 font-medium cursor-pointer"
+      >
+        <svg
+          className="w-4 h-4"
+          fill="none"
+          stroke="currentColor"
+          viewBox="0 0 24 24"
+        >
+          <path
+            strokeLinecap="round"
+            strokeLinejoin="round"
+            strokeWidth={2}
+            d="M12 4v16m8-8H4"
+          />
+        </svg>
+        Create new playlist
+      </button>
+    </div>
+  );
+
+  return usePortal
+    ? createPortal(dropdownContent, document.body)
+    : dropdownContent;
+};
+
+export default PlaylistDropdown;
Index: frontend/src/components/Sidebar.tsx
===================================================================
--- frontend/src/components/Sidebar.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/Sidebar.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -48,5 +48,5 @@
       await axiosInstance.post("/playlists", { name: playlistName });
       toast.success("Playlist created successfully!");
-      await refreshPlaylists();
+      await refreshPlaylists(false);
     } catch (error) {
       toast.error(getErrorMessage(error));
Index: frontend/src/components/SongItem.tsx
===================================================================
--- frontend/src/components/SongItem.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/SongItem.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -1,259 +1,248 @@
-import { useEffect, useRef, useState } from "react";
+import { useRef, useState } from "react";
 import { useNavigate } from "react-router-dom";
 import { baseURL } from "../api/axiosInstance";
 import { usePlayer } from "../context/playerContext";
 import { toEmbedUrl } from "../utils/utils";
+import PlaylistDropdown from "./PlaylistDropdown";
 
 export interface SongItemData {
-	id: number;
-	title: string;
-	cover?: string | null;
-	genre?: string;
-	link?: string | null;
-	releasedBy?: string;
-	isLikedByCurrentUser?: boolean;
+  id: number;
+  title: string;
+  cover?: string | null;
+  genre?: string;
+  link?: string | null;
+  releasedBy?: string;
+  isLikedByCurrentUser?: boolean;
 }
 
 interface SongItemProps {
-	song: SongItemData;
-	/** Optional label shown before the artist, e.g. "Song" for search results */
-	label?: string;
-	/** Optional role badge for artist contributions, e.g. "PERFORMER" */
-	role?: string;
-	/** Optional index number for playlist/collection views */
-	index?: number;
-	/** Callback when the like button is clicked */
-	onLikeToggle?: (songId: number) => void;
+  song: SongItemData;
+  /** Optional label shown before the artist, e.g. "Song" for search results */
+  label?: string;
+  /** Optional role badge for artist contributions, e.g. "PERFORMER" */
+  role?: string;
+  /** Optional index number for playlist/collection views */
+  index?: number;
+  /** Callback when the like button is clicked */
+  onLikeToggle?: (songId: number) => void;
+  /** Controlled: whether the playlist dropdown is open */
+  isDropdownOpen?: boolean;
+  /** Controlled: callback when dropdown should open/close */
+  onDropdownToggle?: (songId: number | null) => void;
 }
 
 const ROLE_COLORS: { [key: string]: string } = {
-	COMPOSER: "bg-purple-500/20 text-purple-300",
-	PERFORMER: "bg-blue-500/20 text-blue-300",
-	PRODUCER: "bg-green-500/20 text-green-300",
-	MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
+  COMPOSER: "bg-purple-500/20 text-purple-300",
+  PERFORMER: "bg-blue-500/20 text-blue-300",
+  PRODUCER: "bg-green-500/20 text-green-300",
+  MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
 };
 
 const SongItem = ({
-	song,
-	label,
-	role,
-	index,
-	onLikeToggle,
+  song,
+  label,
+  role,
+  index,
+  onLikeToggle,
+  isDropdownOpen,
+  onDropdownToggle,
 }: SongItemProps) => {
-	const navigate = useNavigate();
-	const { play, currentSong } = usePlayer();
-	const [playlistOpen, setPlaylistOpen] = useState(false);
-	const dropdownRef = useRef<HTMLDivElement>(null);
-
-	const isPlaying = currentSong?.id === song.id;
-
-	useEffect(() => {
-		const handleClickOutside = (event: MouseEvent) => {
-			if (
-				dropdownRef.current &&
-				!dropdownRef.current.contains(event.target as Node)
-			) {
-				setPlaylistOpen(false);
-			}
-		};
-		if (playlistOpen) {
-			document.addEventListener("mousedown", handleClickOutside);
-		}
-		return () => document.removeEventListener("mousedown", handleClickOutside);
-	}, [playlistOpen]);
-
-	const handleAddToPlaylist = (playlistName: string) => {
-		console.log(`Adding song ${song.id} to ${playlistName}`);
-		// TODO: Implement actual API call
-		setPlaylistOpen(false);
-	};
-
-	const handleCreateNewPlaylist = () => {
-		console.log(`Creating new playlist for song ${song.id}`);
-		// TODO: Implement actual playlist creation
-		setPlaylistOpen(false);
-	};
-
-	// Build subtitle
-	const subtitleParts: string[] = [];
-	if (label) subtitleParts.push(label);
-	if (song.releasedBy) subtitleParts.push(song.releasedBy);
-	const subtitle = subtitleParts.join(" • ");
-
-	return (
-		<div
-			onClick={() => navigate(`/songs/${song.id}`)}
-			className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group"
-		>
-			{/* Optional index */}
-			{index != null && (
-				<span className="text-gray-500 font-medium w-8 text-center text-sm shrink-0">
-					{index}
-				</span>
-			)}
-
-			{/* Cover */}
-			<img
-				src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
-				alt={song.title}
-				className="w-12 h-12 rounded object-cover shrink-0"
-				onError={(e) => {
-					(e.target as HTMLImageElement).src = "/favicon.png";
-				}}
-			/>
-
-			{/* Title & subtitle */}
-			<div className="flex-1 min-w-0">
-				<p
-					className={`font-medium truncate ${
-						isPlaying ? "text-[#1db954]" : "text-white"
-					}`}
-				>
-					{song.title}
-				</p>
-				{subtitle && (
-					<p className="text-sm text-gray-400 truncate">{subtitle}</p>
-				)}
-			</div>
-
-			{/* Role badge (artist contributions) */}
-			{role && (
-				<span
-					className={`px-3 py-1 rounded-full text-xs font-medium hidden sm:block ${
-						ROLE_COLORS[role] || "bg-white/10 text-gray-300"
-					}`}
-				>
-					{role.replace("_", " ")}
-				</span>
-			)}
-
-			{/* Genre */}
-			{song.genre && (
-				<span className="text-xs text-gray-500 uppercase tracking-wider mr-2 hidden sm:block">
-					{song.genre}
-				</span>
-			)}
-
-			{/* Play button */}
-			{song.link && (
-				<button
-					onClick={(e) => {
-						e.stopPropagation();
-						play({
-							id: song.id,
-							title: song.title,
-							artist: song.releasedBy || "",
-							cover: song.cover,
-							embedUrl: toEmbedUrl(song.link!),
-						});
-					}}
-					className={`p-2 rounded-full transition-all cursor-pointer ${
-						isPlaying
-							? "bg-white text-[#1db954] opacity-100"
-							: "bg-[#1db954] text-black hover:scale-110 opacity-0 group-hover:opacity-100"
-					}`}
-					aria-label={isPlaying ? "Now playing" : "Play song"}
-				>
-					{isPlaying ? (
-						<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-							<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-						</svg>
-					) : (
-						<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-							<path d="M8 5v14l11-7z" />
-						</svg>
-					)}
-				</button>
-			)}
-
-			{/* Like button */}
-			{onLikeToggle && (
-				<button
-					onClick={(e) => {
-						e.stopPropagation();
-						onLikeToggle(song.id);
-					}}
-					className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer"
-					aria-label={song.isLikedByCurrentUser ? "Unlike" : "Like"}
-				>
-					<svg
-						className="w-5 h-5"
-						fill={song.isLikedByCurrentUser ? "#ef4444" : "none"}
-						stroke={song.isLikedByCurrentUser ? "#ef4444" : "#6b7280"}
-						strokeWidth="2"
-						viewBox="0 0 24 24"
-					>
-						<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-					</svg>
-				</button>
-			)}
-
-			{/* Three-dot menu */}
-			<div className="relative" ref={dropdownRef}>
-				<button
-					onClick={(e) => {
-						e.stopPropagation();
-						setPlaylistOpen((prev) => !prev);
-					}}
-					className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer text-gray-400 hover:text-white"
-					aria-label="More options"
-				>
-					<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-						<circle cx="12" cy="5" r="1.5" />
-						<circle cx="12" cy="12" r="1.5" />
-						<circle cx="12" cy="19" r="1.5" />
-					</svg>
-				</button>
-
-				{playlistOpen && (
-					<div className="absolute right-0 bottom-full mb-2 w-48 bg-[#282828] border border-white/10 rounded-lg shadow-lg py-1 z-50">
-						<div className="px-3 py-2 text-xs text-gray-400 border-b border-white/10">
-							Add to playlist
-						</div>
-						<button
-							onClick={(e) => {
-								e.stopPropagation();
-								handleAddToPlaylist("Playlist 1");
-							}}
-							className="w-full text-left px-4 py-2 text-sm text-white hover:bg-white/10 transition-colors"
-						>
-							Playlist 1
-						</button>
-						<button
-							onClick={(e) => {
-								e.stopPropagation();
-								handleAddToPlaylist("Playlist 2");
-							}}
-							className="w-full text-left px-4 py-2 text-sm text-white hover:bg-white/10 transition-colors"
-						>
-							Playlist 2
-						</button>
-						<button
-							onClick={(e) => {
-								e.stopPropagation();
-								handleCreateNewPlaylist();
-							}}
-							className="w-full text-left px-4 py-2 text-sm text-[#1db954] hover:bg-white/10 transition-colors border-t border-white/10 flex items-center gap-2"
-						>
-							<svg
-								className="w-4 h-4"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M12 4v16m8-8H4"
-								/>
-							</svg>
-							Create new playlist
-						</button>
-					</div>
-				)}
-			</div>
-		</div>
-	);
+  const navigate = useNavigate();
+  const { play, currentSong } = usePlayer();
+  const [internalOpen, setInternalOpen] = useState(false);
+  const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });
+  const [dropdownDirection, setDropdownDirection] = useState<"above" | "below">(
+    "below",
+  );
+  const buttonRef = useRef<HTMLButtonElement>(null);
+
+  const playlistOpen = isDropdownOpen ?? internalOpen;
+  const setPlaylistOpen = (open: boolean) => {
+    if (onDropdownToggle) {
+      onDropdownToggle(open ? song.id : null);
+    } else {
+      setInternalOpen(open);
+    }
+  };
+
+  const isPlaying = currentSong?.id === song.id;
+
+  const handleCreateNewPlaylist = () => {
+    console.log(`Creating new playlist for song ${song.id}`);
+    // TODO: Implement actual playlist creation
+    setPlaylistOpen(false);
+  };
+
+  const subtitleParts: string[] = [];
+  if (label) subtitleParts.push(label);
+  if (song.releasedBy) subtitleParts.push(song.releasedBy);
+  const subtitle = subtitleParts.join(" • ");
+
+  return (
+    <div
+      onClick={() => navigate(`/songs/${song.id}`)}
+      onMouseEnter={() => {
+        if (onDropdownToggle && !playlistOpen) {
+          onDropdownToggle(null);
+        }
+      }}
+      className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group"
+    >
+      {/* Optional index */}
+      {index != null && (
+        <span className="text-gray-500 font-medium w-8 text-center text-sm shrink-0">
+          {index}
+        </span>
+      )}
+
+      {/* Cover */}
+      <img
+        src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
+        alt={song.title}
+        className="w-12 h-12 rounded object-cover shrink-0"
+        onError={(e) => {
+          (e.target as HTMLImageElement).src = "/favicon.png";
+        }}
+      />
+
+      {/* Title & subtitle */}
+      <div className="flex-1 min-w-0">
+        <p
+          className={`font-medium truncate ${
+            isPlaying ? "text-[#1db954]" : "text-white"
+          }`}
+        >
+          {song.title}
+        </p>
+        {subtitle && (
+          <p className="text-sm text-gray-400 truncate">{subtitle}</p>
+        )}
+      </div>
+
+      {/* Role badge (artist contributions) */}
+      {role && (
+        <span
+          className={`px-3 py-1 rounded-full text-xs font-medium hidden sm:block ${
+            ROLE_COLORS[role] || "bg-white/10 text-gray-300"
+          }`}
+        >
+          {role.replace("_", " ")}
+        </span>
+      )}
+
+      {/* Genre */}
+      {song.genre && (
+        <span className="text-xs text-gray-500 uppercase tracking-wider mr-2 hidden sm:block">
+          {song.genre}
+        </span>
+      )}
+
+      {/* Play button */}
+      {song.link && (
+        <button
+          onClick={(e) => {
+            e.stopPropagation();
+            play({
+              id: song.id,
+              title: song.title,
+              artist: song.releasedBy || "",
+              cover: song.cover,
+              embedUrl: toEmbedUrl(song.link!),
+            });
+          }}
+          className={`p-2 rounded-full transition-all cursor-pointer ${
+            isPlaying
+              ? "bg-white text-[#1db954] opacity-100"
+              : "bg-[#1db954] text-black hover:scale-110 opacity-0 group-hover:opacity-100"
+          }`}
+          aria-label={isPlaying ? "Now playing" : "Play song"}
+        >
+          {isPlaying ? (
+            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
+              <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
+            </svg>
+          ) : (
+            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
+              <path d="M8 5v14l11-7z" />
+            </svg>
+          )}
+        </button>
+      )}
+
+      {/* Like button */}
+      {onLikeToggle && (
+        <button
+          onClick={(e) => {
+            e.stopPropagation();
+            onLikeToggle(song.id);
+          }}
+          className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer"
+          aria-label={song.isLikedByCurrentUser ? "Unlike" : "Like"}
+        >
+          <svg
+            className="w-5 h-5"
+            fill={song.isLikedByCurrentUser ? "#ef4444" : "none"}
+            stroke={song.isLikedByCurrentUser ? "#ef4444" : "#6b7280"}
+            strokeWidth="2"
+            viewBox="0 0 24 24"
+          >
+            <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
+          </svg>
+        </button>
+      )}
+
+      {/* Three-dot menu */}
+      <div className="relative">
+        <button
+          ref={buttonRef}
+          onClick={(e) => {
+            e.stopPropagation();
+            if (playlistOpen) {
+              setPlaylistOpen(false);
+            } else {
+              if (buttonRef.current) {
+                const rect = buttonRef.current.getBoundingClientRect();
+                const spaceBelow = window.innerHeight - rect.bottom;
+                const dropdownHeight = 260;
+
+                if (spaceBelow < dropdownHeight) {
+                  setDropdownDirection("above");
+                  setDropdownPosition({
+                    top: rect.top - 8,
+                    left: rect.right - 224,
+                  });
+                } else {
+                  setDropdownDirection("below");
+                  setDropdownPosition({
+                    top: rect.bottom + 8,
+                    left: rect.right - 224,
+                  });
+                }
+              }
+              setPlaylistOpen(true);
+            }
+          }}
+          className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer text-gray-400 hover:text-white"
+          aria-label="More options"
+        >
+          <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
+            <circle cx="12" cy="5" r="1.5" />
+            <circle cx="12" cy="12" r="1.5" />
+            <circle cx="12" cy="19" r="1.5" />
+          </svg>
+        </button>
+
+        <PlaylistDropdown
+          songId={song.id}
+          isOpen={playlistOpen}
+          onClose={() => setPlaylistOpen(false)}
+          position={dropdownPosition}
+          usePortal={true}
+          direction={dropdownDirection}
+          onCreateNewPlaylist={handleCreateNewPlaylist}
+        />
+      </div>
+    </div>
+  );
 };
 
Index: frontend/src/components/userProfile/ArtistView.tsx
===================================================================
--- frontend/src/components/userProfile/ArtistView.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/userProfile/ArtistView.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -8,144 +8,149 @@
 
 interface ArtistViewProps {
-	contributions: ArtistContribution[];
+  contributions: ArtistContribution[];
 }
 
 const ArtistView = ({ contributions }: ArtistViewProps) => {
-	const navigate = useNavigate();
-	const [items, setItems] = useState(contributions);
+  const navigate = useNavigate();
+  const [items, setItems] = useState(contributions);
+  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
+    null,
+  );
 
-	const albums = items.filter((c) => c.entityType === "ALBUM");
-	const songs = items.filter((c) => c.entityType === "SONG");
+  const albums = items.filter((c) => c.entityType === "ALBUM");
+  const songs = items.filter((c) => c.entityType === "SONG");
 
-	const getRoleColor = (role: string) => {
-		const colors: { [key: string]: string } = {
-			COMPOSER: "bg-purple-500/20 text-purple-300",
-			PERFORMER: "bg-blue-500/20 text-blue-300",
-			PRODUCER: "bg-green-500/20 text-green-300",
-			MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
-		};
-		return colors[role] || "bg-white/10 text-gray-300";
-	};
+  const getRoleColor = (role: string) => {
+    const colors: { [key: string]: string } = {
+      COMPOSER: "bg-purple-500/20 text-purple-300",
+      PERFORMER: "bg-blue-500/20 text-blue-300",
+      PRODUCER: "bg-green-500/20 text-green-300",
+      MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
+    };
+    return colors[role] || "bg-white/10 text-gray-300";
+  };
 
-	const handleLike = async (id: number, title: string) => {
-		try {
-			const response = await axiosInstance.post(`/musical-entity/${id}/like`);
-			const data = response.data;
+  const handleLike = async (id: number, title: string) => {
+    try {
+      const response = await axiosInstance.post(`/musical-entity/${id}/like`);
+      const data = response.data;
 
-			setItems((prevItems) =>
-				prevItems.map((item) =>
-					item.id === data.entityId
-						? { ...item, isLikedByCurrentUser: data.isLiked }
-						: item,
-				),
-			);
-			toast.success(
-				data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
-			);
-		} catch (err: any) {
-			toast.error(err.response?.data?.error || "Failed to like the item");
-		}
-	};
+      setItems((prevItems) =>
+        prevItems.map((item) =>
+          item.id === data.entityId
+            ? { ...item, isLikedByCurrentUser: data.isLiked }
+            : item,
+        ),
+      );
+      toast.success(
+        data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
+      );
+    } catch (err: any) {
+      toast.error(err.response?.data?.error || "Failed to like the item");
+    }
+  };
 
-	return (
-		<div className="mt-8">
-			{albums.length > 0 && (
-				<div className="mb-12">
-					<div className="flex items-center gap-3 mb-6">
-						<Disc3 className="w-6 h-6 text-[#1db954]" />
-						<h2 className="text-2xl font-bold text-white">Albums</h2>
-					</div>
-					<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
-						{albums.map((album) => (
-							<div
-								key={album.id}
-								className="group cursor-pointer"
-								onClick={() => navigate(`/collection/album/${album.id}`)}
-							>
-								<div className="relative aspect-square rounded-lg mb-3 overflow-hidden shadow-md group-hover:shadow-xl transition-all duration-300 bg-[#181818]">
-									<img
-										src={
-											album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
-										}
-										alt={album.title}
-										className="w-full h-full object-cover"
-										onError={(e) => {
-											(e.target as HTMLImageElement).src = "/favicon.png";
-										}}
-									/>
+  return (
+    <div className="mt-8">
+      {albums.length > 0 && (
+        <div className="mb-12">
+          <div className="flex items-center gap-3 mb-6">
+            <Disc3 className="w-6 h-6 text-[#1db954]" />
+            <h2 className="text-2xl font-bold text-white">Albums</h2>
+          </div>
+          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
+            {albums.map((album) => (
+              <div
+                key={album.id}
+                className="group cursor-pointer"
+                onClick={() => navigate(`/collection/album/${album.id}`)}
+              >
+                <div className="relative aspect-square rounded-lg mb-3 overflow-hidden shadow-md group-hover:shadow-xl transition-all duration-300 bg-[#181818]">
+                  <img
+                    src={
+                      album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
+                    }
+                    alt={album.title}
+                    className="w-full h-full object-cover"
+                    onError={(e) => {
+                      (e.target as HTMLImageElement).src = "/favicon.png";
+                    }}
+                  />
 
-									<button
-										className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
-										title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
-										onClick={(e) => {
-											e.stopPropagation();
-											handleLike(album.id, album.title);
-										}}
-									>
-										<svg
-											className="w-5 h-5"
-											fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
-											stroke={
-												album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
-											}
-											strokeWidth="2"
-											viewBox="0 0 24 24"
-										>
-											<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-										</svg>
-									</button>
+                  <button
+                    className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
+                    title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      handleLike(album.id, album.title);
+                    }}
+                  >
+                    <svg
+                      className="w-5 h-5"
+                      fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
+                      stroke={
+                        album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
+                      }
+                      strokeWidth="2"
+                      viewBox="0 0 24 24"
+                    >
+                      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
+                    </svg>
+                  </button>
 
-									<div className="absolute bottom-0 left-0 right-0 bg-linear-to-t from-black/80 to-transparent p-3">
-										<span
-											className={`text-xs px-2 py-1 rounded-full font-medium ${getRoleColor(album.role)}`}
-										>
-											{album.role.replace("_", " ")}
-										</span>
-									</div>
-								</div>
-								<h3 className="font-semibold text-sm line-clamp-2 text-white group-hover:text-[#1db954] transition-colors">
-									{album.title}
-								</h3>
-							</div>
-						))}
-					</div>
-				</div>
-			)}
+                  <div className="absolute bottom-0 left-0 right-0 bg-linear-to-t from-black/80 to-transparent p-3">
+                    <span
+                      className={`text-xs px-2 py-1 rounded-full font-medium ${getRoleColor(album.role)}`}
+                    >
+                      {album.role.replace("_", " ")}
+                    </span>
+                  </div>
+                </div>
+                <h3 className="font-semibold text-sm line-clamp-2 text-white group-hover:text-[#1db954] transition-colors">
+                  {album.title}
+                </h3>
+              </div>
+            ))}
+          </div>
+        </div>
+      )}
 
-			{songs.length > 0 && (
-				<div className="mb-12">
-					<div className="flex items-center gap-3 mb-6">
-						<Music className="w-6 h-6 text-[#1db954]" />
-						<h2 className="text-2xl font-bold text-white">Songs</h2>
-					</div>
-					<div className="space-y-1">
-						{songs.map((song) => (
-							<SongItem
-								key={song.id}
-								song={{
-									id: song.id,
-									title: song.title,
-									cover: song.cover,
-									genre: song.genre,
-									link: song.link,
-									isLikedByCurrentUser: song.isLikedByCurrentUser,
-								}}
-								role={song.role}
-								onLikeToggle={() => handleLike(song.id, song.title)}
-							/>
-						))}
-					</div>
-				</div>
-			)}
+      {songs.length > 0 && (
+        <div className="mb-12">
+          <div className="flex items-center gap-3 mb-6">
+            <Music className="w-6 h-6 text-[#1db954]" />
+            <h2 className="text-2xl font-bold text-white">Songs</h2>
+          </div>
+          <div className="space-y-1">
+            {songs.map((song) => (
+              <SongItem
+                key={song.id}
+                song={{
+                  id: song.id,
+                  title: song.title,
+                  cover: song.cover,
+                  genre: song.genre,
+                  link: song.link,
+                  isLikedByCurrentUser: song.isLikedByCurrentUser,
+                }}
+                role={song.role}
+                onLikeToggle={() => handleLike(song.id, song.title)}
+                isDropdownOpen={openDropdownSongId === song.id}
+                onDropdownToggle={setOpenDropdownSongId}
+              />
+            ))}
+          </div>
+        </div>
+      )}
 
-			{contributions.length === 0 && (
-				<div className="flex flex-col items-center justify-center py-16 text-gray-500">
-					<Music className="w-20 h-20 mb-4 opacity-20" />
-					<p className="text-lg font-medium">No contributions yet</p>
-					<p className="text-sm mt-2">Start creating music to see it here</p>
-				</div>
-			)}
-		</div>
-	);
+      {contributions.length === 0 && (
+        <div className="flex flex-col items-center justify-center py-16 text-gray-500">
+          <Music className="w-20 h-20 mb-4 opacity-20" />
+          <p className="text-lg font-medium">No contributions yet</p>
+          <p className="text-sm mt-2">Start creating music to see it here</p>
+        </div>
+      )}
+    </div>
+  );
 };
 
Index: frontend/src/components/userProfile/ListenerView.tsx
===================================================================
--- frontend/src/components/userProfile/ListenerView.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/components/userProfile/ListenerView.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -25,4 +25,7 @@
   const [createdItems, setCreatedItems] = useState(createdPlaylists);
   const [savedItems, setSavedItems] = useState(savedPlaylists);
+  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
+    null,
+  );
 
   const likedSongs = items.filter((e) => e.type === "SONG");
@@ -258,4 +261,6 @@
                 index={index + 1}
                 onLikeToggle={() => handleLike(song.id, song.title)}
+                isDropdownOpen={openDropdownSongId === song.id}
+                onDropdownToggle={setOpenDropdownSongId}
               />
             ))}
Index: frontend/src/context/playlistContext.tsx
===================================================================
--- frontend/src/context/playlistContext.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/context/playlistContext.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -17,5 +17,5 @@
   setCreatedPlaylists: Dispatch<SetStateAction<BasicPlaylist[] | undefined>>;
   isLoading: boolean;
-  refreshPlaylists: () => Promise<void>;
+  refreshPlaylists: (addedSong: boolean) => Promise<void>;
 }
 
@@ -28,5 +28,5 @@
   setCreatedPlaylists: () => {},
   isLoading: false,
-  refreshPlaylists: async () => {},
+  refreshPlaylists: async (addedSong: boolean) => {},
 });
 
@@ -38,6 +38,8 @@
   const [isLoading, setIsLoading] = useState(false);
 
-  const fetchCreatedPlaylists = async () => {
-    setIsLoading(true);
+  const fetchCreatedPlaylists = async (addedSong: boolean) => {
+    if (!addedSong) {
+      setIsLoading(true);
+    }
     try {
       const data = await axiosInstance.get<BasicPlaylist[]>("/playlists/user");
@@ -52,5 +54,5 @@
   useEffect(() => {
     if (user) {
-      fetchCreatedPlaylists();
+      fetchCreatedPlaylists(false);
     } else {
       setCreatedPlaylists(undefined);
Index: frontend/src/pages/LandingPage.tsx
===================================================================
--- frontend/src/pages/LandingPage.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/pages/LandingPage.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -1,5 +1,6 @@
-import { useEffect, useRef, useState } from "react";
+import { useEffect, useState } from "react";
 import { useNavigate } from "react-router-dom";
 import axiosInstance, { baseURL } from "../api/axiosInstance";
+import PlaylistDropdown from "../components/PlaylistDropdown";
 import AlbumResult from "../components/search/AlbumResult";
 import SongResult from "../components/search/SongResult";
@@ -7,568 +8,503 @@
 import { usePlayer } from "../context/playerContext";
 import type {
-	Album,
-	BaseNonAdminUser,
-	SearchCategory,
-	Song,
+  Album,
+  BaseNonAdminUser,
+  SearchCategory,
+  Song,
 } from "../utils/types";
 import { toEmbedUrl } from "../utils/utils";
 
 const CATEGORIES: { value: SearchCategory; label: string }[] = [
-	{ value: "songs", label: "Songs" },
-	{ value: "albums", label: "Albums" },
-	{ value: "artists", label: "Artists" },
-	{ value: "users", label: "Users" },
+  { value: "songs", label: "Songs" },
+  { value: "albums", label: "Albums" },
+  { value: "artists", label: "Artists" },
+  { value: "users", label: "Users" },
 ];
 
 const LandingPage = () => {
-	const navigate = useNavigate();
-	const { play, currentSong } = usePlayer();
-	const [songs, setSongs] = useState<Song[]>([]);
-	const [loading, setLoading] = useState<boolean>(true);
-
-	// search state
-	const [searchInput, setSearchInput] = useState("");
-	const [activeQuery, setActiveQuery] = useState("");
-	const [searchCategory, setSearchCategory] = useState<SearchCategory>("songs");
-	const [searchResults, setSearchResults] = useState<unknown[]>([]);
-	const [searchLoading, setSearchLoading] = useState(false);
-	const [hasSearched, setHasSearched] = useState(false);
-
-	// playlist dropdown state
-	const [openPlaylistDropdown, setOpenPlaylistDropdown] = useState<
-		number | null
-	>(null);
-	const playlistDropdownRefs = useRef<{ [key: number]: HTMLDivElement | null }>(
-		{},
-	);
-
-	useEffect(() => {
-		const fetchSongs = async () => {
-			try {
-				const response = await axiosInstance.get("/songs/top");
-				setSongs(response.data);
-			} catch (error) {
-				console.error("Error fetching songs:", error);
-			} finally {
-				setLoading(false);
-			}
-		};
-		fetchSongs();
-	}, []);
-
-	// Handle click outside for playlist dropdown
-	useEffect(() => {
-		const handleClickOutside = (event: MouseEvent) => {
-			if (openPlaylistDropdown !== null) {
-				const ref = playlistDropdownRefs.current[openPlaylistDropdown];
-				if (ref && !ref.contains(event.target as Node)) {
-					setOpenPlaylistDropdown(null);
-				}
-			}
-		};
-
-		document.addEventListener("mousedown", handleClickOutside);
-		return () => {
-			document.removeEventListener("mousedown", handleClickOutside);
-		};
-	}, [openPlaylistDropdown]);
-
-	const toggleLike = async (songId: number) => {
-		try {
-			await axiosInstance.post(`/musical-entity/${songId}/like`);
-			setSongs((prevSongs) =>
-				prevSongs.map((song) =>
-					song.id === songId
-						? { ...song, isLikedByCurrentUser: !song.isLikedByCurrentUser }
-						: song,
-				),
-			);
-		} catch (error) {
-			console.error("Error toggling like:", error);
-		}
-	};
-
-	const togglePlaylistDropdown = (songId: number) => {
-		setOpenPlaylistDropdown((prev) => (prev === songId ? null : songId));
-	};
-
-	const handleAddToPlaylist = (songId: number, playlistName: string) => {
-		console.log(`Adding song ${songId} to ${playlistName}`);
-		// TODO: Implement actual API call
-		setOpenPlaylistDropdown(null);
-	};
-
-	const handleCreateNewPlaylist = (songId: number) => {
-		console.log(`Creating new playlist for song ${songId}`);
-		// TODO: Implement actual playlist creation
-		setOpenPlaylistDropdown(null);
-	};
-
-	const performSearch = async (query: string, category: SearchCategory) => {
-		if (!query.trim()) return;
-
-		setSearchLoading(true);
-		setHasSearched(true);
-		setActiveQuery(query);
-		setSearchCategory(category);
-
-		try {
-			let endpoint = "";
-			switch (category) {
-				case "songs":
-					endpoint = `/songs/search?q=${encodeURIComponent(query)}`;
-					break;
-				case "albums":
-					endpoint = `/albums/search?q=${encodeURIComponent(query)}`;
-					break;
-				case "artists":
-					endpoint = `/users/search?type=ARTIST&q=${encodeURIComponent(query)}`;
-					break;
-				case "users":
-					endpoint = `/users/search?type=LISTENER&q=${encodeURIComponent(query)}`;
-					break;
-			}
-
-			const response = await axiosInstance.get(endpoint);
-			setSearchResults(response.data);
-		} catch (error) {
-			console.error("Search error:", error);
-			setSearchResults([]);
-		} finally {
-			setSearchLoading(false);
-		}
-	};
-
-	const handleSearch = () => {
-		performSearch(searchInput, searchCategory);
-	};
-
-	const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
-		if (e.key === "Enter") {
-			handleSearch();
-		}
-	};
-
-	const handleCategorySwitch = (category: SearchCategory) => {
-		performSearch(activeQuery, category);
-	};
-
-	const clearSearch = () => {
-		setSearchInput("");
-		setActiveQuery("");
-		setHasSearched(false);
-		setSearchResults([]);
-	};
-
-	const renderResults = () => {
-		if (searchLoading) {
-			return (
-				<div className="flex justify-center py-12">
-					<div className="w-10 h-10 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
-				</div>
-			);
-		}
-
-		if (searchResults.length === 0) {
-			return (
-				<div className="text-center py-12 text-gray-400">
-					<p className="text-lg">
-						No {searchCategory} found for "{activeQuery}"
-					</p>
-				</div>
-			);
-		}
-
-		return (
-			<div className="divide-y divide-white/5">
-				{searchResults.map((result, index) => {
-					switch (searchCategory) {
-						case "songs":
-							return (
-								<SongResult key={(result as Song).id} song={result as Song} />
-							);
-						case "albums":
-							return (
-								<AlbumResult
-									key={(result as Album).id}
-									album={result as Album}
-								/>
-							);
-						case "artists":
-							return (
-								<UserResult
-									key={(result as BaseNonAdminUser).username ?? index}
-									user={result as BaseNonAdminUser}
-									label="Artist"
-								/>
-							);
-						case "users":
-							return (
-								<UserResult
-									key={(result as BaseNonAdminUser).username ?? index}
-									user={result as BaseNonAdminUser}
-									label="User"
-								/>
-							);
-					}
-				})}
-			</div>
-		);
-	};
-
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white flex">
-			<div className="flex-1">
-				<div className="p-8">
-					<div className="max-w-7xl mx-auto">
-						{/* Search Bar */}
-						<div className="mb-8 flex flex-col md:flex-row gap-3">
-							<div className="flex flex-1 gap-0">
-								{/* Category Dropdown */}
-								<select
-									value={searchCategory}
-									onChange={(e) =>
-										setSearchCategory(e.target.value as SearchCategory)
-									}
-									className="bg-[#282828] border border-white/10 border-r-0 rounded-l-full py-2 px-4 text-white text-sm focus:outline-none focus:border-[#1db954] appearance-none cursor-pointer"
-								>
-									{CATEGORIES.map((cat) => (
-										<option key={cat.value} value={cat.value}>
-											{cat.label}
-										</option>
-									))}
-								</select>
-
-								{/* Search Input */}
-								<input
-									type="text"
-									placeholder={`Search ${searchCategory}...`}
-									value={searchInput}
-									onChange={(e) => setSearchInput(e.target.value)}
-									onKeyDown={handleKeyDown}
-									className="flex-1 bg-[#282828] border border-white/10 border-r-0 py-2 px-4 text-white focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-								/>
-
-								{/* Search Button */}
-								<button
-									onClick={handleSearch}
-									className="bg-[#1db954] hover:bg-[#1ed760] text-black font-medium px-6 rounded-r-full transition-colors flex items-center gap-2"
-								>
-									<svg
-										className="w-5 h-5"
-										fill="none"
-										stroke="currentColor"
-										viewBox="0 0 24 24"
-									>
-										<path
-											strokeLinecap="round"
-											strokeLinejoin="round"
-											strokeWidth={2}
-											d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
-										/>
-									</svg>
-									<span className="hidden sm:inline">Search</span>
-								</button>
-							</div>
-						</div>
-
-						{/* Search Results Section */}
-						{hasSearched ? (
-							<div>
-								<div className="flex items-center justify-between mb-4">
-									<h2 className="text-2xl font-bold text-white">
-										Results for "{activeQuery}"
-									</h2>
-									<button
-										onClick={clearSearch}
-										className="text-sm text-gray-400 hover:text-white transition-colors"
-									>
-										Clear search
-									</button>
-								</div>
-
-								{/* Quick category switch buttons */}
-								<div className="flex gap-2 mb-6">
-									{CATEGORIES.map((cat) => (
-										<button
-											key={cat.value}
-											onClick={() => handleCategorySwitch(cat.value)}
-											className={`px-4 py-1.5 rounded-full text-sm font-medium transition-colors ${
-												searchCategory === cat.value
-													? "bg-[#1db954] text-black"
-													: "bg-white/10 text-white hover:bg-white/20"
-											}`}
-										>
-											{cat.label}
-										</button>
-									))}
-								</div>
-
-								{/* Results list */}
-								<div className="bg-[#1a1a2e]/50 rounded-xl overflow-hidden">
-									{renderResults()}
-								</div>
-							</div>
-						) : (
-							/* Default song grid */
-							<>
-								<div className="mb-8 border-b border-white/10 pb-6">
-									<h1 className="text-5xl font-bold mb-3 pb-1 bg-linear-to-r from-[#1db954] to-[#1ed760] bg-clip-text text-transparent">
-										Top Songs
-									</h1>
-									<p className="text-xl text-gray-400">
-										Listen to the newest tracks on FinkWave
-									</p>
-								</div>
-
-								{loading ? (
-									<div className="flex flex-col items-center justify-center min-h-[40vh] gap-6">
-										<div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
-										<p className="text-xl text-gray-400">Loading songs...</p>
-									</div>
-								) : (
-									<div className="grid grid-cols-[repeat(auto-fill,minmax(220px,1fr))] gap-8 py-4">
-										{songs.map((song) => (
-											<div
-												key={song.id}
-												onClick={() => navigate(`/songs/${song.id}`)}
-												className="bg-[#282828] rounded-xl overflow-hidden cursor-pointer shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-2 hover:shadow-2xl group"
-											>
-												<div className="relative w-full pt-[100%] overflow-hidden bg-[#181818]">
-													<img
-														src={
-															song.cover
-																? `${baseURL}/${song.cover}`
-																: "/favicon.png"
-														}
-														alt={song.title}
-														className="absolute top-0 left-0 w-full h-full object-cover"
-														onError={(e) => {
-															(e.target as HTMLImageElement).src =
-																"/favicon.png";
-														}}
-													/>
-													<div className="absolute top-0 left-0 w-full h-full bg-black/60 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
-														{song.link ? (
-															<button
-																onClick={(e) => {
-																	e.stopPropagation();
-																	play({
-																		id: song.id,
-																		title: song.title,
-																		artist: song.releasedBy,
-																		cover: song.cover,
-																		embedUrl: toEmbedUrl(song.link!),
-																	});
-																}}
-																className={`w-14 h-14 rounded-full flex items-center justify-center text-xl shadow-[0_4px_12px_rgba(29,185,84,0.5)] transition-all cursor-pointer ${
-																	currentSong?.id === song.id
-																		? "bg-white text-[#1db954]"
-																		: "bg-[#1db954] text-black hover:scale-105"
-																}`}
-																aria-label={
-																	currentSong?.id === song.id
-																		? "Now playing"
-																		: "Play song"
-																}
-															>
-																{currentSong?.id === song.id ? (
-																	<svg
-																		className="w-6 h-6"
-																		fill="currentColor"
-																		viewBox="0 0 24 24"
-																	>
-																		<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-																	</svg>
-																) : (
-																	<svg
-																		className="w-6 h-6"
-																		fill="currentColor"
-																		viewBox="0 0 24 24"
-																	>
-																		<path d="M8 5v14l11-7z" />
-																	</svg>
-																)}
-															</button>
-														) : (
-															<div className="w-14 h-14 rounded-full bg-[#1db954] flex items-center justify-center text-xl text-black shadow-[0_4px_12px_rgba(29,185,84,0.5)]">
-																▶
-															</div>
-														)}
-													</div>
-												</div>
-												<div className="p-4">
-													<h3 className="text-lg font-semibold mb-2 text-white overflow-hidden text-ellipsis whitespace-nowrap">
-														{song.title}
-													</h3>
-													{song.album && (
-														<p
-															onClick={(e) => {
-																e.stopPropagation();
-																if (song.albumId) {
-																	navigate(`/collection/album/${song.albumId}`);
-																}
-															}}
-															className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${
-																song.albumId
-																	? "hover:underline cursor-pointer hover:text-white"
-																	: ""
-															}`}
-														>
-															{song.album}
-														</p>
-													)}
-													<p
-														onClick={(e) => {
-															e.stopPropagation();
-															if (song.artistUsername) {
-																navigate(`/users/${song.artistUsername}`);
-															}
-														}}
-														className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${
-															song.artistUsername
-																? "hover:underline cursor-pointer hover:text-white"
-																: ""
-														}`}
-													>
-														{song.releasedBy}
-													</p>
-													<div className="flex items-center justify-between mt-4 pt-3 border-t border-white/10">
-														{/* Like button */}
-														<button
-															onClick={(e) => {
-																e.stopPropagation();
-																toggleLike(song.id);
-															}}
-															className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
-															aria-label={
-																song.isLikedByCurrentUser
-																	? "Unlike song"
-																	: "Like song"
-															}
-														>
-															{song.isLikedByCurrentUser ? (
-																<svg
-																	className="w-6 h-6 fill-[#1db954]"
-																	viewBox="0 0 24 24"
-																>
-																	<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
-																</svg>
-															) : (
-																<svg
-																	className="w-6 h-6"
-																	fill="none"
-																	stroke="currentColor"
-																	viewBox="0 0 24 24"
-																>
-																	<path
-																		strokeLinecap="round"
-																		strokeLinejoin="round"
-																		strokeWidth={2}
-																		d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
-																	/>
-																</svg>
-															)}
-														</button>
-
-														{/* Add to playlist button */}
-														<div
-															className="relative"
-															ref={(el) => {
-																if (el)
-																	playlistDropdownRefs.current[song.id] = el;
-															}}
-														>
-															<button
-																onClick={(e) => {
-																	e.stopPropagation();
-																	togglePlaylistDropdown(song.id);
-																}}
-																className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
-																aria-label="Add to playlist"
-															>
-																<svg
-																	className="w-6 h-6"
-																	fill="none"
-																	stroke="currentColor"
-																	viewBox="0 0 24 24"
-																>
-																	<path
-																		strokeLinecap="round"
-																		strokeLinejoin="round"
-																		strokeWidth={2}
-																		d="M12 4v16m8-8H4"
-																	/>
-																</svg>
-															</button>
-
-															{/* Playlist dropdown */}
-															{openPlaylistDropdown === song.id && (
-																<div className="absolute right-0 bottom-full mb-2 w-48 bg-gray-700 rounded-lg shadow-lg py-1 z-50">
-																	<div className="px-3 py-2 text-xs text-gray-400 border-b border-white/10">
-																		Add to playlist
-																	</div>
-																	<button
-																		onClick={(e) => {
-																			e.stopPropagation();
-																			handleAddToPlaylist(
-																				song.id,
-																				"Playlist 1",
-																			);
-																		}}
-																		className="w-full text-left px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
-																	>
-																		Playlist 1
-																	</button>
-																	<button
-																		onClick={(e) => {
-																			e.stopPropagation();
-																			handleAddToPlaylist(
-																				song.id,
-																				"Playlist 2",
-																			);
-																		}}
-																		className="w-full text-left px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
-																	>
-																		Playlist 2
-																	</button>
-																	<button
-																		onClick={(e) => {
-																			e.stopPropagation();
-																			handleCreateNewPlaylist(song.id);
-																		}}
-																		className="w-full text-left px-4 py-2 text-sm text-[#1db954] hover:bg-gray-600 transition-colors border-t border-white/10 flex items-center gap-2"
-																	>
-																		<svg
-																			className="w-4 h-4"
-																			fill="none"
-																			stroke="currentColor"
-																			viewBox="0 0 24 24"
-																		>
-																			<path
-																				strokeLinecap="round"
-																				strokeLinejoin="round"
-																				strokeWidth={2}
-																				d="M12 4v16m8-8H4"
-																			/>
-																		</svg>
-																		Create new playlist
-																	</button>
-																</div>
-															)}
-														</div>
-													</div>
-												</div>
-											</div>
-										))}
-									</div>
-								)}
-							</>
-						)}
-					</div>
-				</div>
-			</div>
-		</div>
-	);
+  const navigate = useNavigate();
+  const { play, currentSong } = usePlayer();
+  const [songs, setSongs] = useState<Song[]>([]);
+  const [loading, setLoading] = useState<boolean>(true);
+
+  // search state
+  const [searchInput, setSearchInput] = useState("");
+  const [activeQuery, setActiveQuery] = useState("");
+  const [searchCategory, setSearchCategory] = useState<SearchCategory>("songs");
+  const [searchResults, setSearchResults] = useState<unknown[]>([]);
+  const [searchLoading, setSearchLoading] = useState(false);
+  const [hasSearched, setHasSearched] = useState(false);
+
+  // playlist dropdown state
+  const [openPlaylistDropdown, setOpenPlaylistDropdown] = useState<
+    number | null
+  >(null);
+
+  useEffect(() => {
+    const fetchSongs = async () => {
+      try {
+        const response = await axiosInstance.get("/songs/top");
+        setSongs(response.data);
+      } catch (error) {
+        console.error("Error fetching songs:", error);
+      } finally {
+        setLoading(false);
+      }
+    };
+    fetchSongs();
+  }, []);
+
+  const toggleLike = async (songId: number) => {
+    try {
+      await axiosInstance.post(`/musical-entity/${songId}/like`);
+      setSongs((prevSongs) =>
+        prevSongs.map((song) =>
+          song.id === songId
+            ? { ...song, isLikedByCurrentUser: !song.isLikedByCurrentUser }
+            : song,
+        ),
+      );
+    } catch (error) {
+      console.error("Error toggling like:", error);
+    }
+  };
+
+  const togglePlaylistDropdown = (songId: number) => {
+    if (openPlaylistDropdown === songId) {
+      setOpenPlaylistDropdown(null);
+    } else {
+      setOpenPlaylistDropdown(songId);
+    }
+  };
+
+  const handleCreateNewPlaylist = (songId: number) => {
+    console.log(`Creating new playlist for song ${songId}`);
+    // TODO: Implement actual playlist creation
+    setOpenPlaylistDropdown(null);
+  };
+
+  const performSearch = async (query: string, category: SearchCategory) => {
+    if (!query.trim()) return;
+
+    setSearchLoading(true);
+    setHasSearched(true);
+    setActiveQuery(query);
+    setSearchCategory(category);
+
+    try {
+      let endpoint = "";
+      switch (category) {
+        case "songs":
+          endpoint = `/songs/search?q=${encodeURIComponent(query)}`;
+          break;
+        case "albums":
+          endpoint = `/albums/search?q=${encodeURIComponent(query)}`;
+          break;
+        case "artists":
+          endpoint = `/users/search?type=ARTIST&q=${encodeURIComponent(query)}`;
+          break;
+        case "users":
+          endpoint = `/users/search?type=LISTENER&q=${encodeURIComponent(query)}`;
+          break;
+      }
+
+      const response = await axiosInstance.get(endpoint);
+      setSearchResults(response.data);
+    } catch (error) {
+      console.error("Search error:", error);
+      setSearchResults([]);
+    } finally {
+      setSearchLoading(false);
+    }
+  };
+
+  const handleSearch = () => {
+    performSearch(searchInput, searchCategory);
+  };
+
+  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
+    if (e.key === "Enter") {
+      handleSearch();
+    }
+  };
+
+  const handleCategorySwitch = (category: SearchCategory) => {
+    performSearch(activeQuery, category);
+  };
+
+  const clearSearch = () => {
+    setSearchInput("");
+    setActiveQuery("");
+    setHasSearched(false);
+    setSearchResults([]);
+  };
+
+  const renderResults = () => {
+    if (searchLoading) {
+      return (
+        <div className="flex justify-center py-12">
+          <div className="w-10 h-10 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
+        </div>
+      );
+    }
+
+    if (searchResults.length === 0) {
+      return (
+        <div className="text-center py-12 text-gray-400">
+          <p className="text-lg">
+            No {searchCategory} found for "{activeQuery}"
+          </p>
+        </div>
+      );
+    }
+
+    return (
+      <div className="divide-y divide-white/5">
+        {searchResults.map((result, index) => {
+          switch (searchCategory) {
+            case "songs":
+              return (
+                <SongResult key={(result as Song).id} song={result as Song} />
+              );
+            case "albums":
+              return (
+                <AlbumResult
+                  key={(result as Album).id}
+                  album={result as Album}
+                />
+              );
+            case "artists":
+              return (
+                <UserResult
+                  key={(result as BaseNonAdminUser).username ?? index}
+                  user={result as BaseNonAdminUser}
+                  label="Artist"
+                />
+              );
+            case "users":
+              return (
+                <UserResult
+                  key={(result as BaseNonAdminUser).username ?? index}
+                  user={result as BaseNonAdminUser}
+                  label="User"
+                />
+              );
+          }
+        })}
+      </div>
+    );
+  };
+
+  return (
+    <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white flex">
+      <div className="flex-1">
+        <div className="p-8">
+          <div className="max-w-7xl mx-auto">
+            {/* Search Bar */}
+            <div className="mb-8 flex flex-col md:flex-row gap-3">
+              <div className="flex flex-1 gap-0">
+                {/* Category Dropdown */}
+                <select
+                  value={searchCategory}
+                  onChange={(e) =>
+                    setSearchCategory(e.target.value as SearchCategory)
+                  }
+                  className="bg-[#282828] border border-white/10 border-r-0 rounded-l-full py-2 px-4 text-white text-sm focus:outline-none focus:border-[#1db954] appearance-none cursor-pointer"
+                >
+                  {CATEGORIES.map((cat) => (
+                    <option key={cat.value} value={cat.value}>
+                      {cat.label}
+                    </option>
+                  ))}
+                </select>
+
+                {/* Search Input */}
+                <input
+                  type="text"
+                  placeholder={`Search ${searchCategory}...`}
+                  value={searchInput}
+                  onChange={(e) => setSearchInput(e.target.value)}
+                  onKeyDown={handleKeyDown}
+                  className="flex-1 bg-[#282828] border border-white/10 border-r-0 py-2 px-4 text-white focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
+                />
+
+                {/* Search Button */}
+                <button
+                  onClick={handleSearch}
+                  className="bg-[#1db954] hover:bg-[#1ed760] text-black font-medium px-6 rounded-r-full transition-colors flex items-center gap-2"
+                >
+                  <svg
+                    className="w-5 h-5"
+                    fill="none"
+                    stroke="currentColor"
+                    viewBox="0 0 24 24"
+                  >
+                    <path
+                      strokeLinecap="round"
+                      strokeLinejoin="round"
+                      strokeWidth={2}
+                      d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
+                    />
+                  </svg>
+                  <span className="hidden sm:inline">Search</span>
+                </button>
+              </div>
+            </div>
+
+            {/* Search Results Section */}
+            {hasSearched ? (
+              <div>
+                <div className="flex items-center justify-between mb-4">
+                  <h2 className="text-2xl font-bold text-white">
+                    Results for "{activeQuery}"
+                  </h2>
+                  <button
+                    onClick={clearSearch}
+                    className="text-sm text-gray-400 hover:text-white transition-colors"
+                  >
+                    Clear search
+                  </button>
+                </div>
+
+                {/* Quick category switch buttons */}
+                <div className="flex gap-2 mb-6">
+                  {CATEGORIES.map((cat) => (
+                    <button
+                      key={cat.value}
+                      onClick={() => handleCategorySwitch(cat.value)}
+                      className={`px-4 py-1.5 rounded-full text-sm font-medium transition-colors ${
+                        searchCategory === cat.value
+                          ? "bg-[#1db954] text-black"
+                          : "bg-white/10 text-white hover:bg-white/20"
+                      }`}
+                    >
+                      {cat.label}
+                    </button>
+                  ))}
+                </div>
+
+                {/* Results list */}
+                <div className="bg-[#1a1a2e]/50 rounded-xl overflow-hidden">
+                  {renderResults()}
+                </div>
+              </div>
+            ) : (
+              /* Default song grid */
+              <>
+                <div className="mb-8 border-b border-white/10 pb-6">
+                  <h1 className="text-5xl font-bold mb-3 pb-1 bg-linear-to-r from-[#1db954] to-[#1ed760] bg-clip-text text-transparent">
+                    Top Songs
+                  </h1>
+                  <p className="text-xl text-gray-400">
+                    Listen to the newest tracks on FinkWave
+                  </p>
+                </div>
+
+                {loading ? (
+                  <div className="flex flex-col items-center justify-center min-h-[40vh] gap-6">
+                    <div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
+                    <p className="text-xl text-gray-400">Loading songs...</p>
+                  </div>
+                ) : (
+                  <div className="grid grid-cols-[repeat(auto-fill,minmax(220px,1fr))] gap-8 py-4">
+                    {songs.map((song) => (
+                      <div
+                        key={song.id}
+                        onClick={() => navigate(`/songs/${song.id}`)}
+                        onMouseEnter={() => {
+                          if (
+                            openPlaylistDropdown !== null &&
+                            openPlaylistDropdown !== song.id
+                          ) {
+                            setOpenPlaylistDropdown(null);
+                          }
+                        }}
+                        className="bg-[#282828] rounded-xl cursor-pointer shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-2 hover:shadow-2xl group relative"
+                      >
+                        <div className="relative w-full pt-[100%] overflow-hidden bg-[#181818] rounded-t-xl">
+                          <img
+                            src={
+                              song.cover
+                                ? `${baseURL}/${song.cover}`
+                                : "/favicon.png"
+                            }
+                            alt={song.title}
+                            className="absolute top-0 left-0 w-full h-full object-cover"
+                            onError={(e) => {
+                              (e.target as HTMLImageElement).src =
+                                "/favicon.png";
+                            }}
+                          />
+                          <div className="absolute top-0 left-0 w-full h-full bg-black/60 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
+                            {song.link ? (
+                              <button
+                                onClick={(e) => {
+                                  e.stopPropagation();
+                                  play({
+                                    id: song.id,
+                                    title: song.title,
+                                    artist: song.releasedBy,
+                                    cover: song.cover,
+                                    embedUrl: toEmbedUrl(song.link!),
+                                  });
+                                }}
+                                className={`w-14 h-14 rounded-full flex items-center justify-center text-xl shadow-[0_4px_12px_rgba(29,185,84,0.5)] transition-all cursor-pointer ${
+                                  currentSong?.id === song.id
+                                    ? "bg-white text-[#1db954]"
+                                    : "bg-[#1db954] text-black hover:scale-105"
+                                }`}
+                                aria-label={
+                                  currentSong?.id === song.id
+                                    ? "Now playing"
+                                    : "Play song"
+                                }
+                              >
+                                {currentSong?.id === song.id ? (
+                                  <svg
+                                    className="w-6 h-6"
+                                    fill="currentColor"
+                                    viewBox="0 0 24 24"
+                                  >
+                                    <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
+                                  </svg>
+                                ) : (
+                                  <svg
+                                    className="w-6 h-6"
+                                    fill="currentColor"
+                                    viewBox="0 0 24 24"
+                                  >
+                                    <path d="M8 5v14l11-7z" />
+                                  </svg>
+                                )}
+                              </button>
+                            ) : (
+                              <div className="w-14 h-14 rounded-full bg-[#1db954] flex items-center justify-center text-xl text-black shadow-[0_4px_12px_rgba(29,185,84,0.5)]">
+                                ▶
+                              </div>
+                            )}
+                          </div>
+                        </div>
+                        <div className="p-4">
+                          <h3 className="text-lg font-semibold mb-2 text-white overflow-hidden text-ellipsis whitespace-nowrap">
+                            {song.title}
+                          </h3>
+                          {song.album && (
+                            <p
+                              onClick={(e) => {
+                                e.stopPropagation();
+                                if (song.albumId) {
+                                  navigate(`/collection/album/${song.albumId}`);
+                                }
+                              }}
+                              className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${
+                                song.albumId
+                                  ? "hover:underline cursor-pointer hover:text-white"
+                                  : ""
+                              }`}
+                            >
+                              {song.album}
+                            </p>
+                          )}
+                          <p
+                            onClick={(e) => {
+                              e.stopPropagation();
+                              if (song.artistUsername) {
+                                navigate(`/users/${song.artistUsername}`);
+                              }
+                            }}
+                            className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${
+                              song.artistUsername
+                                ? "hover:underline cursor-pointer hover:text-white"
+                                : ""
+                            }`}
+                          >
+                            {song.releasedBy}
+                          </p>
+                          <div className="flex items-center justify-between mt-4 pt-3 border-t border-white/10">
+                            {/* Like button */}
+                            <button
+                              onClick={(e) => {
+                                e.stopPropagation();
+                                toggleLike(song.id);
+                              }}
+                              className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
+                              aria-label={
+                                song.isLikedByCurrentUser
+                                  ? "Unlike song"
+                                  : "Like song"
+                              }
+                            >
+                              {song.isLikedByCurrentUser ? (
+                                <svg
+                                  className="w-6 h-6 fill-[#1db954]"
+                                  viewBox="0 0 24 24"
+                                >
+                                  <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
+                                </svg>
+                              ) : (
+                                <svg
+                                  className="w-6 h-6"
+                                  fill="none"
+                                  stroke="currentColor"
+                                  viewBox="0 0 24 24"
+                                >
+                                  <path
+                                    strokeLinecap="round"
+                                    strokeLinejoin="round"
+                                    strokeWidth={2}
+                                    d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
+                                  />
+                                </svg>
+                              )}
+                            </button>
+
+                            {/* Add to playlist button */}
+                            <div className="relative">
+                              <button
+                                onClick={(e) => {
+                                  e.stopPropagation();
+                                  togglePlaylistDropdown(song.id);
+                                }}
+                                className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
+                                aria-label="Add to playlist"
+                              >
+                                <svg
+                                  className="w-6 h-6"
+                                  fill="none"
+                                  stroke="currentColor"
+                                  viewBox="0 0 24 24"
+                                >
+                                  <path
+                                    strokeLinecap="round"
+                                    strokeLinejoin="round"
+                                    strokeWidth={2}
+                                    d="M12 4v16m8-8H4"
+                                  />
+                                </svg>
+                              </button>
+
+                              <PlaylistDropdown
+                                songId={song.id}
+                                isOpen={openPlaylistDropdown === song.id}
+                                onClose={() => setOpenPlaylistDropdown(null)}
+                                onCreateNewPlaylist={() =>
+                                  handleCreateNewPlaylist(song.id)
+                                }
+                                direction="above"
+                              />
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    ))}
+                  </div>
+                )}
+              </>
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
 };
 
Index: frontend/src/pages/MusicalCollection.tsx
===================================================================
--- frontend/src/pages/MusicalCollection.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/pages/MusicalCollection.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -21,4 +21,7 @@
   const [isLoading, setIsLoading] = useState(true);
   const [error, setError] = useState<string | null>(null);
+  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
+    null,
+  );
 
   const normalizeCollection = (
@@ -236,4 +239,6 @@
                   index={index + 1}
                   onLikeToggle={() => toggleLike(song.id)}
+                  isDropdownOpen={openDropdownSongId === song.id}
+                  onDropdownToggle={setOpenDropdownSongId}
                 />
               ))}
Index: frontend/src/pages/SongDetail.tsx
===================================================================
--- frontend/src/pages/SongDetail.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/pages/SongDetail.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -1,6 +1,7 @@
-import { useEffect, useRef, useState } from "react";
+import { useEffect, useState } from "react";
 import { Link, useParams } from "react-router-dom";
 import { toast } from "react-toastify";
 import axiosInstance, { baseURL } from "../api/axiosInstance";
+import PlaylistDropdown from "../components/PlaylistDropdown";
 import { useAuth } from "../context/authContext";
 import { usePlayer } from "../context/playerContext";
@@ -9,654 +10,590 @@
 
 const ROLE_LABELS: Record<string, string> = {
-	MAIN_VOCAL: "Main Vocal",
-	FEATURED: "Featured",
-	PRODUCER: "Producer",
-	SONGWRITER: "Songwriter",
-	COMPOSER: "Composer",
-	MIXER: "Mixer",
-	ENGINEER: "Engineer",
+  MAIN_VOCAL: "Main Vocal",
+  FEATURED: "Featured",
+  PRODUCER: "Producer",
+  SONGWRITER: "Songwriter",
+  COMPOSER: "Composer",
+  MIXER: "Mixer",
+  ENGINEER: "Engineer",
 };
 
 const formatRole = (role: string): string => {
-	return ROLE_LABELS[role] || role.replace(/_/g, " ");
+  return ROLE_LABELS[role] || role.replace(/_/g, " ");
 };
 
 const renderStars = (grade: number) => {
-	return (
-		<div className="flex gap-0.5">
-			{[1, 2, 3, 4, 5].map((star) => (
-				<svg
-					key={star}
-					className={`w-4 h-4 ${star <= grade ? "text-yellow-400" : "text-gray-600"}`}
-					fill="currentColor"
-					viewBox="0 0 20 20"
-				>
-					<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
-				</svg>
-			))}
-		</div>
-	);
+  return (
+    <div className="flex gap-0.5">
+      {[1, 2, 3, 4, 5].map((star) => (
+        <svg
+          key={star}
+          className={`w-4 h-4 ${star <= grade ? "text-yellow-400" : "text-gray-600"}`}
+          fill="currentColor"
+          viewBox="0 0 20 20"
+        >
+          <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
+        </svg>
+      ))}
+    </div>
+  );
 };
 
 const SongDetail = () => {
-	const { id } = useParams<{ id: string }>();
-	const { user } = useAuth();
-	const { play, currentSong } = usePlayer();
-	const [song, setSong] = useState<SongDetailType | null>(null);
-	const [loading, setLoading] = useState(true);
-	const [error, setError] = useState<string | null>(null);
-	const [showReviewModal, setShowReviewModal] = useState(false);
-	const [reviewRating, setReviewRating] = useState(0);
-	const [reviewComment, setReviewComment] = useState("");
-	const [hoverRating, setHoverRating] = useState(0);
-	const [showPlaylistDropdown, setShowPlaylistDropdown] = useState(false);
-	const playlistDropdownRef = useRef<HTMLDivElement>(null);
-	console.log(user);
-	useEffect(() => {
-		const fetchSong = async () => {
-			try {
-				setLoading(true);
-				const response = await axiosInstance.get(`/songs/${id}/details`);
-				setSong(response.data);
-			} catch (err) {
-				console.error("Error fetching song details:", err);
-				setError("Failed to load song details.");
-			} finally {
-				setLoading(false);
-			}
-		};
-		if (id) fetchSong();
-	}, [id]);
-
-	// handle click outside for playlist dropdown
-	useEffect(() => {
-		const handleClickOutside = (event: MouseEvent) => {
-			if (
-				playlistDropdownRef.current &&
-				!playlistDropdownRef.current.contains(event.target as Node)
-			) {
-				setShowPlaylistDropdown(false);
-			}
-		};
-
-		document.addEventListener("mousedown", handleClickOutside);
-		return () => {
-			document.removeEventListener("mousedown", handleClickOutside);
-		};
-	}, []);
-
-	const handleSubmitReview = async () => {
-		if (reviewRating === 0) {
-			// todo: replace with toast
-			alert("Please select a rating");
-			return;
-		}
-		try {
-			await axiosInstance.post(`reviews/${song?.id}`, {
-				grade: reviewRating,
-				comment: reviewComment,
-			});
-			const response = await axiosInstance.get(`/songs/${id}/details`);
-			setSong(response.data);
-		} catch (err) {
-			// todo: replace with toast
-			console.error("Error submitting review:", err);
-		} finally {
-			setShowReviewModal(false);
-			setReviewRating(0);
-			setReviewComment("");
-			setHoverRating(0);
-		}
-	};
-
-	const deleteReview = async () => {
-		try {
-			await axiosInstance.delete(`reviews/${song?.id}`);
-			const response = await axiosInstance.get(`/songs/${id}/details`);
-			setSong(response.data);
-		} catch (err) {
-			toast.error("Failed to delete review");
-			console.error("Error deleting review:", err);
-		}
-	};
-
-	const toggleLike = async () => {
-		if (!song) return;
-		try {
-			await axiosInstance.post(`/musical-entity/${song.id}/like`);
-			setSong((prev) =>
-				prev
-					? { ...prev, isLikedByCurrentUser: !prev.isLikedByCurrentUser }
-					: prev,
-			);
-		} catch (err) {
-			toast.error("Failed to toggle like");
-			console.error("Error toggling like:", err);
-		}
-	};
-
-	const handleAddToPlaylist = (playlistName: string) => {
-		console.log(`Adding song ${song?.id} to ${playlistName}`);
-		// TODO: actual API call
-		setShowPlaylistDropdown(false);
-	};
-
-	const handleCreateNewPlaylist = () => {
-		console.log(`Creating new playlist for song ${song?.id}`);
-		// TODO: actual playlist creation
-		setShowPlaylistDropdown(false);
-	};
-
-	if (loading) {
-		return (
-			<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-				<div className="flex flex-col items-center gap-4">
-					<div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin" />
-					<p className="text-gray-400 text-lg">Loading song…</p>
-				</div>
-			</div>
-		);
-	}
-
-	if (error || !song) {
-		return (
-			<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-				<div className="text-center">
-					<p className="text-red-400 text-xl mb-4">
-						{error ?? "Song not found"}
-					</p>
-					<Link to="/" className="text-[#1db954] hover:underline text-sm">
-						← Back to Home
-					</Link>
-				</div>
-			</div>
-		);
-	}
-
-	const otherContributors = song.contributions.filter(
-		(c) => c.artistName !== song.releasedBy,
-	);
-
-	const avgRating =
-		song.reviews.length > 0
-			? (
-					song.reviews.reduce((sum, r) => sum + r.grade, 0) /
-					song.reviews.length
-				).toFixed(1)
-			: null;
-
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white">
-			<div className="max-w-5xl mx-auto px-6 py-10">
-				{/* Back link */}
-				<Link
-					to="/"
-					className="inline-flex items-center gap-1 text-gray-400 hover:text-white text-sm mb-8 transition-colors"
-				>
-					<svg
-						className="w-4 h-4"
-						fill="none"
-						stroke="currentColor"
-						viewBox="0 0 24 24"
-					>
-						<path
-							strokeLinecap="round"
-							strokeLinejoin="round"
-							strokeWidth={2}
-							d="M15 19l-7-7 7-7"
-						/>
-					</svg>
-					Back to Home
-				</Link>
-
-				{/* Hero section */}
-				<div className="flex flex-col md:flex-row gap-8 mb-10">
-					{/* Cover art */}
-					<div className="w-full md:w-72 shrink-0">
-						<div className="relative w-full pt-[100%] rounded-xl overflow-hidden shadow-2xl bg-[#181818]">
-							<img
-								src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
-								alt={song.title}
-								className="absolute inset-0 w-full h-full object-cover"
-								onError={(e) => {
-									(e.target as HTMLImageElement).src = "/favicon.png";
-								}}
-							/>
-						</div>
-					</div>
-
-					{/* Song info */}
-					<div className="flex flex-col justify-end gap-3 min-w-0">
-						<span className="text-xs uppercase tracking-widest text-gray-400 font-medium">
-							{song.genre} • Song
-						</span>
-						<h1 className="text-4xl md:text-5xl font-extrabold leading-tight truncate">
-							{song.title}
-						</h1>
-
-						{/* Main artist */}
-						<p className="text-xl text-gray-300 font-semibold">
-							{song.releasedBy}
-						</p>
-
-						{/* Album */}
-						{song.album && (
-							<p className="text-sm text-gray-500">
-								Album: <span className="text-gray-300">{song.album}</span>
-							</p>
-						)}
-
-						{/* Rating summary */}
-						{avgRating && (
-							<div className="flex items-center gap-2 mt-1">
-								{renderStars(Math.round(Number(avgRating)))}
-								<span className="text-sm text-gray-400">
-									{avgRating} · {song.reviews.length}{" "}
-									{song.reviews.length === 1 ? "review" : "reviews"}
-								</span>
-							</div>
-						)}
-
-						{/* Action buttons */}
-						<div className="flex items-center gap-3 mt-4">
-							{/* Play button */}
-							{song.link && (
-								<button
-									onClick={() =>
-										play({
-											id: song.id,
-											title: song.title,
-											artist: song.releasedBy,
-											cover: song.cover,
-											embedUrl: toEmbedUrl(song.link!),
-										})
-									}
-									className={`flex items-center gap-2 px-6 py-3 rounded-full text-sm font-semibold transition-all cursor-pointer ${
-										currentSong?.id === song.id
-											? "bg-white text-[#1db954]"
-											: "bg-[#1db954] text-black hover:bg-[#1ed760] hover:scale-105"
-									}`}
-								>
-									{currentSong?.id === song.id ? (
-										<>
-											<svg
-												className="w-5 h-5"
-												fill="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-											</svg>
-											Now Playing
-										</>
-									) : (
-										<>
-											<svg
-												className="w-5 h-5"
-												fill="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path d="M8 5v14l11-7z" />
-											</svg>
-											Play Song
-										</>
-									)}
-								</button>
-							)}
-
-							{user && (
-								<>
-									<button
-										onClick={toggleLike}
-										className={`flex items-center gap-2 px-5 py-3 rounded-full text-sm font-semibold transition-colors cursor-pointer ${
-											song.isLikedByCurrentUser
-												? "bg-[#1db954] text-black"
-												: "bg-white/10 text-white hover:bg-white/20"
-										}`}
-									>
-										{song.isLikedByCurrentUser ? (
-											<svg
-												className="w-5 h-5"
-												fill="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
-											</svg>
-										) : (
-											<svg
-												className="w-5 h-5"
-												fill="none"
-												stroke="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path
-													strokeLinecap="round"
-													strokeLinejoin="round"
-													strokeWidth={2}
-													d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
-												/>
-											</svg>
-										)}
-										{song.isLikedByCurrentUser ? "Liked" : "Like"}
-									</button>
-
-									{/* Add to Playlist button */}
-									<div className="relative" ref={playlistDropdownRef}>
-										<button
-											onClick={() =>
-												setShowPlaylistDropdown(!showPlaylistDropdown)
-											}
-											className="flex items-center gap-2 px-5 py-3 rounded-full text-sm font-semibold bg-white/10 text-white hover:bg-white/20 transition-colors cursor-pointer"
-										>
-											<svg
-												className="w-5 h-5"
-												fill="none"
-												stroke="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path
-													strokeLinecap="round"
-													strokeLinejoin="round"
-													strokeWidth={2}
-													d="M12 4v16m8-8H4"
-												/>
-											</svg>
-											Add to Playlist
-										</button>
-
-										{/* Playlist dropdown */}
-										{showPlaylistDropdown && (
-											<div className="absolute left-0 top-full mt-2 w-56 bg-[#282828] rounded-lg shadow-2xl py-1 z-50 border border-white/10">
-												<div className="px-3 py-2 text-xs text-gray-400 border-b border-white/10">
-													Add to playlist
-												</div>
-												<button
-													onClick={() => handleAddToPlaylist("Hello")}
-													className="w-full text-left px-4 py-2.5 text-sm text-white hover:bg-white/10 transition-colors"
-												>
-													Hello
-												</button>
-												<button
-													onClick={() => handleAddToPlaylist("Dimi")}
-													className="w-full text-left px-4 py-2.5 text-sm text-white hover:bg-white/10 transition-colors"
-												>
-													Dimi
-												</button>
-												<button
-													onClick={() => handleAddToPlaylist("lmao")}
-													className="w-full text-left px-4 py-2.5 text-sm text-white hover:bg-white/10 transition-colors"
-												>
-													Kako hello world ama ti si mojot world
-												</button>
-												<button
-													onClick={handleCreateNewPlaylist}
-													className="w-full text-left px-4 py-2.5 text-sm text-[#1db954] hover:bg-white/10 transition-colors border-t border-white/10 flex items-center gap-2"
-												>
-													<svg
-														className="w-4 h-4"
-														fill="none"
-														stroke="currentColor"
-														viewBox="0 0 24 24"
-													>
-														<path
-															strokeLinecap="round"
-															strokeLinejoin="round"
-															strokeWidth={2}
-															d="M12 4v16m8-8H4"
-														/>
-													</svg>
-													Create new playlist
-												</button>
-											</div>
-										)}
-									</div>
-								</>
-							)}
-						</div>
-					</div>
-				</div>
-
-				{/* Credits / Contributions */}
-				{song.contributions.length > 0 && (
-					<section className="mb-10">
-						<h2 className="text-2xl font-bold mb-4">Credits</h2>
-						<div className="bg-[#1a1a2e]/60 rounded-xl p-5 divide-y divide-white/5">
-							{/* Main artist first */}
-							{song.contributions
-								.filter((c) => c.artistName === song.releasedBy)
-								.map((c, i) => (
-									<div
-										key={`main-${i}`}
-										className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
-									>
-										<div className="flex items-center gap-3">
-											<div className="w-10 h-10 bg-[#1db954] rounded-full flex items-center justify-center text-black font-bold text-sm">
-												{c.artistName.charAt(0).toUpperCase()}
-											</div>
-											<div>
-												<p className="text-white font-semibold text-lg">
-													{c.artistName}
-												</p>
-											</div>
-										</div>
-										<span className="text-sm text-gray-400 bg-white/5 px-3 py-1 rounded-full">
-											{formatRole(c.role)}
-										</span>
-									</div>
-								))}
-
-							{/* Other contributors */}
-							{otherContributors.map((c, i) => (
-								<div
-									key={`contrib-${i}`}
-									className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
-								>
-									<div className="flex items-center gap-3">
-										<div className="w-9 h-9 bg-white/10 rounded-full flex items-center justify-center text-white font-medium text-sm">
-											{c.artistName.charAt(0).toUpperCase()}
-										</div>
-										<p className="text-gray-300 font-medium">{c.artistName}</p>
-									</div>
-									<span className="text-sm text-gray-500 bg-white/5 px-3 py-1 rounded-full">
-										{formatRole(c.role)}
-									</span>
-								</div>
-							))}
-						</div>
-					</section>
-				)}
-
-				{/* Reviews */}
-				<section>
-					<div className="flex items-center justify-between mb-4">
-						<h2 className="text-2xl font-bold">
-							Reviews
-							{song.reviews.length > 0 && (
-								<span className="text-base font-normal text-gray-500 ml-2">
-									({song.reviews.length})
-								</span>
-							)}
-						</h2>
-						<button
-							onClick={() => setShowReviewModal(true)}
-							className="flex items-center gap-2 bg-[#1db954] hover:bg-[#1ed760] text-black text-sm font-semibold px-4 py-2 rounded-full transition-colors"
-						>
-							<svg
-								className="w-4 h-4"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M12 4v16m8-8H4"
-								/>
-							</svg>
-							Add Review
-						</button>
-					</div>
-
-					{song.reviews.length === 0 ? (
-						<div className="bg-[#1a1a2e]/60 rounded-xl p-10 text-center">
-							<p className="text-gray-500 text-lg">No reviews yet.</p>
-							<p className="text-gray-600 text-sm mt-1">
-								Be the first to share your thoughts!
-							</p>
-						</div>
-					) : (
-						<div className="space-y-4">
-							{song.reviews.map((review) => (
-								<div
-									key={`${review.id.listenerId}-${review.id.musicalEntityId}`}
-									className="bg-[#1a1a2e]/60 rounded-xl p-5 hover:bg-[#1a1a2e]/80 transition-colors"
-								>
-									<div className="flex items-start justify-between mb-2">
-										<div className="flex items-center gap-3">
-											<div className="w-9 h-9 bg-blue-500/20 rounded-full flex items-center justify-center">
-												<span className="text-blue-400 font-semibold text-sm">
-													{review.author.charAt(0).toUpperCase()}
-												</span>
-											</div>
-											<div>
-												<p className="text-white font-medium">
-													{review.author}
-												</p>
-												{renderStars(review.grade)}
-											</div>
-										</div>
-										{user?.username === review.authorUsername && (
-											<button
-												onClick={deleteReview}
-												className="text-gray-500 hover:text-red-400 transition-colors p-2 rounded-lg hover:bg-red-400/10"
-												title="Delete review"
-											>
-												<svg
-													className="w-5 h-5"
-													fill="none"
-													stroke="currentColor"
-													viewBox="0 0 24 24"
-												>
-													<path
-														strokeLinecap="round"
-														strokeLinejoin="round"
-														strokeWidth={2}
-														d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
-													/>
-												</svg>
-											</button>
-										)}
-									</div>
-									<p className="text-gray-300 text-sm leading-relaxed mt-3 pl-12">
-										{review.comment}
-									</p>
-								</div>
-							))}
-						</div>
-					)}
-				</section>
-			</div>
-
-			{/* Review Modal */}
-			{showReviewModal && (
-				<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/70 backdrop-blur-sm">
-					<div className="bg-[#1a1a2e] rounded-2xl p-6 max-w-md w-full shadow-2xl">
-						<div className="flex items-center justify-between mb-6">
-							<h3 className="text-2xl font-bold">Add Review</h3>
-							<button
-								onClick={() => {
-									setShowReviewModal(false);
-									setReviewRating(0);
-									setReviewComment("");
-									setHoverRating(0);
-								}}
-								className="text-gray-400 hover:text-white transition-colors"
-							>
-								<svg
-									className="w-6 h-6"
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={2}
-										d="M6 18L18 6M6 6l12 12"
-									/>
-								</svg>
-							</button>
-						</div>
-
-						{/* Star Rating */}
-						<div className="mb-6">
-							<label className="block text-sm font-medium mb-3">
-								Rating <span className="text-red-400">*</span>
-							</label>
-							<div className="flex gap-2">
-								{[1, 2, 3, 4, 5].map((star) => (
-									<button
-										key={star}
-										onClick={() => setReviewRating(star)}
-										onMouseEnter={() => setHoverRating(star)}
-										onMouseLeave={() => setHoverRating(0)}
-										className="transition-transform hover:scale-110"
-									>
-										<svg
-											className={`w-10 h-10 ${
-												star <= (hoverRating || reviewRating)
-													? "text-yellow-400"
-													: "text-gray-600"
-											}`}
-											fill="currentColor"
-											viewBox="0 0 20 20"
-										>
-											<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
-										</svg>
-									</button>
-								))}
-							</div>
-						</div>
-
-						{/* Comment */}
-						<div className="mb-6">
-							<label className="block text-sm font-medium mb-2">
-								Comment <span className="text-gray-500">(optional)</span>
-							</label>
-							<textarea
-								value={reviewComment}
-								onChange={(e) => setReviewComment(e.target.value)}
-								placeholder="Share your thoughts about this song..."
-								rows={4}
-								className="w-full bg-[#0f0f1e] border border-white/10 rounded-lg px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] transition-colors resize-none"
-							/>
-						</div>
-
-						{/* Actions */}
-						<div className="flex gap-3 justify-end">
-							<button
-								onClick={() => {
-									setShowReviewModal(false);
-									setReviewRating(0);
-									setReviewComment("");
-									setHoverRating(0);
-								}}
-								className="px-5 py-2.5 rounded-full text-sm font-semibold bg-white/10 hover:bg-white/20 transition-colors"
-							>
-								Cancel
-							</button>
-							<button
-								onClick={handleSubmitReview}
-								disabled={reviewRating === 0}
-								className="px-5 py-2.5 rounded-full text-sm font-semibold bg-[#1db954] hover:bg-[#1ed760] text-black transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
-							>
-								Submit
-							</button>
-						</div>
-					</div>
-				</div>
-			)}
-		</div>
-	);
+  const { id } = useParams<{ id: string }>();
+  const { user } = useAuth();
+  const { play, currentSong } = usePlayer();
+  const [song, setSong] = useState<SongDetailType | null>(null);
+  const [loading, setLoading] = useState(true);
+  const [error, setError] = useState<string | null>(null);
+  const [showReviewModal, setShowReviewModal] = useState(false);
+  const [reviewRating, setReviewRating] = useState(0);
+  const [reviewComment, setReviewComment] = useState("");
+  const [hoverRating, setHoverRating] = useState(0);
+  const [showPlaylistDropdown, setShowPlaylistDropdown] = useState(false);
+  console.log(user);
+  useEffect(() => {
+    const fetchSong = async () => {
+      try {
+        setLoading(true);
+        const response = await axiosInstance.get(`/songs/${id}/details`);
+        setSong(response.data);
+      } catch (err) {
+        console.error("Error fetching song details:", err);
+        setError("Failed to load song details.");
+      } finally {
+        setLoading(false);
+      }
+    };
+    if (id) fetchSong();
+  }, [id]);
+
+  const handleSubmitReview = async () => {
+    if (reviewRating === 0) {
+      // todo: replace with toast
+      alert("Please select a rating");
+      return;
+    }
+    try {
+      await axiosInstance.post(`reviews/${song?.id}`, {
+        grade: reviewRating,
+        comment: reviewComment,
+      });
+      const response = await axiosInstance.get(`/songs/${id}/details`);
+      setSong(response.data);
+    } catch (err) {
+      // todo: replace with toast
+      console.error("Error submitting review:", err);
+    } finally {
+      setShowReviewModal(false);
+      setReviewRating(0);
+      setReviewComment("");
+      setHoverRating(0);
+    }
+  };
+
+  const deleteReview = async () => {
+    try {
+      await axiosInstance.delete(`reviews/${song?.id}`);
+      const response = await axiosInstance.get(`/songs/${id}/details`);
+      setSong(response.data);
+    } catch (err) {
+      toast.error("Failed to delete review");
+      console.error("Error deleting review:", err);
+    }
+  };
+
+  const toggleLike = async () => {
+    if (!song) return;
+    try {
+      await axiosInstance.post(`/musical-entity/${song.id}/like`);
+      setSong((prev) =>
+        prev
+          ? { ...prev, isLikedByCurrentUser: !prev.isLikedByCurrentUser }
+          : prev,
+      );
+    } catch (err) {
+      toast.error("Failed to toggle like");
+      console.error("Error toggling like:", err);
+    }
+  };
+
+  const handleCreateNewPlaylist = () => {
+    console.log(`Creating new playlist for song ${song?.id}`);
+    // TODO: actual playlist creation
+    setShowPlaylistDropdown(false);
+  };
+
+  if (loading) {
+    return (
+      <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
+        <div className="flex flex-col items-center gap-4">
+          <div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin" />
+          <p className="text-gray-400 text-lg">Loading song…</p>
+        </div>
+      </div>
+    );
+  }
+
+  if (error || !song) {
+    return (
+      <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
+        <div className="text-center">
+          <p className="text-red-400 text-xl mb-4">
+            {error ?? "Song not found"}
+          </p>
+          <Link to="/" className="text-[#1db954] hover:underline text-sm">
+            ← Back to Home
+          </Link>
+        </div>
+      </div>
+    );
+  }
+
+  const otherContributors = song.contributions.filter(
+    (c) => c.artistName !== song.releasedBy,
+  );
+
+  const avgRating =
+    song.reviews.length > 0
+      ? (
+          song.reviews.reduce((sum, r) => sum + r.grade, 0) /
+          song.reviews.length
+        ).toFixed(1)
+      : null;
+
+  return (
+    <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white">
+      <div className="max-w-5xl mx-auto px-6 py-10">
+        {/* Back link */}
+        <Link
+          to="/"
+          className="inline-flex items-center gap-1 text-gray-400 hover:text-white text-sm mb-8 transition-colors"
+        >
+          <svg
+            className="w-4 h-4"
+            fill="none"
+            stroke="currentColor"
+            viewBox="0 0 24 24"
+          >
+            <path
+              strokeLinecap="round"
+              strokeLinejoin="round"
+              strokeWidth={2}
+              d="M15 19l-7-7 7-7"
+            />
+          </svg>
+          Back to Home
+        </Link>
+
+        {/* Hero section */}
+        <div className="flex flex-col md:flex-row gap-8 mb-10">
+          {/* Cover art */}
+          <div className="w-full md:w-72 shrink-0">
+            <div className="relative w-full pt-[100%] rounded-xl overflow-hidden shadow-2xl bg-[#181818]">
+              <img
+                src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
+                alt={song.title}
+                className="absolute inset-0 w-full h-full object-cover"
+                onError={(e) => {
+                  (e.target as HTMLImageElement).src = "/favicon.png";
+                }}
+              />
+            </div>
+          </div>
+
+          {/* Song info */}
+          <div className="flex flex-col justify-end gap-3 min-w-0">
+            <span className="text-xs uppercase tracking-widest text-gray-400 font-medium">
+              {song.genre} • Song
+            </span>
+            <h1 className="text-4xl md:text-5xl font-extrabold leading-tight truncate">
+              {song.title}
+            </h1>
+
+            {/* Main artist */}
+            <p className="text-xl text-gray-300 font-semibold">
+              {song.releasedBy}
+            </p>
+
+            {/* Album */}
+            {song.album && (
+              <p className="text-sm text-gray-500">
+                Album: <span className="text-gray-300">{song.album}</span>
+              </p>
+            )}
+
+            {/* Rating summary */}
+            {avgRating && (
+              <div className="flex items-center gap-2 mt-1">
+                {renderStars(Math.round(Number(avgRating)))}
+                <span className="text-sm text-gray-400">
+                  {avgRating} · {song.reviews.length}{" "}
+                  {song.reviews.length === 1 ? "review" : "reviews"}
+                </span>
+              </div>
+            )}
+
+            {/* Action buttons */}
+            <div className="flex items-center gap-3 mt-4">
+              {/* Play button */}
+              {song.link && (
+                <button
+                  onClick={() =>
+                    play({
+                      id: song.id,
+                      title: song.title,
+                      artist: song.releasedBy,
+                      cover: song.cover,
+                      embedUrl: toEmbedUrl(song.link!),
+                    })
+                  }
+                  className={`flex items-center gap-2 px-6 py-3 rounded-full text-sm font-semibold transition-all cursor-pointer ${
+                    currentSong?.id === song.id
+                      ? "bg-white text-[#1db954]"
+                      : "bg-[#1db954] text-black hover:bg-[#1ed760] hover:scale-105"
+                  }`}
+                >
+                  {currentSong?.id === song.id ? (
+                    <>
+                      <svg
+                        className="w-5 h-5"
+                        fill="currentColor"
+                        viewBox="0 0 24 24"
+                      >
+                        <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
+                      </svg>
+                      Now Playing
+                    </>
+                  ) : (
+                    <>
+                      <svg
+                        className="w-5 h-5"
+                        fill="currentColor"
+                        viewBox="0 0 24 24"
+                      >
+                        <path d="M8 5v14l11-7z" />
+                      </svg>
+                      Play Song
+                    </>
+                  )}
+                </button>
+              )}
+
+              {user && (
+                <>
+                  <button
+                    onClick={toggleLike}
+                    className={`flex items-center gap-2 px-5 py-3 rounded-full text-sm font-semibold transition-colors cursor-pointer ${
+                      song.isLikedByCurrentUser
+                        ? "bg-[#1db954] text-black"
+                        : "bg-white/10 text-white hover:bg-white/20"
+                    }`}
+                  >
+                    {song.isLikedByCurrentUser ? (
+                      <svg
+                        className="w-5 h-5"
+                        fill="currentColor"
+                        viewBox="0 0 24 24"
+                      >
+                        <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
+                      </svg>
+                    ) : (
+                      <svg
+                        className="w-5 h-5"
+                        fill="none"
+                        stroke="currentColor"
+                        viewBox="0 0 24 24"
+                      >
+                        <path
+                          strokeLinecap="round"
+                          strokeLinejoin="round"
+                          strokeWidth={2}
+                          d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
+                        />
+                      </svg>
+                    )}
+                    {song.isLikedByCurrentUser ? "Liked" : "Like"}
+                  </button>
+
+                  {/* Add to Playlist button */}
+                  <div className="relative">
+                    <button
+                      onClick={() => setShowPlaylistDropdown((prev) => !prev)}
+                      className="flex items-center gap-2 px-5 py-3 rounded-full text-sm font-semibold bg-white/10 text-white hover:bg-white/20 transition-colors cursor-pointer"
+                    >
+                      <svg
+                        className="w-5 h-5"
+                        fill="none"
+                        stroke="currentColor"
+                        viewBox="0 0 24 24"
+                      >
+                        <path
+                          strokeLinecap="round"
+                          strokeLinejoin="round"
+                          strokeWidth={2}
+                          d="M12 4v16m8-8H4"
+                        />
+                      </svg>
+                      Add to Playlist
+                    </button>
+
+                    <PlaylistDropdown
+                      songId={song.id}
+                      isOpen={showPlaylistDropdown}
+                      onClose={() => setShowPlaylistDropdown(false)}
+                      onCreateNewPlaylist={handleCreateNewPlaylist}
+                      direction="below"
+                    />
+                  </div>
+                </>
+              )}
+            </div>
+          </div>
+        </div>
+
+        {/* Credits / Contributions */}
+        {song.contributions.length > 0 && (
+          <section className="mb-10">
+            <h2 className="text-2xl font-bold mb-4">Credits</h2>
+            <div className="bg-[#1a1a2e]/60 rounded-xl p-5 divide-y divide-white/5">
+              {/* Main artist first */}
+              {song.contributions
+                .filter((c) => c.artistName === song.releasedBy)
+                .map((c, i) => (
+                  <div
+                    key={`main-${i}`}
+                    className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
+                  >
+                    <div className="flex items-center gap-3">
+                      <div className="w-10 h-10 bg-[#1db954] rounded-full flex items-center justify-center text-black font-bold text-sm">
+                        {c.artistName.charAt(0).toUpperCase()}
+                      </div>
+                      <div>
+                        <p className="text-white font-semibold text-lg">
+                          {c.artistName}
+                        </p>
+                      </div>
+                    </div>
+                    <span className="text-sm text-gray-400 bg-white/5 px-3 py-1 rounded-full">
+                      {formatRole(c.role)}
+                    </span>
+                  </div>
+                ))}
+
+              {/* Other contributors */}
+              {otherContributors.map((c, i) => (
+                <div
+                  key={`contrib-${i}`}
+                  className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
+                >
+                  <div className="flex items-center gap-3">
+                    <div className="w-9 h-9 bg-white/10 rounded-full flex items-center justify-center text-white font-medium text-sm">
+                      {c.artistName.charAt(0).toUpperCase()}
+                    </div>
+                    <p className="text-gray-300 font-medium">{c.artistName}</p>
+                  </div>
+                  <span className="text-sm text-gray-500 bg-white/5 px-3 py-1 rounded-full">
+                    {formatRole(c.role)}
+                  </span>
+                </div>
+              ))}
+            </div>
+          </section>
+        )}
+
+        {/* Reviews */}
+        <section>
+          <div className="flex items-center justify-between mb-4">
+            <h2 className="text-2xl font-bold">
+              Reviews
+              {song.reviews.length > 0 && (
+                <span className="text-base font-normal text-gray-500 ml-2">
+                  ({song.reviews.length})
+                </span>
+              )}
+            </h2>
+            <button
+              onClick={() => setShowReviewModal(true)}
+              className="flex items-center gap-2 bg-[#1db954] hover:bg-[#1ed760] text-black text-sm font-semibold px-4 py-2 rounded-full transition-colors"
+            >
+              <svg
+                className="w-4 h-4"
+                fill="none"
+                stroke="currentColor"
+                viewBox="0 0 24 24"
+              >
+                <path
+                  strokeLinecap="round"
+                  strokeLinejoin="round"
+                  strokeWidth={2}
+                  d="M12 4v16m8-8H4"
+                />
+              </svg>
+              Add Review
+            </button>
+          </div>
+
+          {song.reviews.length === 0 ? (
+            <div className="bg-[#1a1a2e]/60 rounded-xl p-10 text-center">
+              <p className="text-gray-500 text-lg">No reviews yet.</p>
+              <p className="text-gray-600 text-sm mt-1">
+                Be the first to share your thoughts!
+              </p>
+            </div>
+          ) : (
+            <div className="space-y-4">
+              {song.reviews.map((review) => (
+                <div
+                  key={`${review.id.listenerId}-${review.id.musicalEntityId}`}
+                  className="bg-[#1a1a2e]/60 rounded-xl p-5 hover:bg-[#1a1a2e]/80 transition-colors"
+                >
+                  <div className="flex items-start justify-between mb-2">
+                    <div className="flex items-center gap-3">
+                      <div className="w-9 h-9 bg-blue-500/20 rounded-full flex items-center justify-center">
+                        <span className="text-blue-400 font-semibold text-sm">
+                          {review.author.charAt(0).toUpperCase()}
+                        </span>
+                      </div>
+                      <div>
+                        <p className="text-white font-medium">
+                          {review.author}
+                        </p>
+                        {renderStars(review.grade)}
+                      </div>
+                    </div>
+                    {user?.username === review.authorUsername && (
+                      <button
+                        onClick={deleteReview}
+                        className="text-gray-500 hover:text-red-400 transition-colors p-2 rounded-lg hover:bg-red-400/10"
+                        title="Delete review"
+                      >
+                        <svg
+                          className="w-5 h-5"
+                          fill="none"
+                          stroke="currentColor"
+                          viewBox="0 0 24 24"
+                        >
+                          <path
+                            strokeLinecap="round"
+                            strokeLinejoin="round"
+                            strokeWidth={2}
+                            d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
+                          />
+                        </svg>
+                      </button>
+                    )}
+                  </div>
+                  <p className="text-gray-300 text-sm leading-relaxed mt-3 pl-12">
+                    {review.comment}
+                  </p>
+                </div>
+              ))}
+            </div>
+          )}
+        </section>
+      </div>
+
+      {/* Review Modal */}
+      {showReviewModal && (
+        <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/70 backdrop-blur-sm">
+          <div className="bg-[#1a1a2e] rounded-2xl p-6 max-w-md w-full shadow-2xl">
+            <div className="flex items-center justify-between mb-6">
+              <h3 className="text-2xl font-bold">Add Review</h3>
+              <button
+                onClick={() => {
+                  setShowReviewModal(false);
+                  setReviewRating(0);
+                  setReviewComment("");
+                  setHoverRating(0);
+                }}
+                className="text-gray-400 hover:text-white transition-colors"
+              >
+                <svg
+                  className="w-6 h-6"
+                  fill="none"
+                  stroke="currentColor"
+                  viewBox="0 0 24 24"
+                >
+                  <path
+                    strokeLinecap="round"
+                    strokeLinejoin="round"
+                    strokeWidth={2}
+                    d="M6 18L18 6M6 6l12 12"
+                  />
+                </svg>
+              </button>
+            </div>
+
+            {/* Star Rating */}
+            <div className="mb-6">
+              <label className="block text-sm font-medium mb-3">
+                Rating <span className="text-red-400">*</span>
+              </label>
+              <div className="flex gap-2">
+                {[1, 2, 3, 4, 5].map((star) => (
+                  <button
+                    key={star}
+                    onClick={() => setReviewRating(star)}
+                    onMouseEnter={() => setHoverRating(star)}
+                    onMouseLeave={() => setHoverRating(0)}
+                    className="transition-transform hover:scale-110"
+                  >
+                    <svg
+                      className={`w-10 h-10 ${
+                        star <= (hoverRating || reviewRating)
+                          ? "text-yellow-400"
+                          : "text-gray-600"
+                      }`}
+                      fill="currentColor"
+                      viewBox="0 0 20 20"
+                    >
+                      <path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
+                    </svg>
+                  </button>
+                ))}
+              </div>
+            </div>
+
+            {/* Comment */}
+            <div className="mb-6">
+              <label className="block text-sm font-medium mb-2">
+                Comment <span className="text-gray-500">(optional)</span>
+              </label>
+              <textarea
+                value={reviewComment}
+                onChange={(e) => setReviewComment(e.target.value)}
+                placeholder="Share your thoughts about this song..."
+                rows={4}
+                className="w-full bg-[#0f0f1e] border border-white/10 rounded-lg px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] transition-colors resize-none"
+              />
+            </div>
+
+            {/* Actions */}
+            <div className="flex gap-3 justify-end">
+              <button
+                onClick={() => {
+                  setShowReviewModal(false);
+                  setReviewRating(0);
+                  setReviewComment("");
+                  setHoverRating(0);
+                }}
+                className="px-5 py-2.5 rounded-full text-sm font-semibold bg-white/10 hover:bg-white/20 transition-colors"
+              >
+                Cancel
+              </button>
+              <button
+                onClick={handleSubmitReview}
+                disabled={reviewRating === 0}
+                className="px-5 py-2.5 rounded-full text-sm font-semibold bg-[#1db954] hover:bg-[#1ed760] text-black transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
+              >
+                Submit
+              </button>
+            </div>
+          </div>
+        </div>
+      )}
+    </div>
+  );
 };
 
Index: frontend/src/pages/UserDetail.tsx
===================================================================
--- frontend/src/pages/UserDetail.tsx	(revision 85512ff50bc46445db00d8c3ecea57616baddb36)
+++ frontend/src/pages/UserDetail.tsx	(revision ce45c7a7871379455b3a3c55a48f767ca2e0e739)
@@ -14,5 +14,4 @@
   Playlist,
 } from "../utils/types";
-import { useCreatedPlaylists } from "../context/playlistContext";
 
 interface FollowStatus {
@@ -38,6 +37,5 @@
   const { username: usernameParam } = useParams();
   const { user: currentUser } = useAuth();
-  const { createdPlaylists: currentUserCreatedPlaylists } =
-    useCreatedPlaylists();
+
   const navigate = useNavigate();
   const [user, setUser] = useState<UserProfile | null>(null);
