Index: frontend/src/App.tsx
===================================================================
--- frontend/src/App.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ frontend/src/App.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -1,9 +1,9 @@
 import { createBrowserRouter, Outlet, RouterProvider } from "react-router-dom";
-import AllUsers from "./components/userProfile/AllUsersHelper";
-import UserDetail from "./components/userProfile/UserDetailView";
-import LandingPage from "./LandingPage";
-import Login from "./Login";
-import Nav from "./Nav";
-import Register from "./Register";
+import AllUsers from "./pages/AllUsers";
+import LandingPage from "./pages/LandingPage";
+import Login from "./pages/Login";
+import Nav from "./pages/Nav";
+import Register from "./pages/Register";
+import UserDetailView from "./pages/UserDetailView";
 
 const Layout = () => {
@@ -37,5 +37,5 @@
 			{
 				path: "/users/:userId",
-				element: <UserDetail />,
+				element: <UserDetailView />,
 			},
 			{
Index: frontend/src/LandingPage.tsx
===================================================================
--- frontend/src/LandingPage.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ 	(revision )
@@ -1,5 +1,0 @@
-const LandingPage = () => {
-	return <div>landing page</div>;
-};
-
-export default LandingPage;
Index: frontend/src/Login.tsx
===================================================================
--- frontend/src/Login.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ 	(revision )
@@ -1,71 +1,0 @@
-import { useState } from "react";
-import { useNavigate } from "react-router-dom";
-import axiosInstance, { scheduleTokenRefresh } from "./api/axiosInstance";
-import { useAuth } from "./context/authContext";
-import type { User } from "./types";
-
-const Login = () => {
-	const [username, setUsername] = useState("");
-	const [password, setPassword] = useState("");
-	const [error, setError] = useState<string | null>(null);
-	const { setUser } = useAuth();
-	const navigate = useNavigate();
-
-	const handleLogin = async (e: React.FormEvent) => {
-		e.preventDefault();
-		try {
-			const response = await axiosInstance.post<{
-				user: User;
-				tokenExpiresIn: number;
-			}>("/auth/login", { username, password });
-			scheduleTokenRefresh(response.data.tokenExpiresIn);
-			setUser(response.data.user);
-			navigate("/");
-		} catch (error) {
-			setError("Login failed. Please check your credentials.");
-		}
-	};
-	return (
-		<div className="flex flex-col items-center justify-center min-h-[90vh] bg-gray-100">
-			<h2 className="text-2xl mb-4">Login</h2>
-			<form
-				onSubmit={handleLogin}
-				className="bg-white p-6 rounded shadow-md w-80"
-			>
-				{error && <p className="text-red-500 mb-4">{error}</p>}
-				<div className="mb-4">
-					<label className="block text-gray-700 mb-2" htmlFor="username">
-						Username
-					</label>
-					<input
-						type="text"
-						id="username"
-						className="w-full p-2 border border-gray-300 rounded"
-						value={username}
-						onChange={(e) => setUsername(e.target.value)}
-					/>
-				</div>
-				<div className="mb-4">
-					<label className="block text-gray-700 mb-2" htmlFor="password">
-						Password
-					</label>
-					<input
-						type="password"
-						id="password"
-						className="w-full p-2 border border-gray-300 rounded"
-						value={password}
-						onChange={(e) => setPassword(e.target.value)}
-					/>
-				</div>
-				<button
-					type="submit"
-					className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors duration-200 w-full cursor-pointer"
-				>
-					Login
-				</button>
-			</form>
-		</div>
-	);
-};
-
-export default Login;
Index: frontend/src/Nav.tsx
===================================================================
--- frontend/src/Nav.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ 	(revision )
@@ -1,85 +1,0 @@
-import { Link } from "react-router-dom";
-import axiosInstance, { baseURL } from "./api/axiosInstance";
-import Logo from "./assets/logo-finkwave.png";
-import { useAuth } from "./context/authContext";
-
-const Nav = () => {
-	const { user, setUser, isAuthLoading } = useAuth();
-
-	const handleLogout = async (e: React.MouseEvent<HTMLButtonElement>) => {
-		e.preventDefault();
-		try {
-			await axiosInstance.post("/auth/logout");
-			setUser(undefined);
-		} catch (error) {
-			console.error("Logout failed:", error);
-		}
-	};
-
-	return (
-		<div className="bg-gray-800 p-4 flex justify-between items-center">
-			<Link to="/" className="text-white text-lg font-semibold">
-				<img src={Logo} alt="Finkwave Logo" className="h-12 w-auto" />
-			</Link>
-
-			<div className="flex items-center space-x-4">
-				{!isAuthLoading && (
-					<div className="flex items-center space-x-3">
-						{user ? (
-							<div className="flex items-center space-x-3">
-								<div className="flex items-center space-x-2 bg-slate-700 rounded-lg px-3 py-2">
-									{user.profilePhoto ? (
-										<img
-											src={`${baseURL}/${user.profilePhoto}`}
-											alt={`${user.username}'s profile`}
-											className="w-8 h-8 rounded-full object-cover"
-										/>
-									) : (
-										<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
-											<span className="text-white text-sm font-semibold">
-												{user.username.charAt(0).toUpperCase()}
-											</span>
-										</div>
-									)}
-
-									<div className="text-white">
-										<p className="text-sm font-medium">{user.username}</p>
-										<p className="text-xs text-gray-300 capitalize">
-											{user.role}
-										</p>
-									</div>
-								</div>
-								<button
-									onClick={handleLogout}
-									className="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg text-sm 
-                                    font-medium transition-colors duration-200 flex items-center space-x-1 cursor-pointer"
-								>
-									Logout
-								</button>
-							</div>
-						) : (
-							<div className="flex items-center space-x-4">
-								<Link
-									to="/login"
-									className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm 
-                                    font-medium transition-colors duration-200 cursor-pointer"
-								>
-									Login
-								</Link>
-								<Link
-									to="/register"
-									className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg text-sm
-                                    font-medium transition-colors duration-200 cursor-pointer"
-								>
-									Register
-								</Link>
-							</div>
-						)}
-					</div>
-				)}
-			</div>
-		</div>
-	);
-};
-
-export default Nav;
Index: frontend/src/Register.tsx
===================================================================
--- frontend/src/Register.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ 	(revision )
@@ -1,160 +1,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router";
-import axiosInstance, { scheduleTokenRefresh } from "./api/axiosInstance";
-import { useAuth } from "./context/authContext";
-import type { User } from "./types";
-
-const Register = () => {
-	const { setUser } = useAuth();
-	const [username, setUsername] = useState("");
-	const [password, setPassword] = useState("");
-	const [fullname, setFullname] = useState("");
-	const [email, setEmail] = useState("");
-	const [profilePhotoFile, setProfilePhotoFile] = useState<File | null>(null);
-	const [previewProfilePhoto, setPreviewProfilePhoto] = useState<string | null>(
-		null,
-	);
-
-	const navigate = useNavigate();
-
-	useEffect(() => {
-		return () => {
-			if (previewProfilePhoto) {
-				URL.revokeObjectURL(previewProfilePhoto);
-			}
-		};
-	}, [previewProfilePhoto]);
-
-	const handleRegister = async (e: React.FormEvent) => {
-		e.preventDefault();
-		// todo: add proper error handling
-		if (profilePhotoFile && profilePhotoFile.size > 5 * 1024 * 1024) {
-			alert("Max file size is 5MB");
-			return;
-		}
-
-		if (profilePhotoFile && !profilePhotoFile.type.startsWith("image/")) {
-			alert("Only images allowed");
-			return;
-		}
-		const formData = new FormData();
-		if (profilePhotoFile) formData.append("profilePhoto", profilePhotoFile);
-		formData.append("username", username);
-		formData.append("fullname", fullname);
-		formData.append("email", email);
-		formData.append("password", password);
-
-		try {
-			const response = await axiosInstance.post<{
-				user: User;
-				tokenExpiresIn: number;
-			}>("/auth/register", formData);
-			scheduleTokenRefresh(response.data.tokenExpiresIn);
-			setUser(response.data.user);
-			navigate("/");
-		} catch (error) {
-			console.error("Registration failed:", error);
-		}
-	};
-
-	return (
-		<div className="flex flex-col items-center justify-center min-h-[90vh] bg-gray-100">
-			<h2 className="text-2xl mb-4">Register</h2>
-			<form className="bg-white p-6 rounded shadow-md w-80">
-				<div className="mb-4">
-					<label className="block text-gray-700 mb-2" htmlFor="username">
-						Username
-					</label>
-					<input
-						type="text"
-						id="username"
-						className="w-full p-2 border border-gray-300 rounded"
-						value={username}
-						onChange={(e) => setUsername(e.target.value)}
-					/>
-				</div>
-				<div className="mb-4">
-					<label className="block text-gray-700 mb-2" htmlFor="password">
-						Password
-					</label>
-					<input
-						type="password"
-						id="password"
-						className="w-full p-2 border border-gray-300 rounded"
-						value={password}
-						onChange={(e) => setPassword(e.target.value)}
-					/>
-				</div>
-				<div className="mb-4">
-					<label className="block text-gray-700 mb-2" htmlFor="fullName">
-						Full Name
-					</label>
-					<input
-						type="text"
-						id="fullName"
-						className="w-full p-2 border border-gray-300 rounded"
-						value={fullname}
-						onChange={(e) => setFullname(e.target.value)}
-					/>
-				</div>
-				<div className="mb-4">
-					<label className="block text-gray-700 mb-2" htmlFor="email">
-						Email
-					</label>
-					<input
-						type="email"
-						id="email"
-						className="w-full p-2 border border-gray-300 rounded"
-						value={email}
-						onChange={(e) => setEmail(e.target.value)}
-					/>
-				</div>
-				<div className="mb-4">
-					<label className="block text-gray-700 mb-2">Profile Photo</label>
-					<div className="flex items-center gap-3">
-						<label
-							htmlFor="profilePhoto"
-							className="px-4 py-2 bg-blue-500 text-white rounded cursor-pointer hover:bg-blue-600 transition-colors text-sm font-medium"
-						>
-							Choose File
-						</label>
-						<span className="text-gray-600 text-sm">
-							{profilePhotoFile ? profilePhotoFile.name : "No file chosen"}
-						</span>
-					</div>
-					<input
-						type="file"
-						accept="image/*"
-						id="profilePhoto"
-						className="hidden"
-						onChange={(e) => {
-							if (e.target.files && e.target.files[0]) {
-								setProfilePhotoFile(e.target.files[0]);
-								setPreviewProfilePhoto(URL.createObjectURL(e.target.files[0]));
-							}
-						}}
-					/>
-				</div>
-				{previewProfilePhoto && (
-					<div className="mb-4">
-						<p className="block text-gray-700 mb-2">Profile Photo Preview:</p>
-						<img
-							src={previewProfilePhoto}
-							alt="Profile Preview"
-							className="w-20 h-20 object-cover rounded-full"
-						/>
-					</div>
-				)}
-				<button
-					type="submit"
-					className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 cursor-pointer"
-					onClick={handleRegister}
-				>
-					Register
-				</button>
-			</form>
-		</div>
-	);
-};
-
-export default Register;
Index: frontend/src/components/userProfile/AllUsersHelper.tsx
===================================================================
--- frontend/src/components/userProfile/AllUsersHelper.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ 	(revision )
@@ -1,87 +1,0 @@
-import React, { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import axiosInstance from "../../api/axiosInstance";
-interface User {
-  id: number;
-  username: string;
-  fullName: string;
-}
-
-const AllUsers = () => {
-  const [users, setUsers] = useState<User[]>([]);
-  const [searchedUser, setSearchedUser] = useState<string>("");
-  const [error, setError] = useState<string | null>(null);
-  const navigate = useNavigate();
-
-  useEffect(() => {
-    const fetchUsers = async () => {
-      const response = axiosInstance.get("/users/all");
-      setUsers((await response).data);
-    };
-    fetchUsers();
-  }, []);
-
-  const handleUserClick = (userId: number) => {
-    navigate(`/users/${userId}`);
-  };
-
-  const handleSearch = async (e: React.FormEvent) => {
-    e.preventDefault();
-    try {
-      const response = await axiosInstance.get(`/users/search`, {
-        params: { name: searchedUser },
-      });
-      setUsers(response.data);
-    } catch (err: any) {
-      const errorMessage = err.response?.data?.error || "Search failed";
-      setError(errorMessage);
-    }
-  };
-
-  if (users.length == 0) return <div className="p-6">Loading...</div>;
-  if (error) {
-    return (
-      <div className="p-6 bg-red-50 border border-red-200 text-red-700 rounded-lg">
-        <h2 className="font-bold">Error</h2>
-        <p>{error}</p>
-      </div>
-    );
-  }
-
-  return (
-    <div className="container mx-auto p-6">
-      <h1 className="text-3xl font-bold mb-6">All Users</h1>
-      <form onSubmit={handleSearch} className="flex gap-2 mb-10">
-        <input
-          type="text"
-          value={searchedUser}
-          onChange={(e) => setSearchedUser(e.target.value)}
-          className="border p-2 rounded w-full"
-          placeholder="Search for a user..."
-        />
-        <button
-          type="submit"
-          className="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700 transition-colors"
-        >
-          Search
-        </button>
-      </form>
-
-      <div className="grid gap-4">
-        {users.map((u) => (
-          <div
-            key={u.id}
-            onClick={() => handleUserClick(u.id)}
-            className="bg-white shadow-md rounded-lg p-4 hover:shadow-lg hover:bg-gray-50 cursor-pointer transition-all"
-          >
-            <h2 className="text-xl font-semibold">{u.fullName}</h2>
-            <p className="text-gray-600">@{u.username}</p>
-            <p className="text-gray-600">{u.id}</p>
-          </div>
-        ))}
-      </div>
-    </div>
-  );
-};
-
-export default AllUsers;
Index: frontend/src/components/userProfile/UserDetailView.tsx
===================================================================
--- frontend/src/components/userProfile/UserDetailView.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ 	(revision )
@@ -1,119 +1,0 @@
-import { useEffect, useState } from "react";
-import { useParams, useNavigate } from "react-router-dom";
-import ArtistView from "./ArtistView";
-import ListenerView from "./ListenerView";
-import axiosInstance from "../../api/axiosInstance";
-import type { ArtistContributionDTO } from "../../types";
-import type { MusicalEntityDTO } from "../../types";
-import type { Playlist } from "../../types";
-
-interface User {
-  id: number;
-  username: string;
-  fullName: string;
-  userType: string;
-  followers: number;
-  following: number;
-  isFollowedByCurrentUser: boolean;
-
-  musicalEntities?: {
-    contributions: ArtistContributionDTO[];
-  };
-
-  likes?: {
-    likedEntities: MusicalEntityDTO[];
-  };
-
-  createdPlaylists?: Playlist[];
-}
-
-const UserDetail = () => {
-  // user refers to the selected user NOT to the user from context
-  const { userId } = useParams();
-  const navigate = useNavigate();
-  const [user, setUser] = useState<User | null>(null);
-  const [error, setError] = useState<string | null>(null);
-
-  useEffect(() => {
-    const fetchUser = async () => {
-      setError(null);
-      try {
-        const response = await axiosInstance.get(`/users/${userId}`);
-
-        setUser(response.data);
-      } catch (err: any) {
-        const errorMessage =
-          err.response?.data?.error || "Failed to fetch user";
-        setError(errorMessage);
-      }
-    };
-    fetchUser();
-  }, [userId]);
-
-  if (error) {
-    return (
-      <div className="p-6 bg-red-50 border border-red-200 text-red-700 rounded-lg">
-        <h2 className="font-bold">Error</h2>
-        <p>{error}</p>
-      </div>
-    );
-  }
-
-  if (!user) return <div className="p-6">Loading...</div>;
-
-  return (
-    <div className="container mx-auto p-6">
-      <button
-        onClick={() => navigate(-1)}
-        className="mb-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
-      >
-        ← Back
-      </button>
-
-      <div className="bg-white shadow-lg rounded-lg p-8">
-        <div className="flex items-start gap-6 mb-8">
-          <div className="shrink-0">
-            <div className="w-32 h-32 rounded-full bg-linear-to-br from-blue-400 to-purple-500 flex items-center justify-center text-white text-4xl font-bold shadow-lg">
-              {user.fullName.charAt(0).toUpperCase()}
-            </div>
-          </div>
-
-          <div className="flex-1">
-            <h1 className="text-4xl font-bold mb-2">{user.fullName}</h1>
-            <span className="inline-block px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm font-medium mb-4">
-              {user.userType}
-            </span>
-
-            <div className="flex gap-6 mb-4 text-gray-700">
-              <div className="flex flex-col">
-                <span className="text-2xl font-bold">{user.followers}</span>
-                <span className="text-sm text-gray-500">Followers</span>
-              </div>
-              <div className="flex flex-col">
-                <span className="text-2xl font-bold">{user.following}</span>
-                <span className="text-sm text-gray-500">Following</span>
-              </div>
-            </div>
-
-            <button className="px-6 py-2 bg-blue-500 hover:bg-blue-600 text-white font-semibold rounded-lg shadow-md transition-colors duration-200 cursor-pointer">
-              {user.isFollowedByCurrentUser ? "Unfollow" : "Follow"}
-            </button>
-          </div>
-        </div>
-
-        {user.userType === "ARTIST" && user.musicalEntities?.contributions && (
-          <ArtistView contributions={user.musicalEntities.contributions} />
-        )}
-
-        {user.userType === "LISTENER" && user.likes?.likedEntities && (
-          <ListenerView
-            likedEntities={user.likes.likedEntities}
-            playlists={user.createdPlaylists}
-          />
-        )}
-      </div>
-    </div>
-  );
-};
-
-export default UserDetail;
Index: frontend/src/context/authContext.tsx
===================================================================
--- frontend/src/context/authContext.tsx	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ frontend/src/context/authContext.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -12,5 +12,5 @@
 	scheduleTokenRefresh,
 } from "../api/axiosInstance";
-import { type User } from "../types";
+import { type User } from "../utils/types";
 
 interface AuthContextType {
Index: frontend/src/pages/AllUsers.tsx
===================================================================
--- frontend/src/pages/AllUsers.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
+++ frontend/src/pages/AllUsers.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -0,0 +1,88 @@
+import React, { useEffect, useState } from "react";
+import { useNavigate } from "react-router-dom";
+import axiosInstance from "../api/axiosInstance";
+
+interface User {
+	id: number;
+	username: string;
+	fullName: string;
+}
+
+const AllUsers = () => {
+	const [users, setUsers] = useState<User[]>([]);
+	const [searchedUser, setSearchedUser] = useState<string>("");
+	const [error, setError] = useState<string | null>(null);
+	const navigate = useNavigate();
+
+	useEffect(() => {
+		const fetchUsers = async () => {
+			const response = axiosInstance.get("/users/all");
+			setUsers((await response).data);
+		};
+		fetchUsers();
+	}, []);
+
+	const handleUserClick = (userId: number) => {
+		navigate(`/users/${userId}`);
+	};
+
+	const handleSearch = async (e: React.FormEvent) => {
+		e.preventDefault();
+		try {
+			const response = await axiosInstance.get(`/users/search`, {
+				params: { name: searchedUser },
+			});
+			setUsers(response.data);
+		} catch (err: any) {
+			const errorMessage = err.response?.data?.error || "Search failed";
+			setError(errorMessage);
+		}
+	};
+
+	if (users.length == 0) return <div className="p-6">Loading...</div>;
+	if (error) {
+		return (
+			<div className="p-6 bg-red-50 border border-red-200 text-red-700 rounded-lg">
+				<h2 className="font-bold">Error</h2>
+				<p>{error}</p>
+			</div>
+		);
+	}
+
+	return (
+		<div className="container mx-auto p-6">
+			<h1 className="text-3xl font-bold mb-6">All Users</h1>
+			<form onSubmit={handleSearch} className="flex gap-2 mb-10">
+				<input
+					type="text"
+					value={searchedUser}
+					onChange={(e) => setSearchedUser(e.target.value)}
+					className="border p-2 rounded w-full"
+					placeholder="Search for a user..."
+				/>
+				<button
+					type="submit"
+					className="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700 transition-colors"
+				>
+					Search
+				</button>
+			</form>
+
+			<div className="grid gap-4">
+				{users.map((u) => (
+					<div
+						key={u.id}
+						onClick={() => handleUserClick(u.id)}
+						className="bg-white shadow-md rounded-lg p-4 hover:shadow-lg hover:bg-gray-50 cursor-pointer transition-all"
+					>
+						<h2 className="text-xl font-semibold">{u.fullName}</h2>
+						<p className="text-gray-600">@{u.username}</p>
+						<p className="text-gray-600">{u.id}</p>
+					</div>
+				))}
+			</div>
+		</div>
+	);
+};
+
+export default AllUsers;
Index: frontend/src/pages/LandingPage.tsx
===================================================================
--- frontend/src/pages/LandingPage.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
+++ frontend/src/pages/LandingPage.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -0,0 +1,5 @@
+const LandingPage = () => {
+	return <div>landing page</div>;
+};
+
+export default LandingPage;
Index: frontend/src/pages/Login.tsx
===================================================================
--- frontend/src/pages/Login.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
+++ frontend/src/pages/Login.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -0,0 +1,71 @@
+import { useState } from "react";
+import { useNavigate } from "react-router-dom";
+import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
+import { useAuth } from "../context/authContext";
+import type { User } from "../utils/types";
+
+const Login = () => {
+	const [username, setUsername] = useState("");
+	const [password, setPassword] = useState("");
+	const [error, setError] = useState<string | null>(null);
+	const { setUser } = useAuth();
+	const navigate = useNavigate();
+
+	const handleLogin = async (e: React.FormEvent) => {
+		e.preventDefault();
+		try {
+			const response = await axiosInstance.post<{
+				user: User;
+				tokenExpiresIn: number;
+			}>("/auth/login", { username, password });
+			scheduleTokenRefresh(response.data.tokenExpiresIn);
+			setUser(response.data.user);
+			navigate("/");
+		} catch (error) {
+			setError("Login failed. Please check your credentials.");
+		}
+	};
+	return (
+		<div className="flex flex-col items-center justify-center min-h-[90vh] bg-gray-100">
+			<h2 className="text-2xl mb-4">Login</h2>
+			<form
+				onSubmit={handleLogin}
+				className="bg-white p-6 rounded shadow-md w-80"
+			>
+				{error && <p className="text-red-500 mb-4">{error}</p>}
+				<div className="mb-4">
+					<label className="block text-gray-700 mb-2" htmlFor="username">
+						Username
+					</label>
+					<input
+						type="text"
+						id="username"
+						className="w-full p-2 border border-gray-300 rounded"
+						value={username}
+						onChange={(e) => setUsername(e.target.value)}
+					/>
+				</div>
+				<div className="mb-4">
+					<label className="block text-gray-700 mb-2" htmlFor="password">
+						Password
+					</label>
+					<input
+						type="password"
+						id="password"
+						className="w-full p-2 border border-gray-300 rounded"
+						value={password}
+						onChange={(e) => setPassword(e.target.value)}
+					/>
+				</div>
+				<button
+					type="submit"
+					className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors duration-200 w-full cursor-pointer"
+				>
+					Login
+				</button>
+			</form>
+		</div>
+	);
+};
+
+export default Login;
Index: frontend/src/pages/Nav.tsx
===================================================================
--- frontend/src/pages/Nav.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
+++ frontend/src/pages/Nav.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -0,0 +1,85 @@
+import { Link } from "react-router-dom";
+import axiosInstance, { baseURL } from "../api/axiosInstance";
+import Logo from "../assets/logo-finkwave.png";
+import { useAuth } from "../context/authContext";
+
+const Nav = () => {
+	const { user, setUser, isAuthLoading } = useAuth();
+
+	const handleLogout = async (e: React.MouseEvent<HTMLButtonElement>) => {
+		e.preventDefault();
+		try {
+			await axiosInstance.post("/auth/logout");
+			setUser(undefined);
+		} catch (error) {
+			console.error("Logout failed:", error);
+		}
+	};
+
+	return (
+		<div className="bg-gray-800 p-4 flex justify-between items-center">
+			<Link to="/" className="text-white text-lg font-semibold">
+				<img src={Logo} alt="Finkwave Logo" className="h-12 w-auto" />
+			</Link>
+
+			<div className="flex items-center space-x-4">
+				{!isAuthLoading && (
+					<div className="flex items-center space-x-3">
+						{user ? (
+							<div className="flex items-center space-x-3">
+								<div className="flex items-center space-x-2 bg-slate-700 rounded-lg px-3 py-2">
+									{user.profilePhoto ? (
+										<img
+											src={`${baseURL}/${user.profilePhoto}`}
+											alt={`${user.username}'s profile`}
+											className="w-8 h-8 rounded-full object-cover"
+										/>
+									) : (
+										<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center">
+											<span className="text-white text-sm font-semibold">
+												{user.username.charAt(0).toUpperCase()}
+											</span>
+										</div>
+									)}
+
+									<div className="text-white">
+										<p className="text-sm font-medium">{user.username}</p>
+										<p className="text-xs text-gray-300 capitalize">
+											{user.role}
+										</p>
+									</div>
+								</div>
+								<button
+									onClick={handleLogout}
+									className="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg text-sm 
+                                    font-medium transition-colors duration-200 flex items-center space-x-1 cursor-pointer"
+								>
+									Logout
+								</button>
+							</div>
+						) : (
+							<div className="flex items-center space-x-4">
+								<Link
+									to="/login"
+									className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm 
+                                    font-medium transition-colors duration-200 cursor-pointer"
+								>
+									Login
+								</Link>
+								<Link
+									to="/register"
+									className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg text-sm
+                                    font-medium transition-colors duration-200 cursor-pointer"
+								>
+									Register
+								</Link>
+							</div>
+						)}
+					</div>
+				)}
+			</div>
+		</div>
+	);
+};
+
+export default Nav;
Index: frontend/src/pages/Register.tsx
===================================================================
--- frontend/src/pages/Register.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
+++ frontend/src/pages/Register.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -0,0 +1,160 @@
+import { useEffect, useState } from "react";
+import { useNavigate } from "react-router";
+import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
+import { useAuth } from "../context/authContext";
+import type { User } from "../utils/types";
+
+const Register = () => {
+	const { setUser } = useAuth();
+	const [username, setUsername] = useState("");
+	const [password, setPassword] = useState("");
+	const [fullname, setFullname] = useState("");
+	const [email, setEmail] = useState("");
+	const [profilePhotoFile, setProfilePhotoFile] = useState<File | null>(null);
+	const [previewProfilePhoto, setPreviewProfilePhoto] = useState<string | null>(
+		null,
+	);
+
+	const navigate = useNavigate();
+
+	useEffect(() => {
+		return () => {
+			if (previewProfilePhoto) {
+				URL.revokeObjectURL(previewProfilePhoto);
+			}
+		};
+	}, [previewProfilePhoto]);
+
+	const handleRegister = async (e: React.FormEvent) => {
+		e.preventDefault();
+		// todo: add proper error handling
+		if (profilePhotoFile && profilePhotoFile.size > 5 * 1024 * 1024) {
+			alert("Max file size is 5MB");
+			return;
+		}
+
+		if (profilePhotoFile && !profilePhotoFile.type.startsWith("image/")) {
+			alert("Only images allowed");
+			return;
+		}
+		const formData = new FormData();
+		if (profilePhotoFile) formData.append("profilePhoto", profilePhotoFile);
+		formData.append("username", username);
+		formData.append("fullname", fullname);
+		formData.append("email", email);
+		formData.append("password", password);
+
+		try {
+			const response = await axiosInstance.post<{
+				user: User;
+				tokenExpiresIn: number;
+			}>("/auth/register", formData);
+			scheduleTokenRefresh(response.data.tokenExpiresIn);
+			setUser(response.data.user);
+			navigate("/");
+		} catch (error) {
+			console.error("Registration failed:", error);
+		}
+	};
+
+	return (
+		<div className="flex flex-col items-center justify-center min-h-[90vh] bg-gray-100">
+			<h2 className="text-2xl mb-4">Register</h2>
+			<form className="bg-white p-6 rounded shadow-md w-80">
+				<div className="mb-4">
+					<label className="block text-gray-700 mb-2" htmlFor="username">
+						Username
+					</label>
+					<input
+						type="text"
+						id="username"
+						className="w-full p-2 border border-gray-300 rounded"
+						value={username}
+						onChange={(e) => setUsername(e.target.value)}
+					/>
+				</div>
+				<div className="mb-4">
+					<label className="block text-gray-700 mb-2" htmlFor="password">
+						Password
+					</label>
+					<input
+						type="password"
+						id="password"
+						className="w-full p-2 border border-gray-300 rounded"
+						value={password}
+						onChange={(e) => setPassword(e.target.value)}
+					/>
+				</div>
+				<div className="mb-4">
+					<label className="block text-gray-700 mb-2" htmlFor="fullName">
+						Full Name
+					</label>
+					<input
+						type="text"
+						id="fullName"
+						className="w-full p-2 border border-gray-300 rounded"
+						value={fullname}
+						onChange={(e) => setFullname(e.target.value)}
+					/>
+				</div>
+				<div className="mb-4">
+					<label className="block text-gray-700 mb-2" htmlFor="email">
+						Email
+					</label>
+					<input
+						type="email"
+						id="email"
+						className="w-full p-2 border border-gray-300 rounded"
+						value={email}
+						onChange={(e) => setEmail(e.target.value)}
+					/>
+				</div>
+				<div className="mb-4">
+					<label className="block text-gray-700 mb-2">Profile Photo</label>
+					<div className="flex items-center gap-3">
+						<label
+							htmlFor="profilePhoto"
+							className="px-4 py-2 bg-blue-500 text-white rounded cursor-pointer hover:bg-blue-600 transition-colors text-sm font-medium"
+						>
+							Choose File
+						</label>
+						<span className="text-gray-600 text-sm">
+							{profilePhotoFile ? profilePhotoFile.name : "No file chosen"}
+						</span>
+					</div>
+					<input
+						type="file"
+						accept="image/*"
+						id="profilePhoto"
+						className="hidden"
+						onChange={(e) => {
+							if (e.target.files && e.target.files[0]) {
+								setProfilePhotoFile(e.target.files[0]);
+								setPreviewProfilePhoto(URL.createObjectURL(e.target.files[0]));
+							}
+						}}
+					/>
+				</div>
+				{previewProfilePhoto && (
+					<div className="mb-4">
+						<p className="block text-gray-700 mb-2">Profile Photo Preview:</p>
+						<img
+							src={previewProfilePhoto}
+							alt="Profile Preview"
+							className="w-20 h-20 object-cover rounded-full"
+						/>
+					</div>
+				)}
+				<button
+					type="submit"
+					className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 cursor-pointer"
+					onClick={handleRegister}
+				>
+					Register
+				</button>
+			</form>
+		</div>
+	);
+};
+
+export default Register;
Index: frontend/src/pages/UserDetailView.tsx
===================================================================
--- frontend/src/pages/UserDetailView.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
+++ frontend/src/pages/UserDetailView.tsx	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -0,0 +1,121 @@
+import { useEffect, useState } from "react";
+import { useNavigate, useParams } from "react-router-dom";
+import axiosInstance from "../api/axiosInstance";
+import ArtistView from "../components/userProfile/ArtistView";
+import ListenerView from "../components/userProfile/ListenerView";
+import type {
+	ArtistContributionDTO,
+	MusicalEntityDTO,
+	Playlist,
+} from "../utils/types";
+
+interface User {
+	id: number;
+	username: string;
+	fullName: string;
+	userType: string;
+	followers: number;
+	following: number;
+	isFollowedByCurrentUser: boolean;
+
+	musicalEntities?: {
+		contributions: ArtistContributionDTO[];
+	};
+
+	likes?: {
+		likedEntities: MusicalEntityDTO[];
+	};
+
+	createdPlaylists?: Playlist[];
+}
+
+const UserDetail = () => {
+	// user refers to the selected user NOT to the user from context
+	const { userId } = useParams();
+	const navigate = useNavigate();
+	const [user, setUser] = useState<User | null>(null);
+	const [error, setError] = useState<string | null>(null);
+
+	useEffect(() => {
+		const fetchUser = async () => {
+			setError(null);
+			try {
+				const response = await axiosInstance.get(`/users/${userId}`);
+
+				setUser(response.data);
+			} catch (err: any) {
+				const errorMessage =
+					err.response?.data?.error || "Failed to fetch user";
+				setError(errorMessage);
+			}
+		};
+		fetchUser();
+	}, [userId]);
+
+	if (error) {
+		return (
+			<div className="p-6 bg-red-50 border border-red-200 text-red-700 rounded-lg">
+				<h2 className="font-bold">Error</h2>
+				<p>{error}</p>
+			</div>
+		);
+	}
+
+	if (!user) return <div className="p-6">Loading...</div>;
+
+	return (
+		<div className="container mx-auto p-6">
+			<button
+				onClick={() => navigate(-1)}
+				className="mb-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
+			>
+				← Back
+			</button>
+
+			<div className="bg-white shadow-lg rounded-lg p-8">
+				<div className="flex items-start gap-6 mb-8">
+					<div className="shrink-0">
+						<div className="w-32 h-32 rounded-full bg-linear-to-br from-blue-400 to-purple-500 flex items-center justify-center text-white text-4xl font-bold shadow-lg">
+							{user.fullName.charAt(0).toUpperCase()}
+						</div>
+					</div>
+
+					<div className="flex-1">
+						<h1 className="text-4xl font-bold mb-2">{user.fullName}</h1>
+						<span className="inline-block px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm font-medium mb-4">
+							{user.userType}
+						</span>
+
+						<div className="flex gap-6 mb-4 text-gray-700">
+							<div className="flex flex-col">
+								<span className="text-2xl font-bold">{user.followers}</span>
+								<span className="text-sm text-gray-500">Followers</span>
+							</div>
+							<div className="flex flex-col">
+								<span className="text-2xl font-bold">{user.following}</span>
+								<span className="text-sm text-gray-500">Following</span>
+							</div>
+						</div>
+
+						<button className="px-6 py-2 bg-blue-500 hover:bg-blue-600 text-white font-semibold rounded-lg shadow-md transition-colors duration-200 cursor-pointer">
+							{user.isFollowedByCurrentUser ? "Unfollow" : "Follow"}
+						</button>
+					</div>
+				</div>
+
+				{user.userType === "ARTIST" && user.musicalEntities?.contributions && (
+					<ArtistView contributions={user.musicalEntities.contributions} />
+				)}
+
+				{user.userType === "LISTENER" && user.likes?.likedEntities && (
+					<ListenerView
+						likedEntities={user.likes.likedEntities}
+						playlists={user.createdPlaylists}
+					/>
+				)}
+			</div>
+		</div>
+	);
+};
+
+export default UserDetail;
Index: frontend/src/types.ts
===================================================================
--- frontend/src/types.ts	(revision 0f71490112c86ba2e2d18bbf12dac1b42e534433)
+++ 	(revision )
@@ -1,28 +1,0 @@
-export interface User {
-  username: string;
-  fullName: string;
-  email?: string;
-  profilePhoto?: string | null;
-  role?: "ADMIN" | "NONADMIN";
-}
-
-export interface ArtistContributionDTO {
-  musicalEntityId: number;
-  title: string;
-  genre: string;
-  role: string;
-  entityType: string;
-}
-export interface MusicalEntityDTO {
-  id: number;
-  title: string;
-  genre: string;
-  type: string;
-}
-
-export interface Playlist {
-  id: number;
-  name: string;
-  cover: string;
-  creatorName: string;
-}
Index: frontend/src/utils/types.ts
===================================================================
--- frontend/src/utils/types.ts	(revision 4e5cf92d976588170fa715007a49de90e673172a)
+++ frontend/src/utils/types.ts	(revision 4e5cf92d976588170fa715007a49de90e673172a)
@@ -0,0 +1,28 @@
+export interface User {
+	username: string;
+	fullName: string;
+	email?: string;
+	profilePhoto?: string | null;
+	role?: "ADMIN" | "NONADMIN";
+}
+
+export interface ArtistContributionDTO {
+	musicalEntityId: number;
+	title: string;
+	genre: string;
+	role: string;
+	entityType: string;
+}
+export interface MusicalEntityDTO {
+	id: number;
+	title: string;
+	genre: string;
+	type: string;
+}
+
+export interface Playlist {
+	id: number;
+	name: string;
+	cover: string;
+	creatorName: string;
+}
