Index: backend/auth_form/migrations/0017_student_favorite_subjects.py
===================================================================
--- backend/auth_form/migrations/0017_student_favorite_subjects.py	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
+++ backend/auth_form/migrations/0017_student_favorite_subjects.py	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -0,0 +1,19 @@
+# Generated by Django 5.1.7 on 2025-06-13 14:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('auth_form', '0016_student_assistants'),
+        ('subjects', '0002_subject_info_evaluation_subject_info_is_easy_and_more'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='student',
+            name='favorite_subjects',
+            field=models.ManyToManyField(blank=True, related_name='favorited_by_students', to='subjects.subject'),
+        ),
+    ]
Index: backend/auth_form/models.py
===================================================================
--- backend/auth_form/models.py	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
+++ backend/auth_form/models.py	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -68,5 +68,9 @@
     total_credits = models.PositiveIntegerField(null=True)
     level_credits = ArrayField(models.PositiveIntegerField(null=True), null=True, blank=True)
-    
+    favorite_subjects = models.ManyToManyField(
+        'subjects.subject', 
+        related_name="favorited_by_students", 
+        blank=True
+    )   
     # {1: [s1, s2, s3...], 2: [....], ...}
     passed_subjects_per_semester = models.JSONField(blank=True, null=True) 
@@ -76,8 +80,4 @@
         self.preferred_domains = new_preferences
         self.save()
-
-    def get_recommendations(self):
-        # Placeholder for recommendation logic
-        pass
 
     def get_user_info(self):
Index: backend/backend/urls.py
===================================================================
--- backend/backend/urls.py	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
+++ backend/backend/urls.py	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -17,5 +17,5 @@
 from django.contrib import admin
 from django.urls import path, include
