diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java
index 522fbcdb06..d3b1c35773 100644
--- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java
+++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java
@@ -25,4 +25,5 @@ public interface ProjectForumService {
     // TODO: Get these away from here
     List<Pair<ProjectThread, ForumPost>> latestPost(Project a, int amount);
 
+    boolean hasUnreadThreads(Project project, User user);
 }
diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java
index 4c4cc0b2c2..1825a16197 100644
--- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java
@@ -95,6 +95,17 @@ public class ProjectForumServiceImpl implements ProjectForumService {
         return postRepository.latestPost(project, amount);
     }
 
+    @Override
+    public boolean hasUnreadThreads(Project project, User user) {
+        List<ProjectThread> threads = getThreads(project);
+        for (ProjectThread thread : threads) {
+            if (!basicForumService.isThreadRead(user, thread.getForumThread())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public ProjectThread findOne(long threadId) {
         return projectThreadRepository.findOne(threadId);
diff --git a/core/src/main/java/se/su/dsv/scipro/project/Project.java b/core/src/main/java/se/su/dsv/scipro/project/Project.java
index 92c82a9014..9429d2cbfc 100755
--- a/core/src/main/java/se/su/dsv/scipro/project/Project.java
+++ b/core/src/main/java/se/su/dsv/scipro/project/Project.java
@@ -85,6 +85,13 @@ public class Project extends DomainObject {
     @Enumerated(EnumType.STRING)
     private Language language;
 
+    @ElementCollection(fetch = FetchType.LAZY)
+    @CollectionTable(name = "project_user_note", joinColumns = @JoinColumn(name = "project_id"))
+    @Column(name = "note")
+    @SuppressWarnings("JpaDataSourceORMInspection")  // false warning from IntelliJ for the @MapKeyJoinColumn
+    @MapKeyJoinColumn(name = "user_id")
+    private Map<User, String> userNotes = new HashMap<>();
+
     @PrePersist
     @PreUpdate
     void cleanTitle() {
@@ -94,6 +101,14 @@ public class Project extends DomainObject {
         title = title.trim();
     }
 
+    public Map<User, String> getUserNotes() {
+        return userNotes;
+    }
+
+    public void setUserNotes(Map<User, String> userNotes) {
+        this.userNotes = userNotes;
+    }
+
     public boolean isFinalSeminarRuleExempted() {
         return finalSeminarRuleExempted;
     }
diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectNoteService.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectNoteService.java
new file mode 100644
index 0000000000..7ff1657d63
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectNoteService.java
@@ -0,0 +1,9 @@
+package se.su.dsv.scipro.project;
+
+import se.su.dsv.scipro.system.User;
+
+public interface ProjectNoteService {
+    String getUserNote(Project project, User user);
+
+    void setUserNote(Project project, User user, String note);
+}
diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java
index 0121567847..a1c985044f 100755
--- a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java
+++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java
@@ -11,4 +11,8 @@ import java.util.List;
 @Transactional
 public interface ProjectRepo extends JpaRepository<Project, Long>, QueryDslPredicateExecutor<Project> {
     List<User> findMultipleAuthors(Collection<Project> projects);
+
+    String getUserNoteForProject(Project project, User user);
+
+    void setUserNoteForProject(Project project, User user, String note);
 }
\ No newline at end of file
diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java
index 627af554ec..8211412568 100644
--- a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java
@@ -1,5 +1,6 @@
 package se.su.dsv.scipro.project;
 
+import jakarta.transaction.Transactional;
 import se.su.dsv.scipro.system.GenericRepo;
 import se.su.dsv.scipro.system.User;
 
@@ -30,4 +31,16 @@ public class ProjectRepoImpl extends GenericRepo<Project, Long> implements Proje
         query.setParameter("projects", projects);
         return query.getResultList();
     }
+
+    @Override
+    public String getUserNoteForProject(Project project, User user) {
+        return project.getUserNotes().get(user);
+    }
+
+    @Override
+    @Transactional
+    public void setUserNoteForProject(Project project, User user, String note) {
+        project.getUserNotes().put(user, note);
+        save(project);
+    }
 }
diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java
index ed71696686..e52cae2397 100755
--- a/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java
@@ -22,7 +22,7 @@ import java.time.Duration;
 import java.time.Instant;
 import java.util.*;
 
-public class ProjectServiceImpl extends AbstractServiceImpl<Project, Long> implements ProjectService {
+public class ProjectServiceImpl extends AbstractServiceImpl<Project, Long> implements ProjectService, ProjectNoteService {
 
     public static final int MIN_TITLE_LENGTH = 3;
     private final ProjectRepo projectRepo;
@@ -175,6 +175,16 @@ public class ProjectServiceImpl extends AbstractServiceImpl<Project, Long> imple
         return completed;
     }
 
+    @Override
+    public String getUserNote(Project project, User user) {
+        return projectRepo.getUserNoteForProject(project, user);
+    }
+
+    @Override
+    public void setUserNote(Project project, User user, String note) {
+        projectRepo.setUserNoteForProject(project, user, note);
+    }
+
     @Override
     public List<Project> findAll(Filter filter, Pageable pageable) {
         return findAll(toPredicate(filter), pageable);
diff --git a/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/SupervisorProjectNoteDisplay.java b/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/SupervisorProjectNoteDisplay.java
new file mode 100644
index 0000000000..1a6c45d452
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/SupervisorProjectNoteDisplay.java
@@ -0,0 +1,5 @@
+package se.su.dsv.scipro.settings.dataobjects;
+
+public enum SupervisorProjectNoteDisplay {
+    COMPACT, FULL
+}
diff --git a/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java b/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java
index 8cf7d44e31..ac863a2afa 100644
--- a/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java
+++ b/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java
@@ -58,6 +58,11 @@ public class UserProfile extends DomainObject {
     @Enumerated(EnumType.STRING)
     private Roles selectedRole;
 
+    @Basic
+    @Enumerated(EnumType.STRING)
+    @Column(name = "supervisor_project_note_display")
+    private SupervisorProjectNoteDisplay supervisorProjectNoteDisplay = SupervisorProjectNoteDisplay.COMPACT;
+
     @Override
     public Long getId() {
         return this.id;
@@ -147,6 +152,14 @@ public class UserProfile extends DomainObject {
         this.selectedRole = selectedRole;
     }
 
+    public SupervisorProjectNoteDisplay getSupervisorProjectNoteDisplay() {
+        return supervisorProjectNoteDisplay;
+    }
+
+    public void setSupervisorProjectNoteDisplay(SupervisorProjectNoteDisplay supervisorProjectNoteDisplay) {
+        this.supervisorProjectNoteDisplay = supervisorProjectNoteDisplay;
+    }
+
     @Override
     public String toString() {
         return "UserProfile(id=" + this.getId() + ", user=" + this.getUser() + ", skypeId=" + this.getSkypeId() + ", phoneNumber=" + this.getPhoneNumber() + ", otherInfo=" + this.getOtherInfo() + ", mailCompilation=" + this.isMailCompilation() + ", defaultProjectStatusFilter=" + this.getDefaultProjectStatusFilter() + ", defaultProjectTeamMemberRolesFilter=" + this.getDefaultProjectTeamMemberRolesFilter() + ", defaultSupervisorFilter=" + this.isDefaultSupervisorFilter() + ", defaultProjectTypeFilter=" + this.getDefaultProjectTypeFilter() + ", selectedRole=" + this.getSelectedRole() + ")";
diff --git a/core/src/main/resources/db/migration/V388__user_notes_for_projects.sql b/core/src/main/resources/db/migration/V388__user_notes_for_projects.sql
new file mode 100644
index 0000000000..334caad59b
--- /dev/null
+++ b/core/src/main/resources/db/migration/V388__user_notes_for_projects.sql
@@ -0,0 +1,11 @@
+CREATE TABLE IF NOT EXISTS `project_user_note` (
+    `project_id` bigint NOT NULL,
+    `user_id` bigint NOT NULL,
+    `note` text NULL,
+    PRIMARY KEY (`project_id`, `user_id`),
+    CONSTRAINT `FK_project_user_note_project` FOREIGN KEY (`project_id`) REFERENCES `project` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT `FK_project_user_note_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+ALTER TABLE `user_profile`
+    ADD COLUMN `supervisor_project_note_display` VARCHAR(15) NOT NULL DEFAULT 'COMPACT';
diff --git a/view/src/main/java/se/su/dsv/scipro/components/MaxLengthLabel.java b/view/src/main/java/se/su/dsv/scipro/components/MaxLengthLabel.java
new file mode 100644
index 0000000000..edfdd48ab9
--- /dev/null
+++ b/view/src/main/java/se/su/dsv/scipro/components/MaxLengthLabel.java
@@ -0,0 +1,37 @@
+package se.su.dsv.scipro.components;
+
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.util.convert.IConverter;
+
+import java.util.Locale;
+
+public class MaxLengthLabel extends Label {
+    private final IModel<Integer> maxLengthModel;
+
+    public MaxLengthLabel(String id, IModel<String> dataModel, IModel<Integer> maxLength) {
+        super(id, dataModel);
+        this.maxLengthModel = maxLength;
+    }
+
+    @Override
+    protected IConverter<?> createConverter(Class<?> type) {
+        return new MaxLengthConverter();
+    }
+
+    private class MaxLengthConverter implements IConverter<String> {
+        @Override
+        public String convertToObject(String s, Locale locale) {
+            return s;
+        }
+
+        @Override
+        public String convertToString(String o, Locale locale) {
+            Integer maxLength = maxLengthModel.getObject();
+            if (o.length() > maxLength) {
+                return o.substring(0, maxLength) + "...";
+            }
+            return o;
+        }
+    }
+}
diff --git a/view/src/main/java/se/su/dsv/scipro/components/ModalWindowPlus.java b/view/src/main/java/se/su/dsv/scipro/components/ModalWindowPlus.java
index 9faa92158d..0eca546462 100644
--- a/view/src/main/java/se/su/dsv/scipro/components/ModalWindowPlus.java
+++ b/view/src/main/java/se/su/dsv/scipro/components/ModalWindowPlus.java
@@ -1,6 +1,7 @@
 package se.su.dsv.scipro.components;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.behavior.AttributeAppender;
 import org.apache.wicket.markup.ComponentTag;
@@ -9,6 +10,7 @@ import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
+import org.danekja.java.util.function.serializable.SerializableConsumer;
 
 import java.util.function.Function;
 
@@ -83,4 +85,13 @@ public class ModalWindowPlus extends Panel {
         component.setOutputMarkupPlaceholderTag(true);
         replace(component);
     }
+
+    public void onClose(SerializableConsumer<AjaxRequestTarget> onClose) {
+        add(new AjaxEventBehavior("hidden.bs.modal") {
+            @Override
+            protected void onEvent(AjaxRequestTarget target) {
+                onClose.accept(target);
+            }
+        });
+    }
 }
diff --git a/view/src/main/java/se/su/dsv/scipro/forum/panels/AbstractReadStatePanel.java b/view/src/main/java/se/su/dsv/scipro/forum/panels/AbstractReadStatePanel.java
index 4f57d632d0..25eea67afa 100644
--- a/view/src/main/java/se/su/dsv/scipro/forum/panels/AbstractReadStatePanel.java
+++ b/view/src/main/java/se/su/dsv/scipro/forum/panels/AbstractReadStatePanel.java
@@ -20,7 +20,7 @@ public abstract class AbstractReadStatePanel extends Panel {
             @Override
             public void onClick(final Optional<AjaxRequestTarget> target) {
                 target.ifPresent(t -> {
-                    toggleReadState(t);
+                    onFlagClick(t);
                     t.add(icon);
                 });
             }
@@ -33,7 +33,7 @@ public abstract class AbstractReadStatePanel extends Panel {
     }
 
     protected abstract boolean isRead();
-    protected abstract void toggleReadState(final AjaxRequestTarget target);
+    protected abstract void onFlagClick(final AjaxRequestTarget target);
 
     public static final String TOGGLE = "toggle";
     static final String ICON = "icon";
diff --git a/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java b/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java
index 2e16cb4953..908c096695 100644
--- a/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java
+++ b/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java
@@ -31,7 +31,7 @@ public class ThreadReadStatePanel extends AbstractReadStatePanel {
     }
 
     @Override
-    protected void toggleReadState(final AjaxRequestTarget target) {
+    protected void onFlagClick(final AjaxRequestTarget target) {
         boolean read = isRead();
         basicForumService.setThreadRead(SciProSession.get().getUser(), model.getObject(), !read);
 
diff --git a/view/src/main/java/se/su/dsv/scipro/notifications/panels/NotificationDataPanel.java b/view/src/main/java/se/su/dsv/scipro/notifications/panels/NotificationDataPanel.java
index 8718550924..d5e132eb9f 100755
--- a/view/src/main/java/se/su/dsv/scipro/notifications/panels/NotificationDataPanel.java
+++ b/view/src/main/java/se/su/dsv/scipro/notifications/panels/NotificationDataPanel.java
@@ -117,7 +117,7 @@ public class NotificationDataPanel extends Panel {
                     }
 
                     @Override
-                    protected void toggleReadState(final AjaxRequestTarget target) {
+                    protected void onFlagClick(final AjaxRequestTarget target) {
                         Notification notification = rowModel.getObject();
                         notification.setUnread(!notification.isUnread());
                         notificationService.save(notification);
diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteCellPanel.html b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteCellPanel.html
new file mode 100644
index 0000000000..7a5e924096
--- /dev/null
+++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteCellPanel.html
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+<body>
+<wicket:panel>
+    <div wicket:id="edit_note_modal"></div>
+    <span wicket:id="shortened_note"></span>
+    <wicket:container wicket:id="full_note"></wicket:container>
+    <a wicket:id="view_note"><wicket:message key="note.view.edit"/></a>
+</wicket:panel>
+</body>
+</html>
\ No newline at end of file
diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteCellPanel.utf8.properties b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteCellPanel.utf8.properties
new file mode 100644
index 0000000000..5f31ea7d1c
--- /dev/null
+++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteCellPanel.utf8.properties
@@ -0,0 +1,2 @@
+note.modal.title=View/edit note for ${title}
+note.view.edit=View/edit note
diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteForm.html b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteForm.html
new file mode 100644
index 0000000000..bf546f6a76
--- /dev/null
+++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteForm.html
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+<body>
+<wicket:panel>
+    <form wicket:id="form">
+        <div wicket:id="feedback"></div>
+        <div class="mb-3">
+            <label wicket:for="note" class="sr-only">Note</label>
+            <textarea wicket:id="note" rows="20" class="form-control"></textarea>
+        </div>
+        <button wicket:id="save" type="submit" class="btn btn-primary">Save</button>
+    </form>
+</wicket:panel>
+</body>
+</html>
\ No newline at end of file
diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java
new file mode 100644
index 0000000000..b35962f891
--- /dev/null
+++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java
@@ -0,0 +1,129 @@
+package se.su.dsv.scipro.supervisor.panels;
+
+import jakarta.inject.Inject;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.export.AbstractExportableColumn;
+import org.apache.wicket.feedback.FencedFeedbackPanel;
+import org.apache.wicket.injection.Injector;
+import org.apache.wicket.markup.html.basic.MultiLineLabel;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.markup.html.panel.GenericPanel;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.StringResourceModel;
+import se.su.dsv.scipro.components.LargeModalWindow;
+import se.su.dsv.scipro.components.MaxLengthLabel;
+import se.su.dsv.scipro.components.ModalWindowPlus;
+import se.su.dsv.scipro.project.Project;
+import se.su.dsv.scipro.project.ProjectNoteService;
+import se.su.dsv.scipro.settings.dataobjects.SupervisorProjectNoteDisplay;
+import se.su.dsv.scipro.system.User;
+
+import java.time.LocalTime;
+import java.time.temporal.ChronoUnit;
+
+public class ProjectNoteColumn extends AbstractExportableColumn<Project, String> {
+    @Inject
+    private ProjectNoteService projectNoteService;
+
+    private final IModel<User> user;
+    private final IModel<SupervisorProjectNoteDisplay> supervisorProjectNoteDisplayModel;
+
+    public ProjectNoteColumn(IModel<String> displayModel, IModel<User> user,
+            IModel<SupervisorProjectNoteDisplay> supervisorProjectNoteDisplayModel) {
+        super(displayModel);
+        Injector.get().inject(this);
+        this.supervisorProjectNoteDisplayModel = supervisorProjectNoteDisplayModel;
+        this.user = user;
+    }
+
+    @Override
+    public IModel<String> getDataModel(IModel<Project> rowModel) {
+        return LoadableDetachableModel.of(() -> projectNoteService.getUserNote(
+                rowModel.getObject(),
+                user.getObject()));
+    }
+
+    @Override
+    public void populateItem(
+            Item<ICellPopulator<Project>> cellItem,
+            String componentId,
+            IModel<Project> rowModel)
+    {
+        cellItem.add(new ViewAndEditNoteCellPanel(componentId, rowModel));
+    }
+
+    private class ViewAndEditNoteCellPanel extends GenericPanel<Project> {
+        public ViewAndEditNoteCellPanel(String id, IModel<Project> model) {
+            super(id, model);
+
+            ModalWindowPlus modal = new LargeModalWindow("edit_note_modal");
+            modal.setTitle(new StringResourceModel("note.modal.title", this, model));
+            modal.setContent(componentId -> new ViewAndEditNoteForm(componentId, model));
+            add(modal);
+
+            setOutputMarkupId(true);
+            modal.onClose(target -> target.add(this));
+
+            add(new MaxLengthLabel("shortened_note", getDataModel(model), Model.of(100)) {
+                @Override
+                protected void onConfigure() {
+                    super.onConfigure();
+                    setVisibilityAllowed(supervisorProjectNoteDisplayModel.getObject() == SupervisorProjectNoteDisplay.COMPACT);
+                }
+            });
+            add(new MultiLineLabel("full_note", getDataModel(model)) {
+                @Override
+                protected void onConfigure() {
+                    super.onConfigure();
+                    setVisibilityAllowed(supervisorProjectNoteDisplayModel.getObject() == SupervisorProjectNoteDisplay.FULL);
+                }
+            });
+
+            AjaxLink<Object> noteLink = new AjaxLink<>("view_note") {
+                @Override
+                public void onClick(AjaxRequestTarget target) {
+                    modal.show(target);
+                }
+            };
+            add(noteLink);
+        }
+    }
+
+    private class ViewAndEditNoteForm extends GenericPanel<Project> {
+        public ViewAndEditNoteForm(String id, IModel<Project> project) {
+            super(id, project);
+
+            IModel<String> note = getDataModel(project);
+
+            Form<Project> form = new Form<>("form", project) {
+                @Override
+                protected void onSubmit() {
+                    projectNoteService.setUserNote(
+                            project.getObject(),
+                            user.getObject(),
+                            note.getObject()
+                    );
+                    success("Note saved at " + LocalTime.now().truncatedTo(ChronoUnit.SECONDS));
+                }
+            };
+            add(form);
+
+            form.add(new FencedFeedbackPanel("feedback", form));
+
+            form.add(new TextArea<>("note", note));
+            form.add(new AjaxSubmitLink("save") {
+                @Override
+                protected void onAfterSubmit(AjaxRequestTarget target) {
+                    target.add(form);
+                }
+            });
+        }
+    }
+}
diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.html b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.html
index 9b68bf8d79..73ab571f7f 100755
--- a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.html
+++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.html
@@ -31,6 +31,10 @@
                         </strong>
                         <div wicket:id="projectTypes"></div>
                     </div>
+                    <fieldset class="col-6 col-md-3 col-lg-2">
+                        <legend>Note</legend>
+                        <div wicket:id="note_display"></div>
+                    </fieldset>
                 </div>
             </form>
         </div>
diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.java b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.java
index 00498cbd6b..e3cab053eb 100755
--- a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.java
+++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.java
@@ -1,8 +1,11 @@
 package se.su.dsv.scipro.supervisor.panels;
 
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
 import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.LambdaColumn;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
@@ -10,8 +13,10 @@ import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.form.LambdaChoiceRenderer;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LambdaModel;
+import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.Model;
 import se.su.dsv.scipro.components.*;
 import se.su.dsv.scipro.components.datatables.MultipleUsersColumn;
@@ -19,11 +24,15 @@ import se.su.dsv.scipro.components.datatables.UserColumn;
 import se.su.dsv.scipro.dataproviders.FilteredDataProvider;
 import se.su.dsv.scipro.datatables.project.ProjectStateColumn;
 import se.su.dsv.scipro.datatables.project.ProjectTitleColumn;
+import se.su.dsv.scipro.forum.ProjectForumService;
+import se.su.dsv.scipro.forum.pages.threaded.SupervisorThreadedForumPage;
+import se.su.dsv.scipro.forum.panels.AbstractReadStatePanel;
 import se.su.dsv.scipro.project.Project;
 import se.su.dsv.scipro.project.ProjectService;
 import se.su.dsv.scipro.project.ProjectStatus;
 import se.su.dsv.scipro.project.ProjectTeamMemberRoles;
 import se.su.dsv.scipro.session.SciProSession;
+import se.su.dsv.scipro.settings.dataobjects.SupervisorProjectNoteDisplay;
 import se.su.dsv.scipro.settings.dataobjects.UserProfile;
 import se.su.dsv.scipro.springdata.services.UserProfileService;
 import se.su.dsv.scipro.system.ProjectType;
@@ -51,9 +60,12 @@ public class SupervisorMyProjectsPanel extends Panel {
     private ProjectService projectService;
     @Inject
     private UserProfileService profileService;
+    @Inject
+    private ProjectForumService projectForumService;
 
     private ExportableDataPanel dataPanel;
     private ProjectService.Filter filter = new ProjectService.Filter();
+    private IModel<SupervisorProjectNoteDisplay> supervisorProjectNoteDisplayModel = new Model<>();
 
     public SupervisorMyProjectsPanel(String id) {
         super(id);
@@ -72,6 +84,7 @@ public class SupervisorMyProjectsPanel extends Panel {
     private List<IColumn<Project, String>> createColumns() {
         List<IColumn<Project, String>> columns = new ArrayList<>();
         columns.add(new ProjectStateColumn(Model.of("State"), "stateOfMind"));
+        columns.add(new ProjectForumStateColumn(Model.of("Forum")));
         columns.add(new TemporalColumn<>(Model.of("Started"), "startDate", Project::getStartDate));
         columns.add(new LambdaColumn<>(Model.of("Type"), "projectType.name", Project::getProjectTypeName));
         columns.add(new ProjectTitleColumn(Model.of("Title"), "title"));
@@ -81,6 +94,7 @@ public class SupervisorMyProjectsPanel extends Panel {
                 return new ListAdapterModel<>(rowModel.map(Project::getProjectParticipants));
             }
         });
+        columns.add(new ProjectNoteColumn(Model.of("Note"), LoadableDetachableModel.of(this::currentUser), supervisorProjectNoteDisplayModel));
         columns.add(new UserColumn<>(Model.of("Head supervisor"), "headSupervisor.fullName", Project::getHeadSupervisor));
         return columns;
     }
@@ -103,6 +117,7 @@ public class SupervisorMyProjectsPanel extends Panel {
         filter.setRoles(userProfile.getDefaultProjectTeamMemberRolesFilter());
         filter.setFilterSupervisor(userProfile.isDefaultSupervisorFilter());
         filter.setProjectTypes(userProfile.getDefaultProjectTypeFilter());
+        supervisorProjectNoteDisplayModel.setObject(userProfile.getSupervisorProjectNoteDisplay());
     }
 
     private User currentUser() {
@@ -146,6 +161,19 @@ public class SupervisorMyProjectsPanel extends Panel {
                     updateProfileWithCurrentFilter();
                 }
             });
+            BootstrapRadioChoice<SupervisorProjectNoteDisplay> noteDisplay = new BootstrapRadioChoice<>(
+                    "note_display",
+                    supervisorProjectNoteDisplayModel,
+                    List.of(SupervisorProjectNoteDisplay.values()),
+                    new EnumChoiceRenderer<>(this));
+            noteDisplay.add(new AjaxFormChoiceComponentUpdatingBehavior() {
+                @Override
+                public void onUpdate(AjaxRequestTarget target) {
+                    target.add(dataPanel);
+                    updateProfileWithCurrentFilter();
+                }
+            });
+            add(noteDisplay);
         }
 
         private void updateProfileWithCurrentFilter() {
@@ -154,7 +182,33 @@ public class SupervisorMyProjectsPanel extends Panel {
             userProfile.setDefaultProjectTeamMemberRolesFilter(filter.getRoles());
             userProfile.setDefaultSupervisorFilter(filter.isFilterSupervisor());
             userProfile.setDefaultProjectTypeFilter(filter.getProjectTypes());
+            userProfile.setSupervisorProjectNoteDisplay(supervisorProjectNoteDisplayModel.getObject());
             profileService.save(userProfile);
         }
     }
+
+    private class ProjectForumStateColumn extends AbstractColumn<Project, String> {
+        public ProjectForumStateColumn(IModel<String> label) {
+            super(label);
+        }
+
+        @Override
+        public void populateItem(Item<ICellPopulator<Project>> item, String id, IModel<Project> projectModel) {
+            item.add(new AbstractReadStatePanel(id) {
+                @Override
+                protected boolean isRead() {
+                    return !projectForumService.hasUnreadThreads(
+                            projectModel.getObject(),
+                            SciProSession.get().getUser());
+                }
+
+                @Override
+                protected void onFlagClick(AjaxRequestTarget target) {
+                    setResponsePage(
+                            SupervisorThreadedForumPage.class,
+                            SupervisorThreadedForumPage.getPageParameters(projectModel.getObject()));
+                }
+            });
+        }
+    }
 }
diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.utf8.properties b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.utf8.properties
index 8c2d03baf2..17f454ad8c 100644
--- a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.utf8.properties
+++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorMyProjectsPanel.utf8.properties
@@ -9,3 +9,6 @@ ProjectTeamMemberRoles.CO_SUPERVISOR= Co-Supervisor
 ProjectStatus.ACTIVE= Active
 ProjectStatus.INACTIVE= Inactive
 ProjectStatus.COMPLETED= Completed
+
+SupervisorProjectNoteDisplay.COMPACT=Compact
+SupervisorProjectNoteDisplay.FULL=Full
diff --git a/view/src/test/java/se/su/dsv/scipro/SciProTest.java b/view/src/test/java/se/su/dsv/scipro/SciProTest.java
index af6c912281..e712c36790 100755
--- a/view/src/test/java/se/su/dsv/scipro/SciProTest.java
+++ b/view/src/test/java/se/su/dsv/scipro/SciProTest.java
@@ -83,6 +83,7 @@ import se.su.dsv.scipro.peer.PerformReviewService;
 import se.su.dsv.scipro.plagiarism.PlagiarismControl;
 import se.su.dsv.scipro.plagiarism.urkund.UrkundService;
 import se.su.dsv.scipro.profiles.CurrentProfile;
+import se.su.dsv.scipro.project.ProjectNoteService;
 import se.su.dsv.scipro.project.ProjectPeopleStatisticsService;
 import se.su.dsv.scipro.project.ProjectService;
 import se.su.dsv.scipro.project.pages.ProjectStartPage;
@@ -351,6 +352,8 @@ public abstract class SciProTest {
     protected ExaminerTimelineService examinerTimelineService;
     @Mock
     protected NationalSubjectCategoryService nationalSubjectCategoryService;
+    @Mock
+    protected ProjectNoteService projectNoteService;
 
     protected WicketTester tester;
 
diff --git a/war/src/test/java/se/su/dsv/scipro/forum/ProjectForumServiceImplTest.java b/war/src/test/java/se/su/dsv/scipro/forum/ProjectForumServiceImplTest.java
index 199d5e8520..c25abbd10f 100644
--- a/war/src/test/java/se/su/dsv/scipro/forum/ProjectForumServiceImplTest.java
+++ b/war/src/test/java/se/su/dsv/scipro/forum/ProjectForumServiceImplTest.java
@@ -20,6 +20,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.hasItem;
 import static org.hamcrest.Matchers.hasSize;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class ProjectForumServiceImplTest extends ForumModuleTest {
 
@@ -29,23 +30,24 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
     ProjectForumService service;
 
     private Project project;
-    private User user;
+    private User author;
+    private User supervisor;
 
     @BeforeEach
     public void setUp() throws Exception {
         ProjectType projectType = new ProjectType(DegreeType.BACHELOR, "Some project type", "Some description");
         projectType.addModule(ProjectModule.FORUM);
         save(projectType);
-        final User supervisor = save(User.builder().firstName("Bob").lastName("The Builder").emailAddress("bob@example.com").build());
+        supervisor = save(User.builder().firstName("Bob").lastName("The Builder").emailAddress("bob@example.com").build());
         project = Project.builder().title("Some title").projectType(projectType).startDate(LocalDate.now()).headSupervisor(supervisor).build();
         save(project);
-        user = User.builder().firstName("Stina").lastName("Student").emailAddress("stina@example.com").build();
-        save(user);
+        author = User.builder().firstName("Stina").lastName("Student").emailAddress("stina@example.com").build();
+        save(author);
     }
 
     @Test
     public void testLoadThread() {
-        final ProjectThread thread = service.createThread(project, user, "subject", "content", Set.of());
+        final ProjectThread thread = service.createThread(project, author, "subject", "content", Set.of());
         ProjectThread serviceThread = service.findOne(thread.getId());
 
         assertEquals(thread, serviceThread);
@@ -55,17 +57,17 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
     public void testCreateThreadWithPostAttachment() throws Exception {
         final String file = "attachment.txt";
         try (var is = ProjectForumServiceImplTest.class.getResourceAsStream(file)) {
-            final StreamingUpload upload = new StreamingUpload(file, "text/plain", user, 2, is);
-            final ProjectThread thread = service.createThread(project, user, SUBJECT, CONTENT, Set.of(Attachment.newUpload(upload)));
+            final StreamingUpload upload = new StreamingUpload(file, "text/plain", author, 2, is);
+            final ProjectThread thread = service.createThread(project, author, SUBJECT, CONTENT, Set.of(Attachment.newUpload(upload)));
 
-            assertNewForumThread(thread, project, user, SUBJECT, CONTENT, file);
+            assertNewForumThread(thread, project, author, SUBJECT, CONTENT, file);
         }
     }
 
     @Test
     public void testGetPostPageByForumThread() {
-        final ProjectThread thread = service.createThread(project, user, "subject", "content", Set.of());
-        final ForumPost reply = service.createReply(thread, user, "reply", Set.of());
+        final ProjectThread thread = service.createThread(project, author, "subject", "content", Set.of());
+        final ForumPost reply = service.createReply(thread, author, "reply", Set.of());
 
 
         List<ForumPost> servicePage = service.getPosts(thread);
@@ -76,8 +78,8 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
 
     @Test
     public void testGetThreadsByProject() {
-        final ProjectThread thread1 = service.createThread(project, user, "subject 1", "content", Set.of());
-        final ProjectThread thread2 = service.createThread(project, user, "subject 2", "content", Set.of());
+        final ProjectThread thread1 = service.createThread(project, author, "subject 1", "content", Set.of());
+        final ProjectThread thread2 = service.createThread(project, author, "subject 2", "content", Set.of());
 
         List<ProjectThread> serviceThreads = service.getThreads(project);
 
@@ -86,6 +88,16 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
         assertThat(serviceThreads, hasSize(2));
     }
 
+    @Test
+    public void supervisor_has_unread_forum_threads_after_student_replies() {
+        final ProjectThread thread = service.createThread(project, supervisor, "subject", "content", Set.of());
+        service.createReply(thread, author, "reply", Set.of());
+
+        boolean hasUnreadThreads = service.hasUnreadThreads(project, supervisor);
+
+        assertTrue(hasUnreadThreads);
+    }
+
     private void assertNewForumThread(
             ProjectThread thread, Project project, User user, String subject, String content, String attachmentFileName) {
         assertEquals(project, thread.getProject(), "Thread created for the wrong project");