Index: backend/backend/urls.py
===================================================================
--- backend/backend/urls.py	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ backend/backend/urls.py	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -17,5 +17,5 @@
 from django.contrib import admin
 from django.urls import path, include
-from subjects.views import index, all_subjects, get_suggestions, subject_view
+from subjects.views import index, all_subjects, get_suggestions
 
 urlpatterns = [
@@ -23,5 +23,5 @@
     path('subjects/', all_subjects),
     path('suggestion/', get_suggestions),
-    path('subjects/<str:code>/', subject_view),
+    # path('subjects/<str:code>/', subject_view),
     path('auth/', include('auth_form.urls')),
     path('', index),
Index: backend/subjects/utils.py
===================================================================
--- backend/subjects/utils.py	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ backend/subjects/utils.py	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -171,6 +171,7 @@
         filtered_subjects_vector[subject]['participant_score'] = values['participants']
     
-    for subject in eligible_subjects:
-        filtered_subjects_vector[subject]['tags'] /= max_tag_score
+    if max_tag_score != 0:
+        for subject in eligible_subjects:
+            filtered_subjects_vector[subject]['tags'] /= max_tag_score 
 
     return filtered_subjects_vector
Index: backend/subjects/views.py
===================================================================
--- backend/subjects/views.py	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ backend/subjects/views.py	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -17,9 +17,9 @@
 
 
-@api_view(['GET'])
-def subject_view(request, code):
-    subject = Subject.objects.get(code=code)
-    serializer = SubjectSerializer(subject)
-    return Response(serializer.data)
+# @api_view(['GET'])
+# def subject_view(request, code):
+#     subject = Subject.objects.get(code=code)
+#     serializer = SubjectSerializer(subject)
+#     return Response(serializer.data)
 
 @api_view(['GET'])
Index: frontend/src/components/StudentForm/StudentForm.tsx
===================================================================
--- frontend/src/components/StudentForm/StudentForm.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/components/StudentForm/StudentForm.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -1,3 +1,3 @@
-import { useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
 import {
 	EVALUATIONS,
@@ -20,9 +20,9 @@
 	validateForm,
 } from "./utils";
+import { useAuth } from "../../hooks/useAuth";
 
 interface StudentFormProps {
 	formData: StudentData | null;
 	isLoading: boolean;
-	setIsLoading?: (b: boolean) => void;
 }
 
@@ -87,5 +87,5 @@
 	const [showProfessors, setShowProfessors] = useState(false);
 	const [showAssistants, setShowAssistants] = useState(false);
-	const [subjects, setSubjects] = useSubjects();
+	const [subjects] = useSubjects();
 	const [distinctSubjectData, setDistinctSubjectData] =
 		useState<DistinctSubjectData>({
@@ -99,4 +99,5 @@
 	);
 	const [invalidSubjects, setInvalidSubjects] = useState<Subject[]>([]);
+	const { setFormData } = useAuth();
 
 	// Update form when formData changes (e.g., after fetching user data)
@@ -145,6 +146,6 @@
 	}, [formData]);
 
-	const setUniqueValues = (subJson: Subject[]) => {
-		const allProfessors: string[] = subJson
+	const setUniqueValues = useCallback((subjects: Subject[]) => {
+		const allProfessors: string[] = subjects
 			.flatMap((subject: Subject) => subject.subject_info.professors)
 			.filter((p): p is string => typeof p === "string");
@@ -154,5 +155,5 @@
 			.sort((a, b) => a.localeCompare(b));
 
-		const allAssistants: string[] = subJson
+		const allAssistants: string[] = subjects
 			.flatMap((subject: Subject) => subject.subject_info.assistants)
 			.filter((p): p is string => typeof p === "string");
@@ -163,9 +164,9 @@
 		setDistinctSubjectData(() => ({
 			tags: Array.from(
-				new Set(subJson.flatMap((subject) => subject.subject_info.tags))
+				new Set(subjects.flatMap((subject) => subject.subject_info.tags))
 			).sort((a, b) => a.localeCompare(b)),
 			technologies: Array.from(
 				new Set(
-					subJson
+					subjects
 						.flatMap((subject) => subject.subject_info.technologies)
 						.filter((tech) => tech != "any" && tech != "")
@@ -175,23 +176,11 @@
 			assistants: allAssistants_,
 		}));
-	};
+	}, []);
 
 	useEffect(() => {
-		const fetchSubjects = async () => {
-			try {
-				const resSubjects = await fetch("http://localhost:8000/subjects");
-				if (resSubjects.ok) {
-					const subJson: Subject[] = await resSubjects.json();
-					setSubjects(subJson || []);
-					setUniqueValues(subJson);
-				}
-			} catch (error) {
-				console.error("Error fetching subjects:", error);
-			}
-		};
-
-		if (subjects.length == 0) fetchSubjects();
-		else setUniqueValues(subjects);
-	}, []);
+    if (subjects && subjects.length > 0) {
+        setUniqueValues(subjects);
+    }
+}, [subjects, setUniqueValues]); 
 
 	const toggleSubject = (subject: Subject, semester: number) => {
@@ -283,9 +272,10 @@
 			// For updating existing form data use PATCH instead of PUT for partial updates
 			const method = formData?.has_filled_form ? "PATCH" : "POST";
-			await axiosAuth({
+			const response = await axiosAuth({
 				url: "/auth/form/",
 				method,
 				data: payload,
 			});
+			setFormData(response.data);
 			setHasSubmitted(true);
 			setFormStatus({
Index: frontend/src/components/SubjectCatalog/SubjectCatalog.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SubjectCatalog.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/components/SubjectCatalog/SubjectCatalog.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -14,5 +14,5 @@
 } from "./utils";
 const SubjectCatalog = () => {
-	const [subjects, setSubjects] = useSubjects();
+	const [subjects] = useSubjects();
 	const [visibleCourses, setVisibleCourses] = useState<number>(12);
 	const [searchTerm, setSearchTerm] = useState<string>("");
@@ -45,13 +45,8 @@
 
 	useEffect(() => {
-		const fetchData = async () => {
-			const response = await fetch("http://localhost:8000/subjects");
-			const data = await response.json();
-			setSubjects(data);
+		if (subjects && subjects.length > 0) {
 			setIsLoaded(true);
-		};
-		if (subjects.length == 0) fetchData();
-		else setIsLoaded(true);
-	}, []);
+		}
+	}, [subjects]);
 
 	useEffect(() => {
Index: frontend/src/context/AuthContext.tsx
===================================================================
--- frontend/src/context/AuthContext.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/context/AuthContext.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -1,11 +1,14 @@
 import { createContext } from 'react';
-
+import { StudentData } from '../components/types';
 export interface AuthContextType {
     accessToken: string | null;
     refreshToken: string | null;
+    formData: StudentData | null;
+    setFormData: (data: StudentData | null) => void;
     login: (accessToken: string, refreshToken: string) => void;
     logout: () => void;
     isAuthenticated: boolean;
     refreshAccessToken: () => Promise<string | null>;
+    loading: boolean;
 }
 
Index: frontend/src/context/AuthProvider.tsx
===================================================================
--- frontend/src/context/AuthProvider.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/context/AuthProvider.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -1,6 +1,16 @@
-import React, { useState, ReactNode } from "react";
+import React, { useRef, useState, useEffect, ReactNode, useCallback } from "react";
 import AuthContext, { AuthContextType } from "./AuthContext";
-import axiosInstance from "../api/axiosInstance";
+import axiosInstance from "../api/axiosInstance"; 
+import { jwtDecode } from "jwt-decode"
 import { toast } from "react-toastify";
+import { StudentData } from "../components/types";
+
+interface DecodedToken {
+    exp: number;
+    iat: number;
+    jti: string;
+    token_type: string;
+    user_id: number;
+}
 
 export const AuthProvider: React.FC<{ children: ReactNode }> = ({
@@ -13,9 +23,16 @@
     localStorage.getItem("refresh")
   );
-  const refreshAccessToken = async (): Promise<string | null> => {
-    const refreshToken = localStorage.getItem("refresh");
-    if (!refreshToken) {
+  const [formData, setFormData] = useState<StudentData | null>(null);
+  const [loading, setLoading] = useState(true); 
+
+  const proactiveRefreshTimeoutId = useRef<number | null>(null);
+  // We cannot use the useAxiosAuth hook here due to the circular dependency.
+  const axiosAuth = axiosInstance;
+
+  // Memoize the refresh function to stabilize dependencies in useEffect
+  const refreshAccessToken = useCallback(async (): Promise<string | null> => {
+    const currentRefreshToken = localStorage.getItem("refresh");
+    if (!currentRefreshToken) {
       logout();
-      toast.error("Session expired. Please log in again.");
       return null;
     }
@@ -23,7 +40,6 @@
       const response = await axiosInstance.post<{ access: string; refresh?: string }>(
         "/auth/refresh/",
-        { refresh: refreshToken }
+        { refresh: currentRefreshToken }
       );
-
       const newAccessToken = response.data.access;
       localStorage.setItem("access", newAccessToken);
@@ -31,40 +47,151 @@
 
       if (response.data.refresh) {
-        const newRefreshToken = response.data.refresh;
-        localStorage.setItem("refresh", newRefreshToken);
-        setRefreshToken(newRefreshToken);
+        localStorage.setItem("refresh", response.data.refresh);
+        setRefreshToken(response.data.refresh);
       }
-
+      scheduleProactiveRefresh(newAccessToken);
       return newAccessToken;
     } catch (error) {
       console.error("Error refreshing access token:", error);
       logout();
+      toast.error("Твојата сесија е истечена. Те молам најави се повторно.");
       return null;
     }
-  };
-
-  const login = (newAccessToken: string, newRefreshToken: string) => {
+  }, []); 
+
+  const logout = () => {
+    if (proactiveRefreshTimeoutId.current) {
+        clearTimeout(proactiveRefreshTimeoutId.current);
+    }
+    localStorage.removeItem("access");
+    localStorage.removeItem("refresh");
+    setAccessToken(null);
+    setRefreshToken(null);
+    setFormData(null);
+  };
+
+  const scheduleProactiveRefresh = (token: string) => {
+    if (proactiveRefreshTimeoutId.current) {
+        clearTimeout(proactiveRefreshTimeoutId.current);
+    }
+
+    try {
+        const decodedToken = jwtDecode<DecodedToken>(token);
+        const expirationTime = decodedToken.exp * 1000; 
+        const currentTime = Date.now();
+        
+        // Refresh X milliseconds before the token expires
+        const refreshOffset = 30 * 1000; 
+        
+        let timeoutDuration = expirationTime - currentTime - refreshOffset;
+
+        if (timeoutDuration < 0) {
+          // If the token is already about to expire, refresh immediately
+          timeoutDuration = 1000;
+        }
+
+        proactiveRefreshTimeoutId.current = setTimeout(() => {
+            refreshAccessToken();
+        }, timeoutDuration);
+
+    } catch (error) {
+        console.error("Failed to decode token for proactive refresh:", error);
+    }
+  };
+
+  useEffect(() => {
+    const requestIntercept = axiosAuth.interceptors.request.use(
+      (config) => {
+        if (!config.headers["Authorization"]) {
+          config.headers["Authorization"] = `Bearer ${accessToken}`;
+        }
+        return config;
+      },
+      (error) => Promise.reject(error)
+    );
+
+    const responseIntercept = axiosAuth.interceptors.response.use(
+      (response) => response,
+      async (error) => {
+        const prevRequest = error?.config;
+        if (error?.response?.status === 401 && !prevRequest?.sent) {
+          prevRequest.sent = true;
+          const newAccessToken = await refreshAccessToken();
+          if (newAccessToken) {
+            prevRequest.headers["Authorization"] = `Bearer ${newAccessToken}`;
+            return axiosAuth(prevRequest);
+          }
+        }
+        return Promise.reject(error);
+      }
+    );
+
+    return () => {
+      axiosAuth.interceptors.request.eject(requestIntercept);
+      axiosAuth.interceptors.response.eject(responseIntercept);
+    };
+  }, [accessToken, refreshAccessToken, axiosAuth]);
+
+
+  const fetchFormData = useCallback(async (tokenOverride?: string | null) => {
+    // Determine which token to use: the override from login, or the one from state (for refresh)
+    const tokenToUse = tokenOverride || accessToken;
+
+    if (!tokenToUse) {
+      console.log("Fetch aborted, no token available.");
+      return;
+    }
+    
+    try {
+      const response = await axiosAuth.get<StudentData>("/auth/form/", {
+        headers: {
+          Authorization: `Bearer ${tokenToUse}`
+        }
+      });
+      setFormData(response.data);
+    } catch (error) {
+      console.error("Could not fetch user form data", error);
+      toast.error("Не може да се вчитаат податоците.");
+    }
+  }, [axiosAuth, accessToken]); 
+
+  const login = async (newAccessToken: string, newRefreshToken: string) => {
     localStorage.setItem("access", newAccessToken);
     localStorage.setItem("refresh", newRefreshToken);
     setAccessToken(newAccessToken);
     setRefreshToken(newRefreshToken);
-  };
-
-  const logout = () => {
-    localStorage.removeItem("access");
-    localStorage.removeItem("refresh");
-    setAccessToken(null);
-    setRefreshToken(null);
-  };
-
-  const isAuthenticated = !!accessToken;
+    scheduleProactiveRefresh(newAccessToken);
+    await fetchFormData(newAccessToken);
+  };
+  
+  
+  useEffect(() => {
+    const token = localStorage.getItem("access");
+    if (token) {
+        scheduleProactiveRefresh(token);
+        fetchFormData(token);
+    }
+    setLoading(false);
+  }, []); 
+
+  useEffect(() => {
+    return () => {
+        if (proactiveRefreshTimeoutId.current) {
+            clearTimeout(proactiveRefreshTimeoutId.current);
+        }
+    }
+  }, []); 
+
 
   const contextValue: AuthContextType = {
     accessToken,
     refreshToken,
+    formData,
+    setFormData,
     login,
     logout,
-    isAuthenticated,
+    isAuthenticated: !!accessToken,
     refreshAccessToken,
+    loading,
   };
 
Index: frontend/src/context/SubjectsContext.tsx
===================================================================
--- frontend/src/context/SubjectsContext.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/context/SubjectsContext.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -6,4 +6,5 @@
 	useContext,
 	useState,
+	useEffect,
 } from "react";
 import { Subject } from "../components/types";
@@ -20,4 +21,20 @@
 	const [subjects, setSubjects] = useState<Subject[]>([]);
 
+	useEffect(() => {
+		const fetchSubjects = async () => {
+			try {
+				const resSubjects = await fetch("http://localhost:8000/subjects");
+				if (resSubjects.ok) {
+					const subJson: Subject[] = await resSubjects.json();
+					setSubjects(subJson || []);
+				}
+			} catch (error) {
+				console.error("Error fetching subjects:", error);
+			}
+		};
+
+		fetchSubjects();
+	}, []); 
+
 	return (
 		<SubjectsContext.Provider value={[subjects, setSubjects]}>
Index: frontend/src/pages/Account.tsx
===================================================================
--- frontend/src/pages/Account.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/pages/Account.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -1,35 +1,8 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import { toast } from "react-toastify";
 import StudentForm from "../components/StudentForm/StudentForm";
-import { StudentData } from "../components/types";
 import { useAuth } from "../hooks/useAuth";
-import useAxiosAuth from "../hooks/useAxiosAuth";
 
 const Account = () => {
-	const axiosAuth = useAxiosAuth();
-	const navigate = useNavigate();
-	const { logout } = useAuth();
-	const [formData, setFormData] = useState<StudentData | null>(null);
-	const [isLoading, setIsLoading] = useState(true);
-
-	useEffect(() => {
-		const fetchData = async () => {
-			try {
-				const resForm = await axiosAuth.get("/auth/form/");
-				setFormData(resForm.data);
-			} catch (error) {
-				console.error(error);
-				toast.error("Could not fetch form data after retries.");
-				logout();
-				navigate("/login");
-			} finally {
-				setIsLoading(false);
-			}
-		};
-
-		fetchData();
-	}, [axiosAuth, logout, navigate]);
-
+	const { formData } = useAuth();
+	const isLoading = formData === null;
 	return (
 		<div className="p-4 bg-white">
@@ -37,5 +10,4 @@
 				formData={formData}
 				isLoading={isLoading}
-				setIsLoading={setIsLoading}
 			/>
 		</div>
Index: frontend/src/pages/Recommendations.tsx
===================================================================
--- frontend/src/pages/Recommendations.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/pages/Recommendations.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -1,3 +1,3 @@
-import { useEffect, useMemo, useState } from "react";
+import { useMemo, useState } from "react";
 import { useNavigate } from "react-router-dom";
 import SubjectModal from "../components/SubjectCatalog/SubjectModal";
@@ -6,9 +6,12 @@
 import { useRecommendations } from "../context/RecommendationsContext";
 import useAxiosAuth from "../hooks/useAxiosAuth";
+import { useSubjects } from "../context/SubjectsContext";
+import { useAuth } from "../hooks/useAuth";
 
 const Recommendations = () => {
 	const axiosAuth = useAxiosAuth();
 	const navigate = useNavigate();
-	const [subjectData, setSubjectData] = useState<Subject[]>([]);
+	const { formData } = useAuth();
+	const [subjects] = useSubjects();
 	const [recommendations, setRecommendations] = useRecommendations();
 	const [season_, setSeason] = useState<"winter" | "summer" | "all">("all");
@@ -43,21 +46,24 @@
 	};
 
+	// Now we use the context to get the subjects, but we can also fetch them directly from the backend if needed!
 	// need to fetch subject data so that we can compare the subject IDs (prerequisites store IDs, but we need names)
 	// in the modals for the recommendations
-	useEffect(() => {
-		const fetchData = async () => {
-			const response = await axiosAuth.get("/subjects");
-			setSubjectData(response.data);
-		};
-		fetchData();
-	}, [axiosAuth]);
+	// useEffect(() => {
+	// 	const fetchData = async () => {
+	// 		const response = await fetch("http://localhost:8000/subjects");
+	// 		const data = await response.json();
+	// 		setSubjects(data);
+	// 	};
+	// 	fetchData();
+	// 	if (subjects.length == 0) fetchData();
+	// }, []);
 
 	const subjectIdToNameMap = useMemo(() => {
 		const map = new Map<number, string>();
-		subjectData.forEach((subject) => {
+		subjects.forEach((subject) => {
 			map.set(subject.id, subject.name);
 		});
 		return map;
-	}, [subjectData]);
+	}, [subjects]);
 
 	const cycleSeason = () => {
@@ -97,185 +103,197 @@
 
 	return (
-		<div className="flex h-[90vh] bg-gray-50">
-			{/* <div className="flex h-screen bg-gray-50"> */}
-			<div className="w-1/3 bg-white shadow-lg p-8 flex flex-col justify-center items-center space-y-8">
-				<div className="text-center">
-					<h1 className="text-4xl font-bold text-gray-800 mb-2">Препораки</h1>
-					<p className="text-gray-600 text-lg">
-						Предметите што ќе ги добиеш од алгоритамот се базирани на она што си
-						го пополнил во формата.
-						<br />
-						Тие се подредени според тоа колку твоите интереси се совпаѓаат со
-						она што го нудат предметите.
-					</p>
+		<>
+			{formData?.has_filled_form === false ? (
+				<div className="flex h-[90vh] bg-gray-50">
+					<div className="text-red-500 font-bold text-2xl text-center flex-1 flex items-center justify-center">
+						Пополни информации за твојот профил за да добиеш препораки!
+					</div>
 				</div>
-
-				<button onClick={cycleSeason}>
-					<div className="bg-blue-500 border border-blue-200 rounded-lg p-6 font-semibold text-white text-center hover:bg-blue-800 transition-colors duration-200">
-						<p className="text-white mb-3">
-							{season_ === "all" ? "Избрани семестри:" : "Избран семестар:"}
-						</p>
-						<p className="text-2xl">{getSeasonText()}</p>
+			) : (
+				<div className="flex h-[90vh] bg-gray-50">
+					{/* <div className="flex h-screen bg-gray-50"> */}
+					<div className="w-1/3 bg-white shadow-lg p-8 flex flex-col justify-center items-center space-y-8">
+						<div className="text-center">
+							<h1 className="text-4xl font-bold text-gray-800 mb-2">
+								Препораки
+							</h1>
+							<p className="text-gray-600 text-lg">
+								Предметите што ќе ги добиеш од алгоритамот се базирани на она
+								што си го пополнил во формата.
+								<br />
+								Тие се подредени според тоа колку твоите интереси се совпаѓаат
+								со она што го нудат предметите.
+							</p>
+						</div>
+
+						<button onClick={cycleSeason}>
+							<div className="bg-blue-500 border border-blue-200 rounded-lg p-6 font-semibold text-white text-center hover:bg-blue-800 transition-colors duration-200">
+								<p className="text-white mb-3">
+									{season_ === "all" ? "Избрани семестри:" : "Избран семестар:"}
+								</p>
+								<p className="text-2xl">{getSeasonText()}</p>
+							</div>
+						</button>
+
+						<button
+							onClick={fetchRecommendations}
+							disabled={isLoading}
+							className={`${
+								isLoading
+									? "bg-gray-400 cursor-not-allowed"
+									: "bg-green-500 hover:bg-green-600 hover:scale-105 shadow-md hover:shadow-lg"
+							} text-white px-8 py-4 rounded-lg text-xl font-bold transition-all duration-200 flex items-center space-x-2`}
+						>
+							{isLoading ? (
+								<>
+									<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
+									<span>Се вчитува...</span>
+								</>
+							) : (
+								<span>Вчитај препораки!</span>
+							)}
+						</button>
 					</div>
-				</button>
-
-				<button
-					onClick={fetchRecommendations}
-					disabled={isLoading}
-					className={`${
-						isLoading
-							? "bg-gray-400 cursor-not-allowed"
-							: "bg-green-500 hover:bg-green-600 hover:scale-105 shadow-md hover:shadow-lg"
-					} text-white px-8 py-4 rounded-lg text-xl font-bold transition-all duration-200 flex items-center space-x-2`}
-				>
-					{isLoading ? (
-						<>
-							<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
-							<span>Се вчитува...</span>
-						</>
-					) : (
-						<span>Вчитај препораки!</span>
-					)}
-				</button>
-			</div>
-
-			<div className="flex-1 p-8 overflow-y-auto">
-				{recommendations.length > 0 ? (
-					<div className="space-y-6">
-						<div className="text-center mb-8">
-							<h2 className="text-3xl font-bold text-gray-800 mb-2">
-								Вашите препораки за {getSeasonText().toLowerCase()}{" "}
-								{getSeasonText().toLowerCase() === "двата"
-									? "семестри"
-									: "семестар"}
-							</h2>
-							<div className="w-24 h-1 bg-blue-500 mx-auto rounded-full"></div>
-						</div>
-
-						<div
-							// className={`grid grid-cols-1 lg:grid-cols-2 gap-3 lg:h-[1150px]`}
-							className={`grid grid-cols-1 lg:grid-cols-2 gap-3 auto-rows-[300px] relative pb-4`}
-						>
-							{recommendations.map((subject, index) => (
+
+					<div className="flex-1 p-8 overflow-y-auto">
+						{recommendations.length > 0 ? (
+							<div className="space-y-6">
+								<div className="text-center mb-8">
+									<h2 className="text-3xl font-bold text-gray-800 mb-2">
+										Вашите препораки за {getSeasonText().toLowerCase()}{" "}
+										{getSeasonText().toLowerCase() === "двата"
+											? "семестри"
+											: "семестар"}
+									</h2>
+									<div className="w-24 h-1 bg-blue-500 mx-auto rounded-full"></div>
+								</div>
+
 								<div
-									key={subject.id}
-									className={`h-56 border border-gray-200 rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-shadow duration-200 relative ${
-										index % 2 === 0 ? "self-start" : "self-end"
-									}`}
-									style={{
-										animationName: "fadeInUp",
-										animationDuration: "0.6s",
-										animationTimingFunction: "ease-out",
-										animationFillMode: "forwards",
-										animationDelay: `${index * 100}ms`,
-									}}
+									// className={`grid grid-cols-1 lg:grid-cols-2 gap-3 lg:h-[1150px]`}
+									className={`grid grid-cols-1 lg:grid-cols-2 gap-3 auto-rows-[300px] relative pb-4`}
 								>
-									<div className="p-4 min-h-full flex flex-col gap-1">
-										<div className="flex justify-between items-start mb-2">
-											<div>
-												<h3 className="text-lg font-semibold">
-													{subject.name}
-												</h3>
-												<p className="text-gray-600">{subject.code}</p>
+									{recommendations.map((subject, index) => (
+										<div
+											key={subject.id}
+											className={`h-56 border border-gray-200 rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-shadow duration-200 relative ${
+												index % 2 === 0 ? "self-start" : "self-end"
+											}`}
+											style={{
+												animationName: "fadeInUp",
+												animationDuration: "0.6s",
+												animationTimingFunction: "ease-out",
+												animationFillMode: "forwards",
+												animationDelay: `${index * 100}ms`,
+											}}
+										>
+											<div className="p-4 min-h-full flex flex-col gap-1">
+												<div className="flex justify-between items-start mb-2">
+													<div>
+														<h3 className="text-lg font-semibold">
+															{subject.name}
+														</h3>
+														<p className="text-gray-600">{subject.code}</p>
+													</div>
+												</div>
+
+												<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
+													{subject.subject_info.activated === false ? (
+														<span className="bg-red-500 text-white font-bold px-3 py-1 rounded-full shadow-lg text-xs transition-opacity duration-300 z-10">
+															Никогаш не бил активиран!
+														</span>
+													) : index === 0 ? (
+														<span className="bg-blue-600 text-white font-bold px-3 py-1 rounded-full shadow-lg text-xs transition-opacity duration-300 z-10">
+															Најсоодветен!
+														</span>
+													) : null}
+												</div>
+
+												<div className="flex justify-between mt-auto gap-3">
+													<button
+														onClick={() => openSubjectDetails(subject)}
+														className="flex items-center text-sm text-gray-600 hover:text-gray-800 transition-colors"
+													>
+														<img
+															src="src/assets/eye.svg"
+															className="w-4 h-4 mr-1"
+														/>
+														Краток преглед
+													</button>
+													<button
+														onClick={() => openSubjectView(subject)}
+														className="flex items-center px-3 py-2 bg-blue-600 hover:bg-blue-900 text-white text-sm font-medium rounded-md transition-colors"
+													>
+														<svg
+															className="w-4 h-4 mr-1"
+															fill="none"
+															stroke="currentColor"
+															viewBox="0 0 24 24"
+														>
+															<path
+																strokeLinecap="round"
+																strokeLinejoin="round"
+																strokeWidth={2}
+																d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
+															/>
+														</svg>
+														Отвори предмет
+													</button>
+												</div>
 											</div>
 										</div>
-
-										<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
-											{subject.subject_info.activated === false ? (
-												<span className="bg-red-500 text-white font-bold px-3 py-1 rounded-full shadow-lg text-xs transition-opacity duration-300 z-10">
-													Никогаш не бил активиран!
-												</span>
-											) : index === 0 ? (
-												<span className="bg-blue-600 text-white font-bold px-3 py-1 rounded-full shadow-lg text-xs transition-opacity duration-300 z-10">
-													Најсоодветен!
-												</span>
-											) : null}
-										</div>
-
-										<div className="flex justify-between mt-auto gap-3">
-											<button
-												onClick={() => openSubjectDetails(subject)}
-												className="flex items-center text-sm text-gray-600 hover:text-gray-800 transition-colors"
-											>
-												<img
-													src="src/assets/eye.svg"
-													className="w-4 h-4 mr-1"
-												/>
-												Краток преглед
-											</button>
-											<button
-												onClick={() => openSubjectView(subject)}
-												className="flex items-center px-3 py-2 bg-blue-600 hover:bg-blue-900 text-white text-sm font-medium rounded-md transition-colors"
-											>
-												<svg
-													className="w-4 h-4 mr-1"
-													fill="none"
-													stroke="currentColor"
-													viewBox="0 0 24 24"
-												>
-													<path
-														strokeLinecap="round"
-														strokeLinejoin="round"
-														strokeWidth={2}
-														d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
-													/>
-												</svg>
-												Отвори предмет
-											</button>
-										</div>
-									</div>
+									))}
 								</div>
-							))}
-						</div>
-						{/* Fade gradient at bottom-right to signal scrollability */}
-						<div className="absolute bottom-0 right-0 h-24 w-full pointer-events-none bg-gradient-to-t from-gray-50 to-transparent" />
+								{/* Fade gradient at bottom-right to signal scrollability */}
+								<div className="absolute bottom-0 right-0 h-24 w-full pointer-events-none bg-gradient-to-t from-gray-50 to-transparent" />
+							</div>
+						) : !hasSearched ? (
+							<div className="flex flex-col items-center justify-center h-full text-center">
+								<div className="text-gray-400 mb-6">
+									<svg
+										className="w-16 h-16 mx-auto"
+										fill="none"
+										stroke="currentColor"
+										viewBox="0 0 24 24"
+									>
+										<path
+											strokeLinecap="round"
+											strokeLinejoin="round"
+											strokeWidth={1}
+											d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
+										/>
+									</svg>
+								</div>
+								<h3 className="text-2xl font-bold text-gray-600 mb-4">
+									Започнете со пребарување!
+								</h3>
+								<p className="text-gray-500 text-lg max-w-md">
+									Изберете ја саканата сезона и кликнете на "Вчитај препораки"
+									за да ги откриете вашите идеални предмети!
+								</p>
+							</div>
+						) : (
+							<div className="flex flex-col items-center justify-center h-full text-center">
+								<h3 className="text-2xl font-bold text-gray-600 mb-4">
+									Моментално немаме препораки за тебе :(
+								</h3>
+								<p className="text-gray-500 text-lg max-w-md">
+									Направи промени во профилот и обиди се повторно.
+								</p>
+							</div>
+						)}
 					</div>
-				) : !hasSearched ? (
-					<div className="flex flex-col items-center justify-center h-full text-center">
-						<div className="text-gray-400 mb-6">
-							<svg
-								className="w-16 h-16 mx-auto"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={1}
-									d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
-								/>
-							</svg>
-						</div>
-						<h3 className="text-2xl font-bold text-gray-600 mb-4">
-							Започнете со пребарување!
-						</h3>
-						<p className="text-gray-500 text-lg max-w-md">
-							Изберете ја саканата сезона и кликнете на "Вчитај препораки" за да
-							ги откриете вашите идеални предмети!
-						</p>
-					</div>
-				) : (
-					<div className="flex flex-col items-center justify-center h-full text-center">
-						<h3 className="text-2xl font-bold text-gray-600 mb-4">
-							Моментално немаме препораки за тебе :(
-						</h3>
-						<p className="text-gray-500 text-lg max-w-md">
-							Направи промени во профилот и обиди се повторно.
-						</p>
-					</div>
-				)}
-			</div>
-			{showModal && selectedSubject && (
-				<SubjectModal
-					selectedSubject={selectedSubject}
-					closeModal={closeModal}
-					subjectPrerequisites={getSubjectPrerequisites(
-						selectedSubject,
-						subjectIdToNameMap
+					{showModal && selectedSubject && (
+						<SubjectModal
+							selectedSubject={selectedSubject}
+							closeModal={closeModal}
+							subjectPrerequisites={getSubjectPrerequisites(
+								selectedSubject,
+								subjectIdToNameMap
+							)}
+						/>
 					)}
-				/>
+				</div>
 			)}
-		</div>
+		</>
 	);
 };
Index: frontend/src/pages/Register.tsx
===================================================================
--- frontend/src/pages/Register.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/pages/Register.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -4,4 +4,5 @@
 import PasswordInput from "../components/PasswordInput";
 import { useAuth } from "../hooks/useAuth";
+import { toast } from "react-toastify";
 
 interface RegisterForm {
@@ -56,4 +57,5 @@
 			const { access, refresh } = response.data;
 			login(access, refresh);
+			toast.success("Успешна регистрација!");
 			navigate("/account");
 		} catch (err: unknown) {
@@ -99,5 +101,5 @@
 				/>
 				{errors.email && (
-					<p className="text-red-500 text-sm mb-2">{errors.email[0]}</p>
+					<p className="text-red-500 text-sm mb-2">Постои user со овој mail.</p>
 				)}
 				<PasswordInput
@@ -106,5 +108,5 @@
 					onChange={handleChange}
 					placeholder="Лозинка"
-					error={errors.password ? errors.password[0] : undefined}
+					error={errors.password ? "Пасвордот е прелесен. Треба да содржи барем 8 карактери и еден специјален знак." : undefined}
 				/>
 				<PasswordInput
@@ -116,5 +118,5 @@
 				{errors.confirmPassword && (
 					<p className="text-red-500 text-sm mb-2">
-						{errors.confirmPassword[0]}
+						Лозинките не се совпаѓаат
 					</p>
 				)}
Index: frontend/src/pages/SubjectView.tsx
===================================================================
--- frontend/src/pages/SubjectView.tsx	(revision 3395d4ae63933a8d1623bfd8aeb1a055b9504f35)
+++ frontend/src/pages/SubjectView.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
@@ -1,66 +1,82 @@
 import { ArrowLeft, Tag, Users } from "lucide-react";
-import { useEffect, useState } from "react";
+import { useEffect, useState, useMemo } from "react"; 
 import { useLocation, useNavigate, useParams } from "react-router-dom";
 import { getSubjectPrerequisites } from "../components/SubjectCatalog/utils";
 import SkeletonSubjectView from "../components/SubjectView/SkeletonSubjectView";
-import { Subject } from "../components/types";
 import { EVALUATION_MAP_TO_MK } from "../constants/subjects";
+import { useSubjects } from "../context/SubjectsContext"; 
 
 function SubjectView() {
-	const [selectedSubject, setSelectedSubject] = useState<Subject>(
-		{} as Subject
-	);
-	const [subjectPrerequisites, setSubjectPrerequisites] = useState<
-		"Нема предуслов" | number | string
-	>("Нема предуслов");
-	const [isLoading, setIsLoading] = useState(true);
-	const [isExpanded, setIsExpanded] = useState(false);
-	const [filteredTechonologies, setFilteredTechnologies] = useState([]);
-	const { code } = useParams();
-	const navigate = useNavigate();
-	const location = useLocation();
-	const WORD_LIMIT = 40;
-
-	const from = location.state?.from || "/";
-
-	const truncateText = (text: string) => {
-		if (!text) return "";
-		const words = text.split(/\s+/);
-		return words.length <= WORD_LIMIT
-			? text
-			: words.slice(0, WORD_LIMIT).join(" ") + "...";
-	};
-
-	const canToggle =
-		selectedSubject.code &&
-		selectedSubject.abstract.split(/\s+/).length > WORD_LIMIT;
-	const abstractText = isExpanded
-		? selectedSubject.abstract
-		: truncateText(selectedSubject.abstract);
-
-	const handleGoBack = () => {
-		navigate(from);
-	};
-
-	useEffect(() => {
-		fetch(`http://localhost:8000/subjects/${code}/`)
-			.then((res) => res.json())
-			.then((data) => {
-				setSelectedSubject(data);
-				const technologies = data.subject_info.technologies.map(
-					(tech: string) => (tech === "any" ? "По избор" : tech)
-				);
-				const filtered = technologies.filter(
-					(tech: string) => tech !== "По избор"
-				);
-				if (technologies.includes("По избор")) {
-					filtered.push("По избор");
-				}
-				setFilteredTechnologies(filtered);
-				setSubjectPrerequisites(getSubjectPrerequisites(selectedSubject, data));
-				setIsLoading(false);
-			});
-	}, []);
-	if (isLoading) return <SkeletonSubjectView />;
+    const [subjectPrerequisites, setSubjectPrerequisites] = useState<
+        "Нема предуслов" | number | string
+    >("Нема предуслов");
+    const [isExpanded, setIsExpanded] = useState(false);
+    const [filteredTechonologies, setFilteredTechnologies] = useState<string[]>([]);
+    const { code } = useParams();
+    const navigate = useNavigate();
+    const location = useLocation();
+
+    const [subjects] = useSubjects();
+
+    // useMemo makes this efficient, so it only re-calculates when subjects or code changes.
+    const selectedSubject = useMemo(() => {
+        return subjects.find((subject) => subject.code === code);
+    }, [subjects, code]);
+
+    const WORD_LIMIT = 40;
+    const from = location.state?.from || "/";
+
+    const truncateText = (text: string) => {
+        if (!text) return "";
+        const words = text.split(/\s+/);
+        return words.length <= WORD_LIMIT
+            ? text
+            : words.slice(0, WORD_LIMIT).join(" ") + "...";
+    };
+
+    const abstractText = isExpanded
+        ? selectedSubject?.abstract
+        : truncateText(selectedSubject?.abstract ?? "");
+    
+    const canToggle =
+        selectedSubject &&
+        selectedSubject.abstract.split(/\s+/).length > WORD_LIMIT;
+
+    const handleGoBack = () => {
+        navigate(from);
+    };
+
+    useEffect(() => {
+        if (selectedSubject) {
+            const technologies = selectedSubject.subject_info.technologies.map(
+                (tech: string) => (tech === "any" ? "По избор" : tech)
+            );
+            const filtered = technologies.filter(
+                (tech: string) => tech !== "По избор"
+            );
+            if (technologies.includes("По избор")) {
+                filtered.push("По избор");
+            }
+            setFilteredTechnologies(filtered);
+            const subjectIdToNameMap = new Map(subjects.map(s => [s.id, s.name]));
+            setSubjectPrerequisites(
+                getSubjectPrerequisites(selectedSubject, subjectIdToNameMap)
+            );
+        }
+    }, [selectedSubject, subjects]); 
+
+    // We are "loading" if the global subjects context hasn't populated yet.
+    if (subjects.length === 0) {
+        return <SkeletonSubjectView />;
+    }
+
+    // Handle case where the subject code is not found in our global list
+    if (!selectedSubject) {
+        return (
+            <div className="flex items-center justify-center min-h-screen">
+                Предметот со код '{code}' не е пронајден.
+            </div>
+        );
+    }
 
 	return (