-from subjects.views import index, all_subjects, get_suggestions
+from subjects.views import index, all_subjects, get_suggestions, ToggleFavoriteSubjectView, FavoriteSubjectsView
 
 urlpatterns = [
@@ -23,4 +23,6 @@
     path('subjects/', all_subjects),
     path('suggestion/', get_suggestions),
+    path('student/favorites/', FavoriteSubjectsView.as_view(), name='student-favorites'),
+    path('student/toggle-favorite/', ToggleFavoriteSubjectView.as_view(), name='student-toggle-favorite'),
     # path('subjects/<str:code>/', subject_view),
     path('auth/', include('auth_form.urls')),
Index: backend/subjects/views.py
===================================================================
--- backend/subjects/views.py	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
+++ backend/subjects/views.py	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -6,4 +6,6 @@
 from rest_framework.response import Response
 from rest_framework import status
+from rest_framework.views import APIView
+from rest_framework.permissions import IsAuthenticated
 from django.db.models import Case, When
 from auth_form.serializers import StudentFormSerializer
@@ -55,2 +57,49 @@
     return Response({"data": serializer.data}, status=status.HTTP_200_OK)
 
+class FavoriteSubjectsView(APIView):
+    permission_classes = [IsAuthenticated]
+
+    def get(self, request, *args, **kwargs):
+        try:
+            student = request.user.student
+            # .values_list('id', flat=True) is very efficient
+            favorite_ids = list(student.favorite_subjects.all().values_list('id', flat=True))
+            return Response({'favorite_ids': favorite_ids}, status=status.HTTP_200_OK)
+        except Exception as e:
+            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+        
+class ToggleFavoriteSubjectView(APIView):
+    """
+    Toggles the favorite status of a subject for the authenticated user.
+    Expects a POST request with {'subject_id': <id>}.
+    """
+    permission_classes = [IsAuthenticated]
+    def post(self, request, *args, **kwargs):
+        subject_id = request.data.get('subject_id')
+        if not subject_id:
+            return Response({"message": "Subject ID is required"}, status=status.HTTP_400_BAD_REQUEST)
+
+        try:
+            student = request.user.student
+            subject = Subject.objects.get(id=subject_id)
+
+            if subject in student.favorite_subjects.all():
+                student.favorite_subjects.remove(subject)
+                action = 'removed'
+            else:
+                student.favorite_subjects.add(subject)
+                action = 'added'
+            
+            return Response({
+                'status': 'success',
+                'action': action,
+                'subject_id': subject.id
+            }, status=status.HTTP_200_OK)
+
+        except Subject.DoesNotExist:
+            return Response({'error': 'Subject not found.'}, status=status.HTTP_404_NOT_FOUND)
+        except AttributeError:
+            # This error happens if request.user.student doesn't exist
+            return Response({'error': 'Student profile not found for this user.'}, status=status.HTTP_404_NOT_FOUND)
+        except Exception as e:
+            return Response({'error': f'An unexpected error occurred: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Index: frontend/src/components/SubjectCatalog/FavoriteButton.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/FavoriteButton.tsx	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
+++ frontend/src/components/SubjectCatalog/FavoriteButton.tsx	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -0,0 +1,39 @@
+import { useFavorites } from '../../context/FavoritesContext'; 
+
+const HeartIcon = ({ filled }: { filled: boolean }) => (
+    <svg xmlns="http://www.w3.org/2000/svg" className="h-7 w-7" fill={filled ? 'currentColor' : 'none'} viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
+        <path strokeLinecap="round" strokeLinejoin="round" d="M4.318 6.318a4.5 4.5 0 016.364 0L12 7.636l1.318-1.318a4.5 4.5 0 116.364 6.364L12 20.364l-7.682-7.682a4.5 4.5 0 010-6.364z" />
+    </svg>
+);
+
+interface FavoriteButtonProps {
+    subjectId: number;
+}
+
+const FavoriteButton = ({ subjectId }: FavoriteButtonProps) => {
+    const { favoriteIds, toggleFavorite, isLoading } = useFavorites();
+    const isFavorite = favoriteIds.has(subjectId);
+
+    return (
+        <button
+            onClick={() => toggleFavorite(subjectId)}
+            disabled={isLoading}
+            className={`group relative flex items-center justify-center transition-all duration-200 p-2 rounded-full ${isFavorite ? 'text-red-500' : 'text-gray-400'} ${isLoading ? 'cursor-not-allowed animate-pulse' : ''}`}
+            aria-label={isFavorite ? 'Unfavorite' : 'Favorite'}
+        >
+            <HeartIcon filled={isFavorite} />
+            <span 
+                className="
+                    absolute bottom-full left-1/2 -translate-x-1/2 mb-2  /* Positioning */
+                    w-max px-2 py-1 bg-gray-800 text-white text-xs rounded-md /* Styling */
+                    opacity-0 group-hover:opacity-100 transition-opacity duration-300 /* Visibility */
+                    pointer-events-none /* So it doesn't interfere with clicks */
+                "
+            >
+                {isFavorite ? 'Отстрани од омилени' : 'Додади во омилени'}
+            </span>
+        </button>
+    );
+};
+
+export default FavoriteButton;
Index: frontend/src/components/SubjectCatalog/SubjectList.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SubjectList.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
+++ frontend/src/components/SubjectCatalog/SubjectList.tsx	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -1,4 +1,5 @@
 import { useNavigate } from "react-router-dom";
 import { Subject } from "../types";
+import FavoriteButton from "./FavoriteButton";
 
 interface SubjectListProps {
@@ -36,5 +37,5 @@
             				{subject.abstract}
           					</p> */}
-						<div className="flex flex-wrap gap-2 mb-4">
+						{/* <div className="flex flex-wrap gap-2 mb-4">
 							{subject.subject_info.tags.map((tag) => (
 								<span
@@ -45,5 +46,6 @@
 								</span>
 							))}
-						</div>
+						</div> */}
+						<FavoriteButton subjectId={subject.id} />
 						<div className="flex justify-between mt-auto gap-3">
 							<button
Index: frontend/src/context/FavoritesContext.tsx
===================================================================
--- frontend/src/context/FavoritesContext.tsx	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
+++ frontend/src/context/FavoritesContext.tsx	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -0,0 +1,72 @@
+import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react';
+import { useAuth } from '../hooks/useAuth'; 
+import useAxiosAuth from '../hooks/useAxiosAuth';
+
+interface FavoritesContextType {
+    favoriteIds: Set<number>; 
+    toggleFavorite: (subjectId: number) => Promise<void>;
+    isLoading: boolean;
+}
+
+const FavoritesContext = createContext<FavoritesContextType | undefined>(undefined);
+
+export const FavoritesProvider = ({ children }: { children: ReactNode }) => {
+    const { accessToken } = useAuth(); 
+    const axiosAuth = useAxiosAuth();
+    const [isLoading, setIsLoading] = useState(true);
+    const [favoriteIds, setFavoriteIds] = useState<Set<number>>(new Set());
+
+     useEffect(() => {
+        if (accessToken) {
+            setIsLoading(true);
+            axiosAuth.get<{ favorite_ids: number[] }>('/student/favorites/')
+                .then(response => {
+                    setFavoriteIds(new Set(response.data.favorite_ids));
+                })
+                .catch(error => console.error("Failed to fetch favorites:", error))
+                .finally(() => setIsLoading(false));
+        } else {
+            // If user logs out, clear the favorites
+            setFavoriteIds(new Set());
+            setIsLoading(false);
+        }
+    }, [accessToken, axiosAuth]);
+
+     const toggleFavorite = useCallback(async (subjectId: number) => {
+        // Optimistic UI update
+        const originalFavorites = new Set(favoriteIds);
+        setFavoriteIds(prevIds => {
+            const newIds = new Set(prevIds);
+            if (newIds.has(subjectId)) {
+                newIds.delete(subjectId);
+            } else {
+                newIds.add(subjectId);
+            }
+            return newIds;
+        });
+
+        try {
+            await axiosAuth.post('/student/toggle-favorite/', { subject_id: subjectId });
+        } catch (error) {
+            console.error('Failed to toggle favorite, reverting.', error);
+            setFavoriteIds(originalFavorites); // Revert on error
+            alert("Error: Could not update favorite status.");
+        }
+    }, [axiosAuth, favoriteIds]);
+
+    const value = { favoriteIds, toggleFavorite, isLoading };
+
+    return (
+        <FavoritesContext.Provider value={value}>
+            {children}
+        </FavoritesContext.Provider>
+    );
+};
+
+export const useFavorites = () => {
+    const context = useContext(FavoritesContext);
+    if (context === undefined) {
+        throw new Error('useFavorites must be used within a FavoritesProvider');
+    }
+    return context;
+};
Index: frontend/src/main.tsx
===================================================================
--- frontend/src/main.tsx	(revision 960f3b9ab32c69d28d155b1e542bf30d084ac353)
+++ frontend/src/main.tsx	(revision d450857c320b2ac0b3ca98f976b373659ab4eb00)
@@ -5,4 +5,5 @@
 import { RecommendationsProvider } from "./context/RecommendationsContext.tsx";
 import { SubjectsProvider } from "./context/SubjectsContext.tsx";
+import { FavoritesProvider } from "./context/FavoritesContext.tsx";
 import "./index.css";
 
@@ -12,5 +13,7 @@
 			<SubjectsProvider>
 				<RecommendationsProvider>
-					<App />
+					<FavoritesProvider>
+						<App />
+					</FavoritesProvider>
 				</RecommendationsProvider>
 			</SubjectsProvider>
