a lightweight way to do this could be

store a field on the user “message unread” boolean or number of unreads
then show the notification on the page if message unread is yes

user clicks the icon to see the unread message
shows a repeating group of conversation_users (conversations this user is in)
data structure would be:
message
conversation (links messages together)
conversation_user (links a conversation to a user and also allows for this user has unread messages in this conversation)

user clicks conversation user - shows conversation with list of messages, changes conversation read to read and triggers backend workflow to check update users unread count

when new message is sent
trigger backend workflow for each of the conversation_users to update their unread counts/booleans and conversation_users

this achieves an optimal data structure since:
no searches are done on the page (user stores the unread count)
search is done for lightweight conversation_user in popout when requested and unread conversations are easily filtered
conversations and messages are loaded only when opened