Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AuthController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AuthController.java	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AuthController.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,8 +1,7 @@
 package com.ukim.finki.develop.finkwave.controller;
 
+import java.io.IOException;
 import java.util.Map;
 
-import com.ukim.finki.develop.finkwave.config.AuthProperties;
-import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
@@ -10,7 +9,15 @@
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
+import com.ukim.finki.develop.finkwave.config.AuthProperties;
+import com.ukim.finki.develop.finkwave.exceptions.InvalidTokenException;
+import com.ukim.finki.develop.finkwave.exceptions.UnauthenticatedException;
 import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto;
 import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto;
@@ -31,16 +38,10 @@
     public ResponseEntity<Map<String, Object>> register(
             @ModelAttribute AuthRequestDto authRequestDto,
-            HttpServletResponse httpServletResponse){
-        try {
-            UserResponseDto userResponseDto = authService.registerAndLogIn(httpServletResponse, authRequestDto);
-            return ResponseEntity.ok(Map.of(
-                    "user", userResponseDto,
-                    "tokenExpiresIn", authProperties.getAccessTokenMaxAge()
-            ));
-        } catch (Exception e){
-            return ResponseEntity
-                    .status(HttpStatus.BAD_REQUEST)
-                    .body(Map.of("error", e.getMessage()));
-        }
+            HttpServletResponse httpServletResponse) throws IOException {
+        UserResponseDto userResponseDto = authService.registerAndLogIn(httpServletResponse, authRequestDto);
+        return ResponseEntity.ok(Map.of(
+                "user", userResponseDto,
+                "tokenExpiresIn", authProperties.getAccessTokenMaxAge()
+        ));
     }
 
@@ -48,26 +49,18 @@
     public ResponseEntity<Map<String, Object>> login(
             @RequestBody LoginRequestDto loginRequestDto,
-            HttpServletResponse httpServletResponse){
-        try {
-            UserResponseDto userResponseDto = authService.login(httpServletResponse, loginRequestDto);
-            return ResponseEntity.ok(Map.of(
-                    "user", userResponseDto,
-                    "tokenExpiresIn", authProperties.getAccessTokenMaxAge()
-                    )
-            );
-        } catch (Exception e){
-            return ResponseEntity
-                    .status(HttpStatus.BAD_REQUEST)
-                    .body(Map.of("error", e.getMessage()));
-        }
+            HttpServletResponse httpServletResponse) {
+        UserResponseDto userResponseDto = authService.login(httpServletResponse, loginRequestDto);
+        return ResponseEntity.ok(Map.of(
+                "user", userResponseDto,
+                "tokenExpiresIn", authProperties.getAccessTokenMaxAge()
+        ));
     }
-
 
     @PostMapping("/refresh")
     public ResponseEntity<Map<String, Integer>> refresh(
             HttpServletResponse httpServletResponse,
-            @CookieValue(name = "refreshToken", required = false) String refreshToken){
-        if (refreshToken == null){
-            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "No credentials");
+            @CookieValue(name = "refreshToken", required = false) String refreshToken) {
+        if (refreshToken == null) {
+            throw new InvalidTokenException("No refresh token provided.");
         }
         authService.refreshAccessTokenAndAddCookie(httpServletResponse, refreshToken);
@@ -80,5 +73,5 @@
     public ResponseEntity<Map<String, String>> logout(
             HttpServletResponse httpServletResponse,
-            @CookieValue(name = "refreshToken", required = false) String refreshToken){
+            @CookieValue(name = "refreshToken", required = false) String refreshToken) {
         authService.clearCookies(httpServletResponse, refreshToken);
         SecurityContextHolder.clearContext();
@@ -87,8 +80,8 @@
 
     @GetMapping("/user")
-    public ResponseEntity<Map<String, Object>> getUser(){
+    public ResponseEntity<Map<String, Object>> getUser() {
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-        if (authentication == null || !authentication.isAuthenticated()){
-            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Not authenticated");
+        if (authentication == null || !authentication.isAuthenticated()) {
+            throw new UnauthenticatedException();
         }
         Object principal = authentication.getPrincipal();
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,21 +1,61 @@
 package com.ukim.finki.develop.finkwave.controller;
 
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+import org.springframework.web.server.ResponseStatusException;
 
-import java.util.HashMap;
-import java.util.Map;
+import com.ukim.finki.develop.finkwave.exceptions.AuthException;
 
 @RestControllerAdvice
 public class GlobalExceptionHandler {
+    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
-    @ExceptionHandler(RuntimeException.class)
-    public ResponseEntity<Map<String, String>> handleRuntimeException(RuntimeException ex) {
-        Map<String, String> errorMap = new HashMap<>();
-        errorMap.put("error", ex.getMessage());
+    @ExceptionHandler(AuthException.class)
+    public ResponseEntity<Map<String, String>> handleAuthException(AuthException ex) {
+        return ResponseEntity
+                .status(ex.getStatus())
+                .body(Map.of("error", ex.getMessage()));
+    }
 
-        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorMap);
+    @ExceptionHandler(UsernameNotFoundException.class)
+    public ResponseEntity<Map<String, String>> handleUsernameNotFound(UsernameNotFoundException ex) {
+        return ResponseEntity
+                .status(HttpStatus.UNAUTHORIZED)
+                .body(Map.of("error", "Invalid credentials."));
+    }
+
+    @ExceptionHandler(ResponseStatusException.class)
+    public ResponseEntity<Map<String, String>> handleResponseStatusException(ResponseStatusException ex) {
+        logger.error("Response status error: {}", ex.getMessage());
+        return ResponseEntity
+                .status(ex.getStatusCode())
+                .body(Map.of("error", ex.getReason() != null ? ex.getReason() : "An error occurred."));
+    }
+
+    @ExceptionHandler(MaxUploadSizeExceededException.class)
+    public ResponseEntity<Map<String, Object>> handleMaxSize(MaxUploadSizeExceededException ex) {
+        logger.error("Max upload size error: {}", ex.getMessage());
+        return ResponseEntity
+                .status(HttpStatus.PAYLOAD_TOO_LARGE)
+                .body(Map.of(
+                        "error", "File too large.",
+                        "maxSize", "2MB"
+                ));
+    }
+
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<Map<String, String>> handleGenericException(Exception ex) {
+        logger.error("Unexpected error occurred: {}", ex.getMessage());
+        return ResponseEntity
+                .status(HttpStatus.INTERNAL_SERVER_ERROR)
+                .body(Map.of("error", "An unexpected error occurred."));
     }
 }
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AuthException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AuthException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AuthException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -0,0 +1,16 @@
+package com.ukim.finki.develop.finkwave.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public abstract class AuthException extends RuntimeException {
+    
+    public AuthException(String message) {
+        super(message);
+    }
+    
+    public AuthException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public abstract HttpStatus getStatus();
+}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidCredentialsException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidCredentialsException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidCredentialsException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -0,0 +1,19 @@
+package com.ukim.finki.develop.finkwave.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class InvalidCredentialsException extends AuthException {
+    
+    public InvalidCredentialsException() {
+        super("Invalid credentials.");
+    }
+    
+    public InvalidCredentialsException(String message) {
+        super(message);
+    }
+    
+    @Override
+    public HttpStatus getStatus() {
+        return HttpStatus.UNAUTHORIZED;
+    }
+}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidFileException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidFileException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidFileException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -0,0 +1,24 @@
+package com.ukim.finki.develop.finkwave.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class InvalidFileException extends AuthException {
+    
+    public InvalidFileException(String message) {
+        super(message);
+    }
+    
+    public static InvalidFileException invalidType() {
+        return new InvalidFileException("Invalid file type. Only images are allowed.");
+    }
+    
+    public static InvalidFileException tooLarge(long maxSizeBytes) {
+        long maxSizeMB = maxSizeBytes / 1_000_000;
+        return new InvalidFileException("File too large. Maximum size is " + maxSizeMB + "MB.");
+    }
+    
+    @Override
+    public HttpStatus getStatus() {
+        return HttpStatus.BAD_REQUEST;
+    }
+}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidTokenException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidTokenException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidTokenException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -0,0 +1,19 @@
+package com.ukim.finki.develop.finkwave.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class InvalidTokenException extends AuthException {
+    
+    public InvalidTokenException() {
+        super("Invalid or expired token.");
+    }
+    
+    public InvalidTokenException(String message) {
+        super(message);
+    }
+    
+    @Override
+    public HttpStatus getStatus() {
+        return HttpStatus.UNAUTHORIZED;
+    }
+}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UnauthenticatedException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UnauthenticatedException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UnauthenticatedException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -0,0 +1,19 @@
+package com.ukim.finki.develop.finkwave.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class UnauthenticatedException extends AuthException {
+    
+    public UnauthenticatedException() {
+        super("User not authenticated.");
+    }
+    
+    public UnauthenticatedException(String message) {
+        super(message);
+    }
+    
+    @Override
+    public HttpStatus getStatus() {
+        return HttpStatus.UNAUTHORIZED;
+    }
+}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserAlreadyExistsException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserAlreadyExistsException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserAlreadyExistsException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -0,0 +1,18 @@
+package com.ukim.finki.develop.finkwave.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class UserAlreadyExistsException extends AuthException {
+    
+    public UserAlreadyExistsException(String username) {
+        super("Username '" + username + "' is already taken.");
+    }
+    public UserAlreadyExistsException() {
+        super("Username is already taken.");
+    }
+    
+    @Override
+    public HttpStatus getStatus() {
+        return HttpStatus.CONFLICT;
+    }
+}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserNotFoundException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserNotFoundException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserNotFoundException.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -0,0 +1,19 @@
+package com.ukim.finki.develop.finkwave.exceptions;
+
+import org.springframework.http.HttpStatus;
+
+public class UserNotFoundException extends AuthException {
+    
+    public UserNotFoundException() {
+        super("User not found.");
+    }
+    
+    public UserNotFoundException(String message) {
+        super(message);
+    }
+    
+    @Override
+    public HttpStatus getStatus() {
+        return HttpStatus.NOT_FOUND;
+    }
+}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/RefreshToken.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/RefreshToken.java	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/RefreshToken.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -9,4 +9,5 @@
 @Entity
 @Getter @Setter
+@Table(name = "refresh_token")
 public class RefreshToken {
     @Id
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,3 +1,9 @@
 package com.ukim.finki.develop.finkwave.service;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.UUID;
 
 import org.springframework.security.core.Authentication;
@@ -5,13 +11,19 @@
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
 import com.ukim.finki.develop.finkwave.config.AuthProperties;
-import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.UserResponseDto;
+import com.ukim.finki.develop.finkwave.exceptions.InvalidCredentialsException;
+import com.ukim.finki.develop.finkwave.exceptions.InvalidFileException;
+import com.ukim.finki.develop.finkwave.exceptions.UnauthenticatedException;
+import com.ukim.finki.develop.finkwave.exceptions.UserAlreadyExistsException;
+import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException;
 import com.ukim.finki.develop.finkwave.model.NonAdminUser;
 import com.ukim.finki.develop.finkwave.model.RefreshToken;
 import com.ukim.finki.develop.finkwave.model.Role;
 import com.ukim.finki.develop.finkwave.model.User;
+import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto;
+import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto;
+import com.ukim.finki.develop.finkwave.model.dto.UserResponseDto;
 import com.ukim.finki.develop.finkwave.repository.NonAdminUserRepository;
 import com.ukim.finki.develop.finkwave.repository.UserRepository;
@@ -21,11 +33,4 @@
 import jakarta.transaction.Transactional;
 import lombok.RequiredArgsConstructor;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.UUID;
 
 @Service
@@ -39,4 +44,5 @@
     private final AuthProperties authProperties;
 
+    private static final long MAX_FILE_SIZE = 2_000_000;
 
     @Transactional
@@ -44,5 +50,5 @@
     throws IOException {
         if (userRepository.findByUsername(authRequestDto.username()).isPresent()){
-            throw new RuntimeException("User already exists");
+            throw new UserAlreadyExistsException();
         }
         User user = createNonAdminUser(authRequestDto);
@@ -52,8 +58,8 @@
     public UserResponseDto login(HttpServletResponse response, LoginRequestDto loginRequestDto){
         User user = userRepository.findByUsername(loginRequestDto.username())
-                .orElseThrow(() -> new RuntimeException("Invalid credentials"));
+                .orElseThrow(InvalidCredentialsException::new);
 
         if (!passwordEncoder.matches(loginRequestDto.password(), user.getPassword())){
-            throw new RuntimeException("Invalid credentials");
+            throw new InvalidCredentialsException();
         }
 
@@ -74,5 +80,5 @@
     public UserResponseDto getUserDtoByUsername(String username){
         User user = userRepository.findByUsername(username)
-                .orElseThrow(() -> new RuntimeException("Invalid credentials"));
+                .orElseThrow(UserNotFoundException::new);
 
         return userResponseFromUser(user);
@@ -103,12 +109,11 @@
         Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
         if (authentication == null || !authentication.isAuthenticated()) {
-            throw new RuntimeException("User not authenticated");
+            throw new UnauthenticatedException();
         }
 
         String username=authentication.getName();
 
-
         return userRepository.findByUsername(username).map(User::getId)
-                .orElseThrow(()->new RuntimeException("User not found"));
+                .orElseThrow(UserNotFoundException::new);
     }
 
@@ -124,10 +129,12 @@
 
         MultipartFile profilePhoto = authRequestDto.profilePhoto();
-        if (profilePhoto != null) {
-            if (profilePhoto.getContentType() != null && !profilePhoto.getContentType().startsWith("image/"))
-                throw new IllegalArgumentException("Invalid fyle type");
+        if (profilePhoto != null && !profilePhoto.isEmpty()) {
+            String contentType = profilePhoto.getContentType();
+            if (contentType == null || !contentType.startsWith("image/")) {
+                throw InvalidFileException.invalidType();
+            }
 
-            if (profilePhoto.getSize() > 5_000_000) {
-                throw new IllegalArgumentException(("File too large."));
+            if (profilePhoto.getSize() > MAX_FILE_SIZE) {
+                throw InvalidFileException.tooLarge(MAX_FILE_SIZE);
             }
 
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/RefreshTokenService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/RefreshTokenService.java	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/RefreshTokenService.java	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,10 +1,3 @@
 package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.config.AuthProperties;
-import com.ukim.finki.develop.finkwave.model.RefreshToken;
-import com.ukim.finki.develop.finkwave.model.User;
-import com.ukim.finki.develop.finkwave.repository.RefreshTokenRepository;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
 
 import java.time.Instant;
@@ -12,4 +5,14 @@
 import java.util.Optional;
 import java.util.UUID;
+
+import org.springframework.stereotype.Service;
+
+import com.ukim.finki.develop.finkwave.config.AuthProperties;
+import com.ukim.finki.develop.finkwave.exceptions.InvalidTokenException;
+import com.ukim.finki.develop.finkwave.model.RefreshToken;
+import com.ukim.finki.develop.finkwave.model.User;
+import com.ukim.finki.develop.finkwave.repository.RefreshTokenRepository;
+
+import lombok.RequiredArgsConstructor;
 
 @Service
@@ -32,7 +35,11 @@
 
     public RefreshToken validateRefreshToken(String token){
-        RefreshToken refreshToken = findByToken(token).orElseThrow(() -> new RuntimeException("Invalid token"));
-        if (refreshToken.isRevoked() || refreshToken.getExpiresAt().isBefore(Instant.now())){
-            throw new RuntimeException("Invalid refresh token");
+        RefreshToken refreshToken = findByToken(token)
+                .orElseThrow(() -> new InvalidTokenException("Invalid refresh token."));
+        if (refreshToken.isRevoked()){
+            throw new InvalidTokenException("Refresh token has been revoked.");
+        }
+        if (refreshToken.getExpiresAt().isBefore(Instant.now())){
+            throw new InvalidTokenException("Refresh token has expired.");
         }
         return refreshToken;
Index: frontend/package-lock.json
===================================================================
--- frontend/package-lock.json	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ frontend/package-lock.json	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -15,4 +15,5 @@
 				"react-dom": "^19.2.0",
 				"react-router-dom": "^7.13.0",
+				"react-toastify": "^11.0.5",
 				"tailwindcss": "^4.1.18"
 			},
@@ -2152,4 +2153,13 @@
 			"funding": {
 				"url": "https://github.com/chalk/chalk?sponsor=1"
+			}
+		},
+		"node_modules/clsx": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+			"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+			"license": "MIT",
+			"engines": {
+				"node": ">=6"
 			}
 		},
@@ -3683,4 +3693,17 @@
 			}
 		},
+		"node_modules/react-toastify": {
+			"version": "11.0.5",
+			"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz",
+			"integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==",
+			"license": "MIT",
+			"dependencies": {
+				"clsx": "^2.1.1"
+			},
+			"peerDependencies": {
+				"react": "^18 || ^19",
+				"react-dom": "^18 || ^19"
+			}
+		},
 		"node_modules/resolve-from": {
 			"version": "4.0.0",
Index: frontend/package.json
===================================================================
--- frontend/package.json	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ frontend/package.json	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -17,4 +17,5 @@
 		"react-dom": "^19.2.0",
 		"react-router-dom": "^7.13.0",
+		"react-toastify": "^11.0.5",
 		"tailwindcss": "^4.1.18"
 	},
Index: frontend/src/App.tsx
===================================================================
--- frontend/src/App.tsx	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ frontend/src/App.tsx	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,3 +1,5 @@
 import { createBrowserRouter, Outlet, RouterProvider } from "react-router-dom";
+import { ToastContainer } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
 import AllUsers from "./pages/AllUsers";
 import LandingPage from "./pages/LandingPage";
@@ -11,4 +13,16 @@
 		<div className="flex flex-col min-h-screen">
 			<Nav />
+			<ToastContainer
+				position="top-right"
+				autoClose={2000}
+				hideProgressBar={false}
+				newestOnTop={false}
+				closeOnClick
+				rtl={false}
+				pauseOnFocusLoss
+				draggable
+				pauseOnHover
+				theme="light"
+			/>
 			<main className="grow">
 				<Outlet />
Index: frontend/src/api/axiosInstance.ts
===================================================================
--- frontend/src/api/axiosInstance.ts	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ frontend/src/api/axiosInstance.ts	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -70,5 +70,7 @@
 			[401, 403].includes(error.response?.status) &&
 			!originalConfig._retry &&
-			originalConfig.url !== "/auth/refresh"
+			originalConfig.url !== "/auth/refresh" &&
+			originalConfig.url !== "/auth/login" &&
+			originalConfig.url !== "/auth/register"
 		) {
 			originalConfig._retry = true;
Index: frontend/src/pages/Login.tsx
===================================================================
--- frontend/src/pages/Login.tsx	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ frontend/src/pages/Login.tsx	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,4 +1,5 @@
 import { useState } from "react";
 import { useNavigate } from "react-router-dom";
+import { toast } from "react-toastify";
 import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
 import { useAuth } from "../context/authContext";
@@ -22,6 +23,10 @@
 			setUser(response.data.user);
 			navigate("/");
-		} catch (error) {
-			setError("Login failed. Please check your credentials.");
+			toast.success("Login successful!");
+		} catch (error: any) {
+			const errorMessage =
+				error.response?.data?.error ||
+				"Login failed. Please check your credentials.";
+			setError(`Login failed: ${errorMessage}`);
 		}
 	};
Index: frontend/src/pages/Nav.tsx
===================================================================
--- frontend/src/pages/Nav.tsx	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ frontend/src/pages/Nav.tsx	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,3 +1,4 @@
 import { Link } from "react-router-dom";
+import { toast } from "react-toastify";
 import axiosInstance, { baseURL } from "../api/axiosInstance";
 import Logo from "../assets/logo-finkwave.png";
@@ -12,6 +13,8 @@
 			await axiosInstance.post("/auth/logout");
 			setUser(undefined);
+			toast.success("Logout successful!");
 		} catch (error) {
 			console.error("Logout failed:", error);
+			toast.error("Logout failed!");
 		}
 	};
Index: frontend/src/pages/Register.tsx
===================================================================
--- frontend/src/pages/Register.tsx	(revision 77e572b1384712e7d7e1156b69cc0aa2ae48998f)
+++ frontend/src/pages/Register.tsx	(revision c1d2f0715ebdaf396e54dcc52c7463f8e0a280bd)
@@ -1,4 +1,5 @@
 import { useEffect, useState } from "react";
 import { useNavigate } from "react-router";
+import { toast } from "react-toastify";
 import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
 import { useAuth } from "../context/authContext";
@@ -15,4 +16,5 @@
 		null,
 	);
+	const [error, setError] = useState<string | null>(null);
 
 	const navigate = useNavigate();
@@ -26,9 +28,21 @@
 	}, [previewProfilePhoto]);
 
+	const handleRemoveFile = () => {
+		if (previewProfilePhoto) {
+			URL.revokeObjectURL(previewProfilePhoto);
+		}
+		setProfilePhotoFile(null);
+		setPreviewProfilePhoto(null);
+	};
+
 	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 (username === "" || password === "" || fullname === "" || email === "") {
+			setError("Please fill in all required fields.");
 			return;
 		}
@@ -53,6 +67,8 @@
 			setUser(response.data.user);
 			navigate("/");
-		} catch (error) {
-			console.error("Registration failed:", error);
+			toast.success("Registration successful!");
+		} catch (error: any) {
+			const errorMessage = error.response?.data?.error || "Please try again.";
+			setError(`Registration failed: ${errorMessage}`);
 		}
 	};
@@ -61,5 +77,6 @@
 		<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">
+			<form className="bg-white p-6 rounded shadow-md w-full max-w-md">
+				{error && <p className="text-red-500 mb-4">{error}</p>}
 				<div className="mb-4">
 					<label className="block text-gray-700 mb-2" htmlFor="username">
@@ -115,11 +132,20 @@
 						<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"
+							className="px-4 py-2 bg-blue-500 text-white rounded cursor-pointer hover:bg-blue-600 transition-colors text-sm font-medium text-center"
 						>
 							Choose File
 						</label>
-						<span className="text-gray-600 text-sm">
+						<span className="text-gray-600 text-sm flex-1">
 							{profilePhotoFile ? profilePhotoFile.name : "No file chosen"}
 						</span>
+						{profilePhotoFile && (
+							<button
+								type="button"
+								onClick={handleRemoveFile}
+								className="px-3 py-2 bg-red-500 text-white rounded hover:bg-red-600 transition-colors text-sm font-medium"
+							>
+								Remove
+							</button>
+						)}
 					</div>
 					<input
