diff --git a/backend/package.json b/backend/package.json
index e9ca67549b15eaaf5adc1011bb4c125d853dad76..2ff304c717acea8ffe710a491418111c0d88935a 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -32,6 +32,7 @@
     "@nestjs/core": "^10.0.0",
     "@nestjs/jwt": "^10.2.0",
     "@nestjs/platform-express": "^10.0.0",
+    "@nestjs/schedule": "^4.1.1",
     "@nestjs/typeorm": "^10.0.2",
     "@types/jsonld": "^1.5.15",
     "axios": "^1.7.2",
diff --git a/backend/src/auth/auth.controller.ts b/backend/src/auth/auth.controller.ts
index a13f04c04077ef497cb69e71137754fb50677d6b..ab8401bb36cd856dbf811054d2d86ede8f7cf226 100644
--- a/backend/src/auth/auth.controller.ts
+++ b/backend/src/auth/auth.controller.ts
@@ -1,14 +1,16 @@
-import { Body, Controller, Post } from "@nestjs/common";
-import { AuthService } from "./auth.service";
+import { Body, Controller,  Post } from '@nestjs/common';
+import { AuthService } from './auth.service';
 
 @Controller('auth')
 export class AuthController {
-    constructor(
-        private authService:AuthService
-    ) {}
-    @Post('login')
-    async login(@Body() payload: any) {
-        const {expiry, ...authPayload}=payload
-        return this.authService.login(authPayload, expiry);
-    }
-}
\ No newline at end of file
+  constructor(private authService: AuthService) {}
+  @Post('session')
+  async getSession(@Body('payload') payload: any) {
+    return this.authService.getSession(payload);
+  }
+  @Post('login')
+  async login(@Body() payload: any) {
+    const { expiry, ...authPayload } = payload;
+    return this.authService.login(authPayload, expiry);
+  }
+}
diff --git a/backend/src/auth/auth.service.ts b/backend/src/auth/auth.service.ts
index f2c83e3850990c63ea15a2332120a3bf9a7250b7..f1ae6c0d205cda8efac1876d14f84012d2074d00 100644
--- a/backend/src/auth/auth.service.ts
+++ b/backend/src/auth/auth.service.ts
@@ -30,7 +30,6 @@ export class AuthService {
       secret: accessSecret,
     });
   }
-  //the payload could consist of the
   async login(payload: Payload, tte: number | string) {
     //basically should check if the user signature is valid in the case of a drep or just provide a token for a normal user.
     const token = await this.signJWT(payload, tte);
@@ -40,26 +39,36 @@ export class AuthService {
       stakeKey: payload.stakeKey,
       signatureKey: payload.key,
       signature: payload.signature,
+      lastSignedIn: new Date(),
     };
     //check for existing signature
     const existingSig = await this.voltaireService
       .getRepository('Signature')
       .findOne({
-        where: { signature: payload.signature, signatureKey:payload.key, stakeKey: payload.stakeKey, },
+        where: { stakeKey: payload.stakeKey },
       });
     if (existingSig) {
       //update the signature
-      const updatedSig=await this.voltaireService
+      const updatedSig = await this.voltaireService
         .getRepository('Signature')
-        .update(existingSig.id, signatureDto)
-      return { token, updatedSig };
+        .update(existingSig.id, signatureDto);
+      return { token, updatedSig, session: existingSig };
     }
     const insertedSig = await this.voltaireService
       .getRepository('Signature')
       .insert(signatureDto);
-    return { token, insertedSig };
+    return { token, insertedSig, session: insertedSig?.raw[0] };
   }
-  async verifyLogin(token: string) {
-    // should check if there is an existing drep signature in the db. Well this is for dreps who have a profile.
+  async getSession(payload: Payload) {
+    const signature = await this.voltaireService
+      .getRepository('Signature')
+      .findOne({
+        where: {
+          signature: payload.signature,
+          signatureKey: payload.key,
+          stakeKey: payload.stakeKey,
+        },
+      });
+    return signature;
   }
 }
diff --git a/backend/src/comments/comments.service.ts b/backend/src/comments/comments.service.ts
index 40ed2c4a4fc15021547301c74be69d3c63ff0b58..2990d1782494d3d2f430b5f3381ce364ee69706f 100644
--- a/backend/src/comments/comments.service.ts
+++ b/backend/src/comments/comments.service.ts
@@ -1,5 +1,6 @@
 import { Injectable } from '@nestjs/common';
 import { InjectDataSource } from '@nestjs/typeorm';
+import { NotificationsService } from 'src/notifications/notifications.service';
 import { ReactionsService } from 'src/reactions/reactions.service';
 import { DataSource } from 'typeorm';
 
@@ -9,6 +10,7 @@ export class CommentsService {
     @InjectDataSource('default')
     private voltaireService: DataSource,
     private reactionsService: ReactionsService,
+    private notificationsService: NotificationsService,
   ) {}
 
   async getComments(parentId: number, parentEntity: string) {
@@ -58,7 +60,57 @@ export class CommentsService {
       }
     }
 
-    return this.voltaireService.getRepository('Comment').save(newComment);
+    const savedComment = await this.voltaireService
+      .getRepository('Comment')
+      .save(newComment);
+    // send notification to the owner of the parent entity
+    switch (parentEntity) {
+      case 'note':
+        const note = await this.voltaireService
+          .getRepository('Note')
+          .createQueryBuilder('note')
+          .leftJoinAndSelect('note.author', 'signature')
+          .where('note.id = :id', { id: parentId })
+          .getOne();
+        if (note) {
+          const owner = note.author?.id;
+          if (voter !== note?.author?.stakeKey) {
+            await this.notificationsService.createNotification(
+              this.notificationsService.newCommentOnNoteNotification(
+                new Date(note?.createdAt as Date).getTime(),
+                note?.author?.voterId,
+                voter,
+              ),
+              owner,
+            );
+          }
+        }
+        break;
+      case 'comment':
+        const parentComment = await this.voltaireService
+          .getRepository('Comment')
+          .findOne({ where: { id: parentId } });
+
+        if (parentComment) {
+          const owner = parentComment.voter;
+          if (owner !== voter) {
+            const signature = await this.voltaireService
+              .getRepository('Signature')
+              .findOne({ where: { stakeKey: owner } });
+            await this.notificationsService.createNotification(
+              this.notificationsService.newReplyToCommentNotification(
+                voter,
+              ),
+              signature.id,
+              savedComment.createdAt,
+            );
+          }
+        }
+        break;
+      default:
+        break;
+    }
+    return savedComment;
   }
 
   async removeComment(
diff --git a/backend/src/drep/drep.service.ts b/backend/src/drep/drep.service.ts
index 3c2bf09a69885e7a6ee378fb57159e6e1bf17dfd..de2688e89d7f6215b71e932802e35eba4310318a 100644
--- a/backend/src/drep/drep.service.ts
+++ b/backend/src/drep/drep.service.ts
@@ -415,7 +415,6 @@ export class DrepService {
     tillDate,
     filterValues,
   }: DRepTimelineParams): Observable<TimelineEntry[]> {
-    
     const filters = this.getFilters(filterValues);
     const { startingTime, endingTime } = this.getTimeRange(
       beforeDate,
@@ -515,13 +514,25 @@ export class DrepService {
             epoch_no: results.regData.epoch_of_registration,
           });
         }
-    
+
+        // Remove duplicate timeline entries based on a unique identifier (e.g., timestamp and type)
+        const uniqueEntries = Array.from(
+          new Map(
+            timelineEntries.map((entry) => [
+              `${new Date(entry.timestamp).getTime()}-${entry.type}`,
+              entry,
+            ]),
+          ).values(),
+        );
+
         // Sort timeline entries by timestamp (latest first)
-        timelineEntries.sort((a, b) => {
-          return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
+        uniqueEntries.sort((a, b) => {
+          return (
+            new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
+          );
         });
-    
-        return timelineEntries;
+
+        return uniqueEntries;
       }),
       timeout(100000),
       catchError((error) => {
@@ -591,10 +602,10 @@ export class DrepService {
           tillDate,
         },
       );
-  
+
     // Prepare visibility conditions
     const visibilityConditions = ['note.visibility = :everyone'];
-  
+
     const visibilityParams: {
       everyone: string;
       delegators?: string;
@@ -604,7 +615,7 @@ export class DrepService {
     } = {
       everyone: 'everyone',
     };
-  
+
     // 'delegators' visibility
     if (delegation) {
       visibilityConditions.push(
@@ -613,7 +624,7 @@ export class DrepService {
       visibilityParams.delegators = 'delegators';
       visibilityParams.drepVoterId = delegation.drep_view;
     }
-  
+
     // 'myself' visibility
     if (stakeKeyBech32) {
       visibilityConditions.push(
@@ -622,13 +633,13 @@ export class DrepService {
       visibilityParams.myself = 'myself';
       visibilityParams.stakeKeyBech32 = stakeKeyBech32;
     }
-  
+
     // Combine visibility conditions with OR logic
     queryBuilder.andWhere(
       `(${visibilityConditions.join(' OR ')})`,
       visibilityParams,
     );
-  
+
     // Convert queryBuilder result to an observable
     return from(queryBuilder.getRawMany()).pipe(
       switchMap((allNotes) => {
@@ -636,7 +647,7 @@ export class DrepService {
           // If no notes are found, return an observable emitting an empty array
           return of([]);
         }
-  
+
         // Using forkJoin to run reactions and comments observables for all notes
         const noteObservables = allNotes.map((note) => {
           return forkJoin({
@@ -655,7 +666,7 @@ export class DrepService {
             })),
           );
         });
-  
+
         // Return an observable that emits all notes with reactions and comments
         return forkJoin(noteObservables);
       }),
@@ -664,7 +675,7 @@ export class DrepService {
         return of([]); // Return an empty array on error
       }),
     );
-  }  
+  }
 
   async populateFakeDRepData() {
     const dreps = await this.getAllDRepsCexplorer();
@@ -986,10 +997,10 @@ export class DrepService {
         [voterId],
       );
 
-      const metadataUrl = metadata?.[0]?.metadata_url
+      const metadataUrl = metadata?.[0]?.metadata_url;
 
-      if(!metadataUrl){
-        throw new NotFoundException("metadata url not found!")
+      if (!metadataUrl) {
+        throw new NotFoundException('metadata url not found!');
       }
 
       const { data } = await firstValueFrom(
@@ -1007,12 +1018,12 @@ export class DrepService {
     }
   }
 
-  async getVoltaireDRepViaVoterID(drepVoterId){
+  async getVoltaireDRepViaVoterID(drepVoterId) {
     return await this.voltaireService
-    .getRepository('Drep')
-    .createQueryBuilder('drep')
-    .leftJoinAndSelect('signature', 'signature', 'signature.drepId = drep.id')
-    .where('signature.voterId = :drepVoterId', { drepVoterId })
-    .getRawOne();
+      .getRepository('Drep')
+      .createQueryBuilder('drep')
+      .leftJoinAndSelect('signature', 'signature', 'signature.drepId = drep.id')
+      .where('signature.voterId = :drepVoterId', { drepVoterId })
+      .getRawOne();
   }
 }
diff --git a/backend/src/dto/createNoteDto.ts b/backend/src/dto/createNoteDto.ts
index b9264decd877aa474247235cfd2237ef18500e60..0da784c62f6f43fba90d87e6514688b79856a527 100644
--- a/backend/src/dto/createNoteDto.ts
+++ b/backend/src/dto/createNoteDto.ts
@@ -1,5 +1,4 @@
 import { IsNotEmpty, IsOptional } from 'class-validator';
-import {Type} from 'class-transformer'
 
 export class createNoteDto {
   @IsNotEmpty()
diff --git a/backend/src/dto/createNotificationDto.ts b/backend/src/dto/createNotificationDto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f6da139ec7f444c39f56066642f5316047f87bf1
--- /dev/null
+++ b/backend/src/dto/createNotificationDto.ts
@@ -0,0 +1,14 @@
+enum NotificationType {
+  info = 'info',
+  warning = 'warning',
+  error = 'error',
+}
+
+export class createNotificationDto {
+  title: string;
+  message: string;
+  type: keyof typeof NotificationType;
+  isRead?: boolean;
+  isArchived?: boolean;
+  isPersistent?: boolean;   
+}
diff --git a/backend/src/entities/notification.entity.ts b/backend/src/entities/notification.entity.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0233522c00041789077fb486e63d7bde45821735
--- /dev/null
+++ b/backend/src/entities/notification.entity.ts
@@ -0,0 +1,41 @@
+import {  BaseImmutableEntity } from 'src/global';
+import { Column, Entity,  PrimaryGeneratedColumn } from 'typeorm';
+
+
+//for reference to the notifications   
+@Entity() 
+export class Notification extends BaseImmutableEntity {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column()
+  title: string;
+
+  @Column()
+  message: string;
+
+  @Column({
+    type: 'enum',
+    enum: ['info', 'warning', 'error'],
+    default: 'info',
+  })
+  type: string;
+
+  @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
+  createdAt: Date;
+
+  @Column({ default: false })
+  isRead: boolean;
+
+  @Column({ default: false })
+  isArchived: boolean;
+
+  @Column({ nullable: true })
+  deletedAt: Date;
+
+  @Column({ default: false })
+  isPersistent: boolean;
+
+  @Column()
+  recipient: string;
+}
diff --git a/backend/src/entities/signatures.entity.ts b/backend/src/entities/signatures.entity.ts
index 94534706c39f06f199139539ff97fa1903ecf03a..76b1a37bb5f92469fd59833c9f05dfe988e0251c 100644
--- a/backend/src/entities/signatures.entity.ts
+++ b/backend/src/entities/signatures.entity.ts
@@ -24,4 +24,7 @@ export class Signature {
 
   @Column({ nullable: true, unique: false, default: null })
   signatureKey: string;
+
+  @Column({ nullable: true, unique: false, default: null })
+  lastSignedIn: Date;
 }
diff --git a/backend/src/entities/synctime.entity.ts b/backend/src/entities/synctime.entity.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7e64e53a705495044d564f4252e3a809dfb5ed6a
--- /dev/null
+++ b/backend/src/entities/synctime.entity.ts
@@ -0,0 +1,10 @@
+import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
+
+@Entity()
+export class Synctime {
+  @PrimaryGeneratedColumn()
+  id: number;
+
+  @Column()
+  lastSyncTime: string;
+}
diff --git a/backend/src/global/base.entity.ts b/backend/src/global/base.entity.ts
index ed350cb1e878e04a6b6f1d2c2ae491cb22b7fa9a..8682920d160aba2e5c7aca48dd6018ba4cab1d7e 100644
--- a/backend/src/global/base.entity.ts
+++ b/backend/src/global/base.entity.ts
@@ -49,3 +49,17 @@ export abstract class BaseEntity extends SoftDeletableBaseEntity {
   @UpdateDateColumn() // TypeORM decorator for update date
   updatedAt?: Date;
 }
+/**
+ * Abstract base entity with common fields for primary key, creation, soft-delete, and more.
+ */
+export abstract class BaseImmutableEntity extends SoftDeletableBaseEntity {
+  // Primary key of UUID type
+  @PrimaryGeneratedColumn()
+  id?: number;
+
+  @CreateDateColumn({
+    update: false,
+  }) // TypeORM decorator for creation date
+  createdAt?: Date;
+
+}
diff --git a/backend/src/migrations/1728984622640-migrations.ts b/backend/src/migrations/1728984622640-migrations.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f97cd276f77c6e7f1502b115e7d8be4b1ddabbd4
--- /dev/null
+++ b/backend/src/migrations/1728984622640-migrations.ts
@@ -0,0 +1,34 @@
+import { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class Migrations1728984622640 implements MigrationInterface {
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(`
+        CREATE TABLE "notification" (
+            "id" SERIAL NOT NULL PRIMARY KEY,
+            "title" varchar NOT NULL,
+            "message" varchar NOT NULL,
+            "type" varchar NOT NULL DEFAULT 'info',
+            "createdAt" timestamp NOT NULL DEFAULT now(),
+            "isRead" boolean NOT NULL DEFAULT false,
+            "isArchived" boolean NOT NULL DEFAULT false,
+            "deletedAt" timestamp,
+            "isPersistent" boolean NOT NULL DEFAULT false,
+            "recipient" integer NOT NULL
+        );
+    `);
+    await queryRunner.query(`
+        ALTER TABLE "notification" 
+        ADD CONSTRAINT "FK_signatureId" FOREIGN KEY ("recipient") REFERENCES "signature" ("id");
+    `);
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(`
+        ALTER TABLE "notification" 
+        DROP CONSTRAINT "FK_signatureId";
+    `);
+    await queryRunner.query(`
+        DROP TABLE "notification";
+    `);
+  }
+}
diff --git a/backend/src/migrations/1729032244978-addLastSignedIn.ts b/backend/src/migrations/1729032244978-addLastSignedIn.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b98bc4bd43c4e326f2b247be57467001d703bf2
--- /dev/null
+++ b/backend/src/migrations/1729032244978-addLastSignedIn.ts
@@ -0,0 +1,19 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class AddLastSignedIn1729032244978 implements MigrationInterface {
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`
+            ALTER TABLE "signature"
+            ADD COLUMN "lastSignedIn" timestamp NULL;
+        `);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`
+            ALTER TABLE "signature"
+            DROP COLUMN "lastSignedIn";
+        `);
+    }
+
+}
diff --git a/backend/src/migrations/1729359985813-syncTime.ts b/backend/src/migrations/1729359985813-syncTime.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5c73ea598ff1a5fdaa6547cbe54f38f8a13a3738
--- /dev/null
+++ b/backend/src/migrations/1729359985813-syncTime.ts
@@ -0,0 +1,20 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class SyncTime1729359985813 implements MigrationInterface {
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`
+             CREATE TABLE "synctime" (
+            "id" SERIAL NOT NULL PRIMARY KEY,
+             "lastSyncTime" timestamp NOT NULL DEFAULT now()
+        )
+            `)
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`
+            DROP TABLE "synctime"
+        `);
+    }
+
+}
diff --git a/backend/src/migrations/1729366851137-delete-duplicate-signatures.ts b/backend/src/migrations/1729366851137-delete-duplicate-signatures.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b53178306639817256d837018ee1ff786aa911ab
--- /dev/null
+++ b/backend/src/migrations/1729366851137-delete-duplicate-signatures.ts
@@ -0,0 +1,44 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class DeleteDuplicateSignatures1729366851137 implements MigrationInterface {
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        //delete duplicate signatures where "drepId" is NULL
+        await queryRunner.query(`
+            DELETE FROM "signature" sig
+            WHERE sig.id IN (
+                SELECT s1.id
+                FROM "signature" s1
+                WHERE s1."stakeKey" IS NOT NULL
+                AND EXISTS (
+                    SELECT 1
+                    FROM "signature" s2
+                    WHERE s1."stakeKey" = s2."stakeKey"
+                    AND (s1."drepId" IS NULL OR s1."drepId" = s2."drepId")
+                    AND s1.id <> s2.id 
+                    AND s2."drepId" IS NOT NULL
+                )
+                AND s1."drepId" IS NULL -- Specifically delete entries where "drepId" is NULL
+            )
+        `);
+        //delete duplicate signatures where "drepId" is NOT NULL and is the same
+        await queryRunner.query(`
+            DELETE FROM "signature" sig
+            WHERE sig.id IN (
+                SELECT id FROM (
+                    SELECT id,
+                           ROW_NUMBER() OVER (PARTITION BY "stakeKey", "drepId" ORDER BY id) AS row_num
+                    FROM "signature"
+                    WHERE "stakeKey" IS NOT NULL
+                ) AS ranked
+                WHERE ranked.row_num > 1
+            );
+          `);
+          
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        // No need to rollback
+    }
+
+}
diff --git a/backend/src/note/note.service.ts b/backend/src/note/note.service.ts
index febba4b2bda9ee47673904f3c5eb59116f2215dd..6faf4ee4b221c9375e38693761ced7d31d5dfaa4 100644
--- a/backend/src/note/note.service.ts
+++ b/backend/src/note/note.service.ts
@@ -1,11 +1,11 @@
-import { Injectable, NotFoundException } from '@nestjs/common';
+import { HttpException, Injectable, NotFoundException } from '@nestjs/common';
 import { InjectDataSource } from '@nestjs/typeorm';
 import { CommentsService } from 'src/comments/comments.service';
 import { Delegation } from 'src/common/types';
 import { DrepService } from 'src/drep/drep.service';
 import { createNoteDto } from 'src/dto';
+import { NotificationsService } from 'src/notifications/notifications.service';
 import { ReactionsService } from 'src/reactions/reactions.service';
-import { VoterService } from 'src/voter/voter.service';
 import { DataSource } from 'typeorm';
 @Injectable()
 export class NoteService {
@@ -15,7 +15,7 @@ export class NoteService {
     private drepService: DrepService,
     private reactionsService: ReactionsService,
     private commentsService: CommentsService,
-    private voterService: VoterService,
+    private notificationsService: NotificationsService,
   ) {}
   async getAllNotes(
     stakeKeyBech32?: string,
@@ -71,7 +71,7 @@ export class NoteService {
         .getRepository('Signature')
         .findOne({ where: { stakeKey: noteDto.stake_addr } });
       if (!author) {
-        return new NotFoundException('Author details not found!');
+        throw new NotFoundException('Author details not found!');
       }
       const modifiedNoteDto = {
         ...noteDto,
@@ -81,10 +81,20 @@ export class NoteService {
       const res = await this.voltaireService
         .getRepository('Note')
         .insert(modifiedNoteDto);
+      // add a notification for all delegators if a note is created by the drep and visible to delegators
+      if (isDRepPresent && noteDto.visibility !== 'myself') {
+        await this.notificationsService.processNewNoteNotificationsForDelegators(
+          isDRepPresent.view,
+          new Date(),
+        );
+      }
       return { noteAdded: res.identifiers[0].id };
     } catch (error) {
       console.log(error);
-      return new NotFoundException('DRep associated with note not found!');
+      throw new HttpException(
+        ((error?.code == 23505) && "Duplicate Note found") || error?.message || error?.status || 'An error occured',
+        ((error?.code == 23505) && 409) || 500,
+      );
     }
   }
   async updateNoteInfo(noteId: string, note: createNoteDto) {
diff --git a/backend/src/notifications/notifications.controller.ts b/backend/src/notifications/notifications.controller.ts
index 39937fc9db0774ececc89acd947e63c1a56a8e70..2b938691fb76598d898a25f69a77d00179c504b4 100644
--- a/backend/src/notifications/notifications.controller.ts
+++ b/backend/src/notifications/notifications.controller.ts
@@ -1,11 +1,34 @@
-import {Controller, Get} from '@nestjs/common';
-import {NotificationsService} from "./notifications.service";
+import { Body, Controller, Get, Param, Post } from '@nestjs/common';
+import { NotificationsService } from './notifications.service';
+import { createNotificationDto } from 'src/dto/createNotificationDto';
 
 @Controller('notifications')
 export class NotificationsController {
   constructor(private notificationService: NotificationsService) {}
-  @Get('/')
-  async getNotifications() {
-    return this.notificationService.getNotifications();
+  @Get('/:recipientId/all')
+  async getNotifications(@Param('recipientId') recipientId: string) {
+    return this.notificationService.getNotifications(recipientId);
+  }
+  @Post('/:recipientId/new')
+  async createNotification(
+    @Param('recipientId') recipientId: string,
+    @Body() content: createNotificationDto,
+  ) {
+    return this.notificationService.createNotification(
+      content,
+      Number(recipientId),
+    );
+  }
+  @Post('/:notificationId/read')
+  async markNotificationAsRead(
+    @Param('notificationId') notificationId: string,
+  ) {
+    return this.notificationService.markNotificationAsRead(notificationId);
+  }
+  @Post('/:notificationId/unread')
+  async markNotificationAsUnread(
+    @Param('notificationId') notificationId: string,
+  ) {
+    return this.notificationService.markNotificationAsUnread(notificationId);
   }
 }
diff --git a/backend/src/notifications/notifications.module.ts b/backend/src/notifications/notifications.module.ts
index a94ffc357301051af9928365cdfd6aad77fd3858..d7032e660ebcd66f834812d44216da8157c8c867 100644
--- a/backend/src/notifications/notifications.module.ts
+++ b/backend/src/notifications/notifications.module.ts
@@ -1,12 +1,16 @@
-import { Module } from '@nestjs/common';
+import { Global, Module } from '@nestjs/common';
+import { NotificationsService } from './notifications.service';
+import { NotificationsController } from './notifications.controller';
+import { ScheduleModule } from '@nestjs/schedule';
 import { TypeOrmModule } from '@nestjs/typeorm';
-import { Reaction } from 'src/entities/reaction.entity';
-import {NotificationsService} from "./notifications.service";
-import {NotificationsController} from "./notifications.controller";
+import { Notification } from 'src/entities/notification.entity';
+import { Synctime } from 'src/entities/synctime.entity';
 
+@Global()
 @Module({
-  imports: [TypeOrmModule.forFeature([Reaction])],
+  imports: [ScheduleModule.forRoot(), TypeOrmModule.forFeature([Notification, Synctime])],
+  exports: [NotificationsService],
   controllers: [NotificationsController],
-  providers: [NotificationsService]
+  providers: [NotificationsService],
 })
 export class NotificationsModule {}
diff --git a/backend/src/notifications/notifications.service.ts b/backend/src/notifications/notifications.service.ts
index 20adbc31c20630bb7663c0fd8779b1b650cfe141..42976a833c9ca974340d55d89d284db5c8a76f89 100644
--- a/backend/src/notifications/notifications.service.ts
+++ b/backend/src/notifications/notifications.service.ts
@@ -1,28 +1,316 @@
-import { Injectable } from '@nestjs/common';
+import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
+import { Cron, CronExpression } from '@nestjs/schedule';
 import { InjectDataSource } from '@nestjs/typeorm';
-import { DataSource } from 'typeorm';
+import { VotingActivityHistory } from 'src/common/types';
+import { createNotificationDto } from 'src/dto/createNotificationDto';
+import { Signature } from 'src/entities/signatures.entity';
+import { getCurrentDelegationWithStakeHexQuery } from 'src/queries/currentDelegation';
+import { getDrepVotingActivityInTimestampQuery } from 'src/queries/drepVotingActivity';
+import { DataSource, In } from 'typeorm';
+type NotificationEvent = //for reference
 
+    | 'note_creation'
+    | 'voting'
+    | 'comment_on_note'
+    | 'reply_to_comment'
+    | 'reaction_to_note'
+    | 'reaction_to_comment';
 @Injectable()
 export class NotificationsService {
   constructor(
     @InjectDataSource('default')
     private voltaireService: DataSource,
+    @InjectDataSource('dbsync')
+    private cexplorerService: DataSource,
   ) {}
 
-  async getNotifications() {
-    return [
-      // {
-      //   label: 'dbSync Error',
-      //   text: 'Register to become a DRep, delegate voting power to DReps, & review & vote on governance actions.',
-      //   type: 'info'
-      // },
-    ];
-    // const notifications = await this.voltaireService
-    //   .getRepository('Notification')
-    //   .createQueryBuilder('Notification')
-    //   .where('Notification.parentId = :parentId', { parentId })
-    //   .andWhere('Notification.parentEntity = :parentEntity', { parentEntity })
-    //   .getMany();
-    // return notifications;
+  async getNotifications(ownerId: string) {
+    const notifications = await this.voltaireService
+      .getRepository('Notification')
+      .createQueryBuilder('notification')
+      .where('notification.recipient = :ownerId', { ownerId })
+      .getMany();
+    //sort by date(latest) and isRead
+    notifications.sort((a, b) => {
+      if (a.isRead && !b.isRead) {
+        return 1;
+      }
+      if (!a.isRead && b.isRead) {
+        return -1;
+      }
+      return b.createdAt.getTime() - a.createdAt.getTime();
+    });
+    return notifications;
+  }
+  async createNotification(
+    content: createNotificationDto,
+    ownerId: number,
+    creationTime?: Date,
+  ) {
+    //first check if the owner exists
+    const owner = await this.voltaireService
+      .getRepository('Signature')
+      .findOne({ where: { id: ownerId } });
+    if (!owner) {
+      throw new HttpException('Owner not found', HttpStatus.NOT_FOUND);
+    }
+    const notification = this.voltaireService
+      .getRepository('Notification')
+      .create({
+        ...content,
+        createdAt: creationTime || new Date(),
+        recipient: Number(ownerId),
+      });
+    await this.voltaireService.getRepository('Notification').save(notification);
+    return notification;
+  }
+  async markNotificationAsRead(notificationId: string) {
+    const notification = await this.voltaireService
+      .getRepository('Notification')
+      .findOne({ where: { id: notificationId } });
+    if (!notification) {
+      throw new HttpException('Notification not found', HttpStatus.NOT_FOUND);
+    }
+    notification.isRead = true;
+    return await this.voltaireService
+      .getRepository('Notification')
+      .save(notification);
+  }
+
+  async markNotificationAsUnread(notificationId: string) {
+    const notification = await this.voltaireService
+      .getRepository('Notification')
+      .findOne({ where: { id: notificationId } });
+    if (!notification) {
+      throw new HttpException('Notification not found', HttpStatus.NOT_FOUND);
+    }
+    notification.isRead = false;
+    return await this.voltaireService
+      .getRepository('Notification')
+      .save(notification);
+  }
+
+  async deleteNotification(notificationId: string) {
+    const notification = await this.voltaireService
+      .getRepository('Notification')
+      .findOne({ where: { id: notificationId } });
+    if (!notification) {
+      throw new HttpException('Notification not found', HttpStatus.NOT_FOUND);
+    }
+    return await this.voltaireService
+      .getRepository('Notification')
+      .delete(notification);
+  }
+  async bulkDeleteNotifications(notificationIds: string[]) {
+    const notifications = await this.voltaireService
+      .getRepository('Notification')
+      .findBy({ id: In(notificationIds) });
+    if (!notifications) {
+      throw new HttpException('Notifications not found', HttpStatus.NOT_FOUND);
+    }
+    return await this.voltaireService
+      .getRepository('Notification')
+      .delete(notifications);
+  }
+  async processEntityVoteNotifications(
+    signature: Signature,
+    lastSyncTime: Date,
+  ) {
+    try {
+      //get all the events since the last signin
+      const timeSinceLastSync = lastSyncTime || signature.lastSignedIn;
+      //note_creation by drep delegated to
+      const delegatedTo = (await this.cexplorerService.query(
+        getCurrentDelegationWithStakeHexQuery,
+        [signature.stakeKey],
+      )) as [{ drep_view: string }];
+      const votingActivity = (await this.cexplorerService.manager.query(
+        getDrepVotingActivityInTimestampQuery,
+        [delegatedTo[0].drep_view, timeSinceLastSync, new Date()],
+      )) as VotingActivityHistory[];
+      for (const vote of votingActivity) {
+        //check if voter is the recipient, skip if so
+        if (signature.voterId === vote.view) {
+          continue;
+        }
+        const timeVoted = new Date(vote.time_voted).getTime();
+        const notificationContent = this.newVoteOnProposalNotification(
+          timeVoted,
+          delegatedTo[0].drep_view,
+          vote.vote,
+        );
+
+        await this.createNotification(
+          notificationContent,
+          signature.id,
+          vote.time_voted,
+        );
+      }
+      return 'Done';
+    } catch (error) {
+      console.log('Error while processing vote notifications', error);
+      throw error;
+    }
+  }
+  async processNewNoteNotificationsForDelegators(
+    drepId: string,
+    note_creation_date: Date,
+  ) {
+    //get all the delegators of the drep
+    const drep = await this.cexplorerService.query(
+      `SELECT id, view FROM drep_hash WHERE view = $1`,
+      [drepId],
+    );
+    const delegators = (await this.cexplorerService.query(
+      ` SELECT DISTINCT sa.view FROM delegation_vote as dv
+        JOIN stake_address as sa on sa.id = dv.addr_id
+        WHERE drep_hash_id = $1`,
+      [drep[0].id],
+    )) as [{ view: string }];
+    for (const delegator of delegators) {
+      //check those who have ever signed in
+      const signature = await this.voltaireService
+        .getRepository('Signature')
+        .findOne({ where: { stakeKey: delegator.view } });
+      if (!signature || signature?.voterId === drepId) {
+        continue;
+      }
+      //check if delegator has signed in recently ( 2wks)
+      if (
+        new Date(signature.lastSignedIn).getTime() <
+        note_creation_date.getTime() - 14 * 24 * 60 * 60 * 1000
+      ) {
+        //Delegator has not signed in recently. Skipping to save resources
+        continue;
+      }
+      //send notification to each delegator
+      const notificationContent = this.newNoteNotification(
+        note_creation_date.getTime(),
+        drepId,
+      );
+      await this.createNotification(notificationContent, signature.id);
+    }
+    return 'Done';
+  }
+  // Notification templates
+  newNoteNotification(note_creation_date: number, drepId: string) {
+    return {
+      title: 'New Note',
+      message: `The [DRep](/dreps/${drepId}) you have delegated to has created a new note. Check it out [here](/dreps/${drepId}?start=${note_creation_date - 5 * 24 * 60 * 60 * 1000}&end=${note_creation_date})`,
+      type: 'info' as 'info',
+    };
+  }
+  newCommentOnNoteNotification(
+    note_creation_date: number,
+    drepId: string,
+    voterId: string,
+  ) {
+    return {
+      title: 'New Comment',
+      message: `A [voter](/voters/${voterId}) has commented on your [note](/dreps/${drepId}?start=${note_creation_date - 5 * 24 * 60 * 60 * 1000}&end=${note_creation_date})`,
+      type: 'info' as 'info',
+    };
+  }
+  newReplyToCommentNotification(voterId: string) {
+    return {
+      title: 'New Reply',
+      message: `A [voter](/voters/${voterId}) has replied to your comment.`,
+      type: 'info' as 'info',
+    };
+  }
+  newReactionToNoteNotification(
+    reactionType: 'like' | 'dislike' | 'love' | 'rocket',
+    voterId: string,
+    drepId:string,
+    note_creation_date: number,
+  ) {
+    const reactionIcons = {
+      thumbsup: '👍',
+      thumbsdown: '👎',
+      like: '❤️',
+      rocket: '🚀',
+    };
+    return {
+      title: 'Note Reaction',
+      message: `A [voter](/voters/${voterId}) has reacted ${reactionIcons[reactionType]} to your [note](/dreps/${drepId}?start=${note_creation_date - 5 * 24 * 60 * 60 * 1000}&end=${note_creation_date})`,
+      type: 'info' as 'info',
+    };
+  }
+  newReactionForCommentNotification(
+    reactionType: 'like' | 'dislike' | 'love' | 'rocket',
+    voterId: string,
+  ) {
+    const reactionIcons = {
+      thumbsup: '👍',
+      thumbsdown: '👎',
+      like: '❤️',
+      rocket: '🚀',
+    };
+    return {
+      title: 'Comment Reaction',
+      message: `A [voter](/voters/${voterId}) has reacted ${reactionIcons[reactionType]} to your comment`,
+      type: 'info' as 'info',
+    };
+  }
+  newVoteOnProposalNotification(
+    timeVoted: number,
+    drepId: string,
+    voteType: string,
+  ) {
+    return {
+      title: 'Proposal Vote',
+      message: `The [drep](/dreps/${drepId}) you have delegated to has just voted ${voteType} on this [proposal](/dreps/${drepId}?start=${timeVoted - 5 * 24 * 60 * 60 * 1000}&end=${timeVoted}).`,
+      type: 'info' as 'info',
+    };
+  }
+  //will purge notifications older than 90 days and process vote notifications every hour
+  @Cron(CronExpression.EVERY_HOUR)
+  private async notificationProcessAndPurge() {
+    const synctime = await this.voltaireService
+      .getRepository('Synctime')
+      .find();
+    //get all signatures
+    const signatures = await this.voltaireService
+      .getRepository('Signature')
+      .find({});
+    if (signatures) {
+      for (const sig of signatures) {
+        //check if the signer sign in is less than 2 wks old
+        if (
+          new Date(sig.lastSignedIn).getTime() <
+          new Date().getTime() - 14 * 24 * 60 * 60 * 1000
+        ) {
+          //skip to save resources. unwise to notify inactive users
+          continue;
+        }
+        await this.processEntityVoteNotifications(
+          sig as Signature,
+          synctime[0]?.lastSyncTime,
+        );
+      }
+    }
+    //get notifications
+    const notifications = await this.voltaireService
+      .getRepository('Notification')
+      .find({});
+    if (notifications) {
+      const oldNotifs = notifications.filter((notification) => {
+        const ninetyDaysAgo = new Date();
+        ninetyDaysAgo.setDate(ninetyDaysAgo.getDate() - 90);
+        return notification.createdAt < ninetyDaysAgo;
+      });
+      if (oldNotifs.length > 0) {
+        await this.bulkDeleteNotifications(oldNotifs.map((notif) => notif.id));
+        console.log(`${oldNotifs.length} notifications purged`);
+      }
+    }
+    if (!synctime || synctime?.length === 0) {
+      await this.voltaireService
+        .getRepository('Synctime')
+        .insert({ lastSyncTime: new Date() });
+    } else
+      await this.voltaireService
+        .getRepository('Synctime')
+        .update(synctime[0]?.id, { lastSyncTime: new Date() });
   }
 }
diff --git a/backend/src/queries/currentDelegation.ts b/backend/src/queries/currentDelegation.ts
index 716060df23dad35c9e7ba007d6764e7434517df0..409abd6e1baf707769cd6aa488d8fafaded033fa 100644
--- a/backend/src/queries/currentDelegation.ts
+++ b/backend/src/queries/currentDelegation.ts
@@ -23,3 +23,29 @@ AND NOT EXISTS (
     AND dv2.tx_id > delegation_vote.tx_id
 )
 LIMIT 1;`;
+
+export const getCurrentDelegationWithStakeHexQuery: string = `
+SELECT
+CASE
+    WHEN drep_hash.raw IS NULL THEN NULL
+    ELSE ENCODE(drep_hash.raw, 'hex')
+    END AS drep_raw,
+    drep_hash.view AS drep_view,
+    ENCODE(tx.hash, 'hex')
+FROM
+    delegation_vote
+JOIN
+    tx ON tx.id = delegation_vote.tx_id
+JOIN
+    drep_hash ON drep_hash.id = delegation_vote.drep_hash_id
+JOIN
+    stake_address ON stake_address.id = delegation_vote.addr_id
+WHERE
+    stake_address.view = $1
+AND NOT EXISTS (
+    SELECT *
+    FROM delegation_vote AS dv2
+    WHERE dv2.addr_id = delegation_vote.addr_id
+    AND dv2.tx_id > delegation_vote.tx_id
+)
+LIMIT 1;`;
diff --git a/backend/src/queries/drepDelegatorsWithVotingPower.ts b/backend/src/queries/drepDelegatorsWithVotingPower.ts
index 091faaea4eef877331476d2206f737173ef0216b..45b49ec41657875af19b6b8757631c8eef421c82 100644
--- a/backend/src/queries/drepDelegatorsWithVotingPower.ts
+++ b/backend/src/queries/drepDelegatorsWithVotingPower.ts
@@ -31,6 +31,33 @@ export const getDrepDelegatorsWithVotingPowerQuery = (
     OFFSET ${offset}
 `;
 
+export const getDrepDelegatorsQuery = `
+      WITH latest_delegations AS (
+          SELECT delegation_vote.addr_id, MAX(block.time) AS latest_time
+          FROM drep_hash
+          JOIN delegation_vote ON delegation_vote.drep_hash_id = drep_hash.id
+          JOIN stake_address ON delegation_vote.addr_id = stake_address.id
+          JOIN tx ON delegation_vote.tx_id = tx.id
+          JOIN block ON tx.block_id = block.id
+          WHERE drep_hash.view = $1
+          GROUP BY delegation_vote.addr_id
+      )
+      SELECT sa.view AS stake_address,
+         b.epoch_no AS delegation_epoch,
+         COALESCE(SUM(txo.value), 0) AS voting_power
+      FROM drep_hash AS dh
+             JOIN delegation_vote AS dv ON dh.id = dv.drep_hash_id
+             JOIN stake_address sa ON dv.addr_id = sa.id
+             JOIN tx ON dv.tx_id = tx.id
+             JOIN block b ON tx.block_id = b.id
+             JOIN latest_delegations ld ON dv.addr_id = ld.addr_id
+      AND b.time = ld.latest_time
+      JOIN tx_out txo ON sa.id = txo.stake_address_id AND txo.consumed_by_tx_id IS NULL
+      GROUP BY sa.view,
+           b.epoch_no
+  `;
+  
+
 export const getDrepDelegatorsCountQuery = () => `
     WITH latest_delegations AS (
         SELECT delegation_vote.addr_id, MAX(block.time) AS latest_time
diff --git a/backend/src/queries/drepVotingActivity.ts b/backend/src/queries/drepVotingActivity.ts
index 1531cd3ef351af0a1839fc6d875a1c6615b8d43c..c59efc6d093f49a459a192749d1b075af396984c 100644
--- a/backend/src/queries/drepVotingActivity.ts
+++ b/backend/src/queries/drepVotingActivity.ts
@@ -35,3 +35,41 @@ export const getDrepVotingActivityQuery = `
         AND bk.time::DATE BETWEEN $3::DATE AND $2::DATE
     ORDER BY 
         bk.epoch_no`;
+export const getDrepVotingActivityInTimestampQuery = `
+    SELECT  
+        dh.view, 
+        SUBSTRING(CAST(prop_creation_tx.hash AS TEXT) FROM 3) AS gov_action_proposal_id,
+        prop_creation_bk.time AS prop_inception,
+        gp.type,
+        gp.description,
+        gp.voting_anchor_id,
+        vp.vote::text,
+        ocvd.json AS metadata,
+        bk.time AS time_voted,
+        prop_creation_bk.epoch_no AS proposal_epoch,
+        bk.epoch_no AS voting_epoch,
+        va.url
+    FROM 
+        drep_hash AS dh
+    JOIN 
+        voting_procedure AS vp ON dh.id = vp.drep_voter
+    LEFT JOIN 
+        gov_action_proposal AS gp ON vp.gov_action_proposal_id = gp.id
+    LEFT JOIN 
+        tx AS tx ON vp.tx_id = tx.id
+    LEFT JOIN 
+        tx AS prop_creation_tx ON gp.tx_id = prop_creation_tx.id
+    LEFT JOIN 
+        block AS bk ON tx.block_id = bk.id 
+    LEFT JOIN 
+        block AS prop_creation_bk ON prop_creation_tx.block_id = prop_creation_bk.id
+    LEFT JOIN
+        voting_anchor as va ON gp.voting_anchor_id = va.id
+    LEFT JOIN
+        off_chain_vote_data AS ocvd ON ocvd.voting_anchor_id = va.id
+    WHERE
+        dh.view = $1
+        --$2 earliest range limit, $3 latest range limit
+        AND bk.time BETWEEN $2::timestamptz AND $3::timestamptz
+    ORDER BY 
+        bk.epoch_no`;
diff --git a/backend/src/reactions/reactions.service.ts b/backend/src/reactions/reactions.service.ts
index acffa740f3b96dfe8864cc41e8a5ea3dcecf9e35..cfc8d2a65497497d356cd218e936e8291ba178ea 100644
--- a/backend/src/reactions/reactions.service.ts
+++ b/backend/src/reactions/reactions.service.ts
@@ -1,5 +1,6 @@
 import { Injectable } from '@nestjs/common';
 import { InjectDataSource } from '@nestjs/typeorm';
+import { NotificationsService } from 'src/notifications/notifications.service';
 import { DataSource } from 'typeorm';
 
 @Injectable()
@@ -7,6 +8,7 @@ export class ReactionsService {
   constructor(
     @InjectDataSource('default')
     private voltaireService: DataSource,
+    private notificationsService: NotificationsService,
   ) {}
 
   async getReactions(parentId: number, parentEntity: string) {
@@ -18,16 +20,76 @@ export class ReactionsService {
       .getMany();
     return reactions;
   }
-  async insertReaction(parentId: number, parentEntity: string, type: string, voter: string) {
+  async insertReaction(
+    parentId: number,
+    parentEntity: string,
+    type: string,
+    voter: string,
+  ) {
     const newReaction = this.voltaireService.getRepository('Reaction').create({
       parentId,
       parentEntity,
       type,
       voter,
     });
-    return this.voltaireService.getRepository('Reaction').save(newReaction);
+    const createdRxn = await this.voltaireService
+      .getRepository('Reaction')
+      .save(newReaction);
+    //inform the owner of the reacted to entity
+    let parent;
+    let content;
+    switch (parentEntity) {
+      case 'note':
+        parent = await this.voltaireService
+          .getRepository(parentEntity)
+          .createQueryBuilder(parentEntity)
+          .leftJoinAndSelect('note.author', 'signature')
+          .where('note.id = :parentId', { parentId })
+          .getOne();
+        if (voter !== parent.author?.stakeKey) {
+          content = this.notificationsService.newReactionToNoteNotification(
+            createdRxn.type as any,
+            voter,
+            parent?.author?.voterId,
+            new Date(parent?.createdAt).getTime()
+          );
+          await this.notificationsService.createNotification(
+            content,
+            parent.author?.id,
+          );
+        }
+        break;
+      case 'comment':
+        parent = await this.voltaireService
+          .getRepository(parentEntity)
+          .findOne({ where: { id: parentId } });
+        if (voter !== parent.voter) {
+          content = this.notificationsService.newReactionForCommentNotification(
+            createdRxn.type as any,
+            voter,
+          );
+          const signature = await this.voltaireService
+            .getRepository('Signature')
+            .findOne({ where: { stakeKey: parent.voter } });
+          if (signature) {
+            await this.notificationsService.createNotification(
+              content,
+              signature.id,
+            );
+          }
+        }
+        break;
+      default:
+        break;
+    }
+    return createdRxn;
   }
-  async removeReaction(parentId: number, parentEntity: string, type: string, voter: string) {
+  async removeReaction(
+    parentId: number,
+    parentEntity: string,
+    type: string,
+    voter: string,
+  ) {
     const reaction = await this.voltaireService
       .getRepository('Reaction')
       .createQueryBuilder('reaction')
diff --git a/backend/yarn.lock b/backend/yarn.lock
index bb71370b36d2cf1d63be18e86df6e9813a2bbb61..444873a16df95b9a0b97bd8c200426d23d44b6b1 100644
--- a/backend/yarn.lock
+++ b/backend/yarn.lock
@@ -1052,6 +1052,14 @@
     multer "1.4.4-lts.1"
     tslib "2.6.2"
 
+"@nestjs/schedule@^4.1.1":
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/@nestjs/schedule/-/schedule-4.1.1.tgz#a730cff250ad5db78fe6a1bfc7f12a30856e48df"
+  integrity sha512-VxAnCiU4HP0wWw8IdWAVfsGC/FGjyToNjjUtXDEQL6oj+w/N5QDd2VT9k6d7Jbr8PlZuBZNdWtDKSkH5bZ+RXQ==
+  dependencies:
+    cron "3.1.7"
+    uuid "10.0.0"
+
 "@nestjs/schematics@^10.0.0", "@nestjs/schematics@^10.0.1":
   version "10.1.1"
   resolved "https://registry.yarnpkg.com/@nestjs/schematics/-/schematics-10.1.1.tgz#a67fb178a7ad6025ccc3314910b077ac454fcdf3"
@@ -1333,6 +1341,11 @@
   dependencies:
     "@types/node" "*"
 
+"@types/luxon@~3.4.0":
+  version "3.4.2"
+  resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.4.2.tgz#e4fc7214a420173cea47739c33cdf10874694db7"
+  integrity sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==
+
 "@types/methods@^1.1.4":
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547"
@@ -2396,6 +2409,14 @@ create-require@^1.1.0:
   resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
   integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
 
+cron@3.1.7:
+  version "3.1.7"
+  resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.7.tgz#3423d618ba625e78458fff8cb67001672d49ba0d"
+  integrity sha512-tlBg7ARsAMQLzgwqVxy8AZl/qlTc5nibqYwtNGoCrd+cV+ugI+tvZC1oT/8dFH8W455YrywGykx/KMmAqOr7Jw==
+  dependencies:
+    "@types/luxon" "~3.4.0"
+    luxon "~3.4.0"
+
 cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -4233,6 +4254,11 @@ lru-cache@^6.0.0:
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3"
   integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==
 
+luxon@~3.4.0:
+  version "3.4.4"
+  resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.4.tgz#cf20dc27dc532ba41a169c43fdcc0063601577af"
+  integrity sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==
+
 magic-string@0.30.5:
   version "0.30.5"
   resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9"
@@ -5810,6 +5836,11 @@ utils-merge@1.0.1:
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
   integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
 
+uuid@10.0.0:
+  version "10.0.0"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294"
+  integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==
+
 uuid@9.0.1, uuid@^9.0.0:
   version "9.0.1"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
diff --git a/frontend/package.json b/frontend/package.json
index 0409701dc8ec1bac5c02a15fe2197247ecac4857..832a62181733e0c1b1df289b3f751dc632518138 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -51,6 +51,7 @@
     "axios": "^1.6.7",
     "bech32": "^2.0.0",
     "blakejs": "^1.2.1",
+    "date-fns": "^4.1.0",
     "framer-motion": "^11.1.7",
     "idb": "^8.0.0",
     "js-cookie": "^3.0.5",
diff --git a/frontend/src/app/[locale]/dreps/[drepid]/not-found.tsx b/frontend/src/app/[locale]/dreps/[drepid]/not-found.tsx
index a69326156130e7c57d941430e9ceb1800bf0b7ab..849526dbe836285ae393c10ba8dd6b51d1bdeae5 100644
--- a/frontend/src/app/[locale]/dreps/[drepid]/not-found.tsx
+++ b/frontend/src/app/[locale]/dreps/[drepid]/not-found.tsx
@@ -1,3 +1,4 @@
+'use client'
 import { usePathname } from 'next/navigation';
 import React from 'react';
 
diff --git a/frontend/src/assets/styles/globals.css b/frontend/src/assets/styles/globals.css
index 0a16d4dcbf26823701970d40ba70690266384452..41deb2ca0a023d9ad817170eef3bd83f3770f66b 100644
--- a/frontend/src/assets/styles/globals.css
+++ b/frontend/src/assets/styles/globals.css
@@ -255,4 +255,4 @@ table.dreps-table .drep_always_no_confidence > td {
     border-right: 0;
   }
   
-}
+}
\ No newline at end of file
diff --git a/frontend/src/components/1694.io/TranslationBlock.tsx b/frontend/src/components/1694.io/TranslationBlock.tsx
index 911a00be5eae91d1f086289bb7a2c275be124621..a2be79c3c73182cfe446f16c7673f4acc282dd1e 100644
--- a/frontend/src/components/1694.io/TranslationBlock.tsx
+++ b/frontend/src/components/1694.io/TranslationBlock.tsx
@@ -1,8 +1,5 @@
-import React, { useEffect, useState } from 'react';
-import Link from 'next/link';
-import Button from '../atoms/Button';
-import BecomeADRepButton from './BecomeADRepButton';
-import HoverChip, { HtmlTooltip } from '../atoms/HoverChip';
+import React, {  useState } from 'react';
+import  { HtmlTooltip } from '../atoms/HoverChip';
 import { CopyToClipboard } from 'react-copy-to-clipboard';
 import {
   Accordion,
diff --git a/frontend/src/components/atoms/HoverChip.tsx b/frontend/src/components/atoms/HoverChip.tsx
index 65fcebb3e4a6b5e29e2b948b1f29d8e1e27dce06..3aadbf7f6c566b0b6c18047861e63d5f1bc7f582 100644
--- a/frontend/src/components/atoms/HoverChip.tsx
+++ b/frontend/src/components/atoms/HoverChip.tsx
@@ -1,27 +1,19 @@
-import { useState } from 'react';
-import { Tooltip, TooltipProps, tooltipClasses } from '@mui/material';
-import { CopyToClipboard } from 'react-copy-to-clipboard';
+import { Tooltip, TooltipProps } from '@mui/material';
 import styled from '@emotion/styled';
 
 interface HoverChipProps {
-  icon?: string;
   text?: string;
   handleClick?: () => void;
   position?: 'top' | 'bottom';
-  textToCopy?: string;
   children?: React.ReactElement;
 }
 
 const HoverChip = ({
-  icon,
   text,
   handleClick,
   position = 'top',
-  textToCopy,
   children,
 }: HoverChipProps) => {
-  const [isHovered, setIsHovered] = useState(false);
-
   return (
     <Tooltip
       title={text}
diff --git a/frontend/src/components/atoms/SingleNotification.tsx b/frontend/src/components/atoms/SingleNotification.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7f075440e0a464399963c8ed35049d7863a99f5e
--- /dev/null
+++ b/frontend/src/components/atoms/SingleNotification.tsx
@@ -0,0 +1,88 @@
+import React, { useState } from 'react';
+import {
+  Typography,
+  Box,
+  IconButton,
+  Menu,
+  MenuItem,
+  Checkbox,
+} from '@mui/material';
+import { formatDistanceToNow } from 'date-fns';
+import { Notification } from '../../../types/commonTypes';
+import * as marked from 'marked';
+import HoverChip from './HoverChip';
+
+interface NotificationItemProps {
+  notification: Notification;
+  onMarkAsRead: (id: number) => void;
+  onMarkAsUnread: (id: number) => void;
+}
+
+const NotificationItem: React.FC<NotificationItemProps> = ({
+  notification,
+  onMarkAsRead,
+  onMarkAsUnread,
+}) => {
+  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
+
+  const handleOpenMenu = (event: React.MouseEvent<HTMLElement>) => {
+    setAnchorEl(event.currentTarget);
+  };
+
+  const handleCloseMenu = () => {
+    setAnchorEl(null);
+  };
+
+  const handleAction = (action: 'read' | 'unread') => {
+    handleCloseMenu();
+    switch (action) {
+      case 'read':
+        onMarkAsRead(notification.id);
+        break;
+      case 'unread':
+        onMarkAsUnread(notification.id);
+        break;
+    }
+  };
+
+  return (
+    <Box
+      className="my-0.5 flex items-center justify-between p-2"
+      sx={{
+        opacity: notification.isRead ? '50%' : '100%',
+      }}
+    >
+      <Box className="mr-2 flex flex-grow flex-col">
+        <Typography variant="subtitle2" className="font-bold">
+          {notification.title}
+        </Typography>
+        <p
+          className="parsed-content text-xs text-gray-600"
+          dangerouslySetInnerHTML={{
+            __html: marked.parse(notification.message),
+          }}
+        ></p>
+        <Typography variant="caption" className="text-gray-400">
+          {formatDistanceToNow(new Date(notification.createdAt), {
+            addSuffix: true,
+          })}
+        </Typography>
+      </Box>
+      <IconButton
+        className="self-start"
+        onClick={() => handleAction(notification.isRead ? 'unread' : 'read')}
+      >
+        <HoverChip
+          text={notification.isRead ? 'Mark as unread' : 'Mark as read'}
+          position="bottom"
+        >
+          <Checkbox
+            checked={notification.isRead}
+          />
+        </HoverChip>
+      </IconButton>
+    </Box>
+  );
+};
+
+export default NotificationItem;
diff --git a/frontend/src/components/dreps/notes/SingleNote.tsx b/frontend/src/components/dreps/notes/SingleNote.tsx
index 85203c0890fb864b174c4721b167b62a6583a3ba..ff7379d79b240c505f4c928f1429a827ff0cf8c1 100644
--- a/frontend/src/components/dreps/notes/SingleNote.tsx
+++ b/frontend/src/components/dreps/notes/SingleNote.tsx
@@ -9,7 +9,6 @@ import { z } from 'zod';
 import { SubmitHandler, useForm } from 'react-hook-form';
 import { zodResolver } from '@hookform/resolvers/zod';
 import { postAddComment } from '@/services/requests/postAddComment';
-import * as marked from 'marked';
 import { useGetSingleNoteQuery } from '@/hooks/useGetSingleNoteQuery';
 import { processContent } from '@/lib/ContentProcessor/processContent';
 import MarkdownEditor from '@/components/atoms/MarkdownEditor';
diff --git a/frontend/src/components/molecules/LoginButton.tsx b/frontend/src/components/molecules/LoginButton.tsx
index 9a511e0b044fb17572b8ad7bb60445b4a643ccbc..27edbd7170dfe4b61f4caa503a4b185a58f26b28 100644
--- a/frontend/src/components/molecules/LoginButton.tsx
+++ b/frontend/src/components/molecules/LoginButton.tsx
@@ -22,7 +22,8 @@ const LoginButton = ({
     stakeKeyBech32,
     dRepIDBech32,
   } = useCardano();
-  const { setIsLoggedIn, setLoginModalOpen, drepId } = useDRepContext();
+  const { setIsLoggedIn, setLoginModalOpen, drepId, setSignatureId } =
+    useDRepContext();
   const { addErrorAlert } = useGlobalNotifications();
   const handleLogin = async () => {
     let signature;
@@ -50,12 +51,14 @@ const LoginButton = ({
           key,
           expiry: loginPeriod,
         };
-        const { token } = await userLogin(loginCredentials);
+        const { token, session } = await userLogin(loginCredentials);
+        setSignatureId(session.id);
         setItemToLocalStorage('signatures', { signature, key });
-        setItemToLocalStorage('token', token);
+        setItemToLocalStorage('token_1694', token);
         setIsLoggedIn(true);
         setLoginModalOpen(false);
       }
+      
     } catch (error) {
       console.log(error);
       if (error instanceof Error) {
diff --git a/frontend/src/components/molecules/LoginInfoCard.tsx b/frontend/src/components/molecules/LoginInfoCard.tsx
index 894dae92ce305050db5af9d9b5b444ced408ba8a..53b8c5970a7390a38679cb5fc4c938c935883f60 100644
--- a/frontend/src/components/molecules/LoginInfoCard.tsx
+++ b/frontend/src/components/molecules/LoginInfoCard.tsx
@@ -7,7 +7,7 @@ export const LoginInfoCard = () => {
   const { loginCredentials } = useCardano();
   const { setIsLoggedIn } = useDRepContext();
   const onClickLogout = () => {
-    removeItemFromLocalStorage('token');
+    removeItemFromLocalStorage('token_1694');
     setIsLoggedIn(false);
   };
 
diff --git a/frontend/src/components/molecules/NotificationDrawer.tsx b/frontend/src/components/molecules/NotificationDrawer.tsx
index a64b1e387d970a5e2f60b431ce2c29d8a31eb728..e2cf8083b132d0985df6952d213ca8e93ae9c21b 100644
--- a/frontend/src/components/molecules/NotificationDrawer.tsx
+++ b/frontend/src/components/molecules/NotificationDrawer.tsx
@@ -2,13 +2,19 @@ import React, { useState } from 'react';
 import Menu from '@mui/material/Menu';
 import MenuItem from '@mui/material/MenuItem';
 import Grow from '@mui/material/Grow';
-import { Box } from '@mui/material';
+import { Box, Badge, Divider } from '@mui/material';
 import { useGetUserNotificationQuery } from '@/hooks/useGetUserNotificationQuery';
 import Typography from '@mui/material/Typography';
+import { useDRepContext } from '@/context/drepContext';
+import NotificationItem from '../atoms/SingleNotification';
+import {
+  postMarkNotificationAsRead,
+  postMarkNotificationAsUnread,
+} from '@/services/requests/postNotificationRequests';
 
 export default function NotificationDrawer() {
   const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
-
+  const { signatureId } = useDRepContext();
   const open = Boolean(anchorEl);
   const handleClick = (event: React.MouseEvent<HTMLElement>) => {
     setAnchorEl(event.currentTarget);
@@ -17,11 +23,64 @@ export default function NotificationDrawer() {
   const handleClose = () => {
     setAnchorEl(null);
   };
-  const { notifications: notificationItems = [] } = useGetUserNotificationQuery();
+
+  const { notifications: allNotifications = [], refetch } =
+    useGetUserNotificationQuery({
+      recipientId: signatureId,
+    });
+
+  const inboxNotifications = allNotifications.filter(
+    (n) => !n.isRead && !n.isArchived,
+  );
+
+  const handleMarkAsRead = async (id: number) => {
+    await postMarkNotificationAsRead({ notificationId: String(id) });
+    refetch();
+  };
+  const handleMarkAsUnread = async (id: number) => {
+    await postMarkNotificationAsUnread({ notificationId: String(id) });
+    refetch();
+  };
+
+  const renderNotifications = (notifications: any[]) => {
+    if (notifications.length === 0) {
+      return (
+        <MenuItem disableRipple className="pointer-events-none">
+          <Box className="mb-4 flex flex-col text-wrap py-2 text-complementary-500">
+            {signatureId ? (
+              <>
+                <Typography variant="subtitle2" className="font-bold">
+                  Mempool Clear
+                </Typography>
+                <Typography variant="body1">You're all caught up.</Typography>
+              </>
+            ) : (
+              <Typography variant="body1">
+                Please login to view notifications
+              </Typography>
+            )}
+          </Box>
+        </MenuItem>
+      );
+    }
+    return notifications.map((item) => (
+      <NotificationItem
+        key={item.id}
+        notification={item}
+        onMarkAsRead={handleMarkAsRead}
+        onMarkAsUnread={handleMarkAsUnread}
+      />
+    ));
+  };
 
   return (
     <div>
-      <div className="cursor-pointer">
+      <Badge
+        className="cursor-pointer"
+        badgeContent={inboxNotifications.length || 0}
+        color="warning"
+        max={10}
+      >
         <img
           src="/svgs/bell.svg"
           id="notification-dropdown"
@@ -31,11 +90,11 @@ export default function NotificationDrawer() {
           onClick={handleClick}
           aria-expanded={open ? 'true' : undefined}
         />
-      </div>
+      </Badge>
       <Menu
         id="notification-drawer"
         MenuListProps={{
-          'aria-labelledby': 'notification-drawer',
+          'aria-labelledby': 'notification-dropdown',
         }}
         anchorEl={anchorEl}
         open={open}
@@ -43,7 +102,7 @@ export default function NotificationDrawer() {
         TransitionComponent={Grow}
         anchorOrigin={{
           vertical: 'bottom',
-          horizontal: 'center',
+          horizontal: 'left',
         }}
         transformOrigin={{
           vertical: 'top',
@@ -54,57 +113,22 @@ export default function NotificationDrawer() {
             borderRadius: '0 0 1rem 1rem',
             boxShadow: '1px 2px 11px 0 rgba(0, 18, 61, 0.37)',
             bgcolor: '#F3F5FF',
+            maxHeight: '80vh',
+            width: '20rem',
+            overflow: 'auto',
           },
-          '.MuiMenu-list': { padding: 0 },
+          '.MuiMenu-list': { padding: 1 },
         }}
       >
-        <Box className="w-72">
-          <Box className="flex w-full items-center justify-between p-2">
-            <Typography variant="h4">Notifications</Typography>
-          </Box>
-          {!!notificationItems && (
-            <Box className="relative flex w-full flex-col">
-              {notificationItems.map((item, index) => (
-                <MenuItem
-                  key={index}
-                  onClick={handleClose}
-                  sx={{
-                    '&:hover': {
-                      backgroundColor: '#FFC19D',
-                    },
-                  }}
-                >
-                  <Box className="flex max-w-60 gap-4">
-                    <Box className="flex flex-col text-wrap text-complementary-500">
-                      <p className="p-0 text-base font-normal">{item.label}</p>
-                      <p className="text-xs font-normal leading-4">
-                        {item.text}
-                      </p>
-                    </Box>
-                  </Box>
-                </MenuItem>
-              ))}
-            </Box>
-          )}
-        </Box>
-        {!notificationItems ||
-          (notificationItems.length <= 0 && (
-            <MenuItem
-              onClick={handleClose}
-              sx={{
-                '&:hover': {
-                  backgroundColor: '#FFC19D',
-                },
-              }}
-            >
-              <Box className="mb-4 flex flex-col text-wrap py-2 text-complementary-500">
-                <Typography variant="subtitle2" className="font-bold">
-                  Mempool Clear
-                </Typography>
-                <Typography variant="body1">You're all caught up.</Typography>
-              </Box>
-            </MenuItem>
-          ))}
+        {/* Header */}
+        <MenuItem
+          disabled
+          className="flex w-full items-center justify-between p-1"
+        >
+          <Typography variant="h6">Notifications</Typography>
+        </MenuItem>
+        <Divider />
+        {renderNotifications(allNotifications)}
       </Menu>
     </div>
   );
diff --git a/frontend/src/components/organisms/NewNoteForm.tsx b/frontend/src/components/organisms/NewNoteForm.tsx
index 8c11ade16619e0406835454fb261704a24be51b0..70c3894e9eb0ee68edf7a32daf36d3bb7bfa90ae 100644
--- a/frontend/src/components/organisms/NewNoteForm.tsx
+++ b/frontend/src/components/organisms/NewNoteForm.tsx
@@ -47,7 +47,7 @@ const NewNoteForm = () => {
       }
       setIsLoading(true);
       const stakeAddress = Address.from_bytes(
-        Buffer.from(stakeKey, 'hex'),
+        Buffer.from(stakeKey, 'hex') as any,
       ).to_bech32();
       const { postTag, postText, postTitle, postVisibility } = data;
       const newNote = {
@@ -63,7 +63,7 @@ const NewNoteForm = () => {
       addSuccessAlert('Note Created Successfully!');
       setIsLoading(false);
     } catch (error) {
-      addErrorAlert('Note Creation Failed!');
+      addErrorAlert(String(error?.response?.data?.message) || 'Note Creation Failed!');
       console.log(error);
       setIsLoading(false);
     }
diff --git a/frontend/src/components/organisms/NewProfile.tsx b/frontend/src/components/organisms/NewProfile.tsx
index 8d60acbe1bf7bf2c6f089f4e7643d206245eb910..4834257be3c45734e93f9ee7a7fded07381eeac9 100644
--- a/frontend/src/components/organisms/NewProfile.tsx
+++ b/frontend/src/components/organisms/NewProfile.tsx
@@ -223,7 +223,7 @@ const NewProfile = () => {
       }
 
       const stakeAddress = Address.from_bytes(
-        Buffer.from(stakeKey, 'hex'),
+        Buffer.from(stakeKey, 'hex') as any,
       ).to_bech32();
       const formData: drepInput = {
         signature,
@@ -238,7 +238,7 @@ const NewProfile = () => {
       setNewDrepId(insertedDrep.raw[0].id);
       setCurrentRegistrationStep(2);
       addSuccessAlert('DRep Profile Created Successfully!');
-      setItemToLocalStorage('token', token);
+      setItemToLocalStorage('token_1694', token);
       setItemToLocalStorage('signatures', { signature, key });
       setIsLoggedIn(true);
       router.push(`/dreps/workflow/profile/update/step2`);
diff --git a/frontend/src/context/drepContext.tsx b/frontend/src/context/drepContext.tsx
index fb249d6449f84e71e130da8683d10c99fa7092e9..4bacee3203ae175952d5603b4bd2c43116311b4e 100644
--- a/frontend/src/context/drepContext.tsx
+++ b/frontend/src/context/drepContext.tsx
@@ -15,12 +15,12 @@ import {
   getItemFromLocalStorage,
   removeItemFromLocalStorage,
 } from '@/lib';
-import { processExternalMetadata } from '@/lib/metadataProcessor';
 import { getSingleDRepViaVoterId } from '@/services/requests/getSingleDrepViaVoterId';
 import { getItemFromIndexedDB } from '@/lib/indexedDb';
 import { getDRepRegStatus } from '@/services/requests/getDRepRegStatus';
 import { getDRepMetadata } from '@/services/requests/getDRepMetadata';
 import { blake2bHex } from 'blakejs';
+import { getSession } from '@/services/requests/getSession';
 
 interface DRepContext {
   step1Status: stepStatus['status'];
@@ -29,7 +29,7 @@ interface DRepContext {
   step4Status: stepStatus['status'];
   isLoggedIn: boolean;
   loginModalOpen: boolean;
-  hideCloseButtonOnLoginModal: boolean
+  hideCloseButtonOnLoginModal: boolean;
   isWalletListModalOpen: boolean;
   hideCloseButtonOnWalletListModal: boolean;
   isNotDRepErrorModalOpen: boolean;
@@ -47,7 +47,9 @@ interface DRepContext {
   setCurrentRegistrationStep: React.Dispatch<React.SetStateAction<number>>;
   setIsNotDRepErrorModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
   setIsWalletListModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
-  setHideCloseButtonOnWalletListModal: React.Dispatch<React.SetStateAction<boolean>>;
+  setHideCloseButtonOnWalletListModal: React.Dispatch<
+    React.SetStateAction<boolean>
+  >;
   setCurrentLocale: React.Dispatch<React.SetStateAction<string>>;
   setNewDrepId: React.Dispatch<React.SetStateAction<number>>;
   setLoginModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
@@ -57,6 +59,8 @@ interface DRepContext {
   metadataJsonHash: any;
   setMetadataJsonHash: React.Dispatch<React.SetStateAction<any>>;
   handleRefresh: () => Promise<void>;
+  signatureId: any;
+  setSignatureId: React.Dispatch<React.SetStateAction<any>>;
 }
 
 interface Props {
@@ -73,21 +77,31 @@ DRepContext.displayName = 'DRepContext';
 
 function DRepProvider(props: Props) {
   const [isWalletListModalOpen, setIsWalletListModalOpen] = useState(false);
-  const [hideCloseButtonOnWalletListModal, setHideCloseButtonOnWalletListModal] = useState(false);
+  const [
+    hideCloseButtonOnWalletListModal,
+    setHideCloseButtonOnWalletListModal,
+  ] = useState(false);
   const { sharedState, updateSharedState } = useSharedContext();
   const [isNotDRepErrorModalOpen, setIsNotDRepErrorModalOpen] = useState(false);
   const [metadataJsonLd, setMetadataJsonLd] = useState(null);
+  const [signatureId, setSignatureId] = useState(null);
   const [metadataJsonHash, setMetadataJsonHash] = useState(null);
   const [isDRepRegistered, setIsDRepRegistered] = useState(false);
-  const [currentRegistrationStep, setCurrentRegistrationStep] = useState<currentRegistrationStep['step']>(1);
+  const [currentRegistrationStep, setCurrentRegistrationStep] =
+    useState<currentRegistrationStep['step']>(1);
   const [drepId, setNewDrepId] = useState<number | null>(null);
   const [isLoggedIn, setIsLoggedIn] = useState(false);
   const [loginModalOpen, setLoginModalOpen] = useState(false);
-  const [hideCloseButtonOnLoginModal, setHideCloseButtonOnLoginModal] = useState(false);
-  const [step1Status, setStep1Status] = useState<stepStatus['status']>('pending');
-  const [step2Status, setStep2Status] = useState<stepStatus['status']>('pending');
-  const [step3Status, setStep3Status] = useState<stepStatus['status']>('pending');
-  const [step4Status, setStep4Status] = useState<stepStatus['status']>('pending');
+  const [hideCloseButtonOnLoginModal, setHideCloseButtonOnLoginModal] =
+    useState(false);
+  const [step1Status, setStep1Status] =
+    useState<stepStatus['status']>('pending');
+  const [step2Status, setStep2Status] =
+    useState<stepStatus['status']>('pending');
+  const [step3Status, setStep3Status] =
+    useState<stepStatus['status']>('pending');
+  const [step4Status, setStep4Status] =
+    useState<stepStatus['status']>('pending');
   //will fix later
   const [currentLocale, setCurrentLocale] = useState<string | null>('en');
   useEffect(() => {
@@ -96,12 +110,18 @@ function DRepProvider(props: Props) {
       isNotDRepErrorModalOpen,
       isLoggedIn,
       isLoginModalOpen: loginModalOpen,
-      hideCloseButtonOnLoginModal: hideCloseButtonOnLoginModal
+      hideCloseButtonOnLoginModal: hideCloseButtonOnLoginModal,
     });
-  }, [isWalletListModalOpen, isNotDRepErrorModalOpen, isLoggedIn, loginModalOpen, hideCloseButtonOnLoginModal]);
+  }, [
+    isWalletListModalOpen,
+    isNotDRepErrorModalOpen,
+    isLoggedIn,
+    loginModalOpen,
+    hideCloseButtonOnLoginModal,
+  ]);
   useEffect(() => {
     persistLogin();
-  }, []);
+  }, [sharedState?.stakeKey]);
   useEffect(() => {
     handleDrepProfileCreationState();
   }, [sharedState?.dRepIDBech32]);
@@ -143,7 +163,11 @@ function DRepProvider(props: Props) {
         if (res) {
           metadataJsonLd = res;
           setMetadataJsonLd(res);
-          const jsonHash = blake2bHex(JSON.stringify(metadataJsonLd), undefined, 32);
+          const jsonHash = blake2bHex(
+            JSON.stringify(metadataJsonLd),
+            undefined,
+            32,
+          );
           setMetadataJsonHash(jsonHash);
         }
       } catch (e) {
@@ -171,7 +195,7 @@ function DRepProvider(props: Props) {
 
       if (!metadataJsonLd) return;
       const metadataBody = metadataJsonLd?.body;
-    
+
       if (metadataBody?.givenName || metadataBody?.bio || metadataBody?.email) {
         setStep1Status('success');
       }
@@ -192,8 +216,8 @@ function DRepProvider(props: Props) {
     }
   };
 
-  const persistLogin = () => {
-    const token = getItemFromLocalStorage('token');
+  const persistLogin = async () => {
+    const token = getItemFromLocalStorage('token_1694');
     if (token) {
       const {
         decoded: { exp, ...rest },
@@ -202,15 +226,28 @@ function DRepProvider(props: Props) {
       //check if token is expired
       if (exp < Date.now() / 1000) {
         setIsLoggedIn(false);
-        removeItemFromLocalStorage('token');
+        removeItemFromLocalStorage('token_1694');
+        removeItemFromLocalStorage('signatures');
+        return;
+      }
+      if (!sharedState?.stakeKey) {
+        setIsLoggedIn(true);
+        updateSharedState({ loginCredentials: { signature, key } });
         return;
       }
+      //get session data from backend
+      const sessionData = await getSession({
+        payload: { signature, key, stakeKey: sharedState?.stakeKey },
+      });
+      setSignatureId(sessionData?.id);
       setIsLoggedIn(true);
       updateSharedState({ loginCredentials: { signature, key } });
     }
   };
   const logout = useCallback(async () => {
-    removeItemFromLocalStorage('token');
+    removeItemFromLocalStorage('token_1694');
+    removeItemFromLocalStorage('signatures');
+    setSignatureId(null)
     setIsLoggedIn(false);
   }, []);
 
@@ -220,6 +257,8 @@ function DRepProvider(props: Props) {
       isNotDRepErrorModalOpen,
       currentLocale,
       drepId,
+      signatureId,
+      setSignatureId,
       isLoggedIn,
       step1Status,
       step2Status,
@@ -259,6 +298,7 @@ function DRepProvider(props: Props) {
       currentRegistrationStep,
       currentLocale,
       drepId,
+      signatureId,
       loginModalOpen,
       step1Status,
       step2Status,
@@ -276,7 +316,9 @@ function DRepProvider(props: Props) {
       {props.children}
       {sharedState.isWalletListModalOpen && (
         <div className="blur-container absolute left-0 top-0  z-50 flex h-screen w-full items-center justify-center">
-          <ChooseWalletModal hideCloseButton={hideCloseButtonOnWalletListModal} />
+          <ChooseWalletModal
+            hideCloseButton={hideCloseButtonOnWalletListModal}
+          />
         </div>
       )}
       {sharedState.isNotDRepErrorModalOpen && (
diff --git a/frontend/src/context/sharedContext.tsx b/frontend/src/context/sharedContext.tsx
index 357836a07e2cad73afec28ce1c3f1c90083d4e1c..4a4d68cbf620eabde74c825e412cbefdf854e988 100644
--- a/frontend/src/context/sharedContext.tsx
+++ b/frontend/src/context/sharedContext.tsx
@@ -15,6 +15,7 @@ export function SharedProvider({ children }) {
       key:null
     },
     dRepIDBech32: '',
+    stakeKey: '',
   });
 
   const updateSharedState = useCallback((newState) => {
diff --git a/frontend/src/context/walletContext.tsx b/frontend/src/context/walletContext.tsx
index 4325eb69cb2fee73c92397bd62463fab19a28e1e..32da25f526f2d4f8e3c4d536b4c8f3aef6b0a77e 100644
--- a/frontend/src/context/walletContext.tsx
+++ b/frontend/src/context/walletContext.tsx
@@ -194,7 +194,7 @@ function CardanoProvider(props: Props) {
     try {
       const raw = await enabledApi.getChangeAddress();
       const changeAddress = Address.from_bytes(
-        Buffer.from(raw, 'hex'),
+        Buffer.from(raw, 'hex') as any,
       ).to_bech32();
       setWalletState((prev) => ({ ...prev, changeAddress }));
     } catch (err) {
@@ -205,20 +205,20 @@ function CardanoProvider(props: Props) {
     try {
       const balanceCBORHex = await enabledApi.getBalance();
       const balance = Number(
-        Value.from_bytes(Buffer.from(balanceCBORHex, 'hex')).coin().to_str(),
+        Value.from_bytes(Buffer.from(balanceCBORHex, 'hex') as any)
+          .coin()
+          .to_str(),
       );
       setWalletState((prev) => ({ ...prev, balance }));
     } catch (err) {
       console.log(err);
-    }
-  };
-
+    }}
   const getUsedAddresses = async (enabledApi: CardanoApiWallet) => {
     try {
       const raw = await enabledApi.getUsedAddresses();
       const rawFirst = raw[0];
       const usedAddress = Address.from_bytes(
-        Buffer.from(rawFirst, 'hex'),
+        Buffer.from(rawFirst, 'hex') as any,
       ).to_bech32();
       setWalletState((prev) => ({ ...prev, usedAddress }));
     } catch (err) {
@@ -236,7 +236,7 @@ function CardanoProvider(props: Props) {
 
       for (const rawUtxo of rawUtxos) {
         const utxo = TransactionUnspentOutput.from_bytes(
-          Buffer.from(rawUtxo, 'hex'),
+          Buffer.from(rawUtxo, 'hex') as any,
         );
         const input = utxo.input();
         const txid = Buffer.from(input.transaction_id().to_bytes()).toString(
@@ -328,21 +328,25 @@ function CardanoProvider(props: Props) {
             .catch((e) => {
               throw e.info;
             });
-          
-          // Get the network ID of the connected wallet
-        const network = await enabledApi.getNetworkId();
-        const requiredNetwork = CONFIGURED_NETWORK_ID;
 
-        if (requiredNetwork !== network) {
-          if (requiredNetwork == 1) {
-            addErrorAlert('Mainnet network wallet required, please switch to the mainnet');
-          } else {
-            addErrorAlert('Testnet network wallet required, please switch to the testnet');
+          // Get the network ID of the connected wallet
+          const network = await enabledApi.getNetworkId();
+          const requiredNetwork = CONFIGURED_NETWORK_ID;
+
+          if (requiredNetwork !== network) {
+            if (requiredNetwork == 1) {
+              addErrorAlert(
+                'Mainnet network wallet required, please switch to the mainnet',
+              );
+            } else {
+              addErrorAlert(
+                'Testnet network wallet required, please switch to the testnet',
+              );
+            }
+            setIsEnableLoading(null);
+            setIsEnabling(false);
+            return { status: 'WRONG_NETWORK' };
           }
-          setIsEnableLoading(null);
-          setIsEnabling(false);
-          return { status: 'WRONG_NETWORK' };
-        }
 
           await getChangeAddress(enabledApi);
           await getUsedAddresses(enabledApi);
@@ -353,7 +357,7 @@ function CardanoProvider(props: Props) {
           if (!enabledExtensions.some((item) => item.cip === 95)) {
             throw new Error('errors.walletNoCIP95FunctionsEnabled');
           }
-          
+
           //Check and set wallet balance
           await getBalance(enabledApi);
           // Check and set wallet address
@@ -414,14 +418,14 @@ function CardanoProvider(props: Props) {
           if (savedStakeKey && stakeKeysList.includes(savedStakeKey)) {
             setStakeKey(savedStakeKey);
             const stakeAddress = Address.from_bytes(
-              Buffer.from(savedStakeKey, 'hex'),
+              Buffer.from(savedStakeKey, 'hex') as any,
             ).to_bech32();
             setStakeKeyBech32(stakeAddress);
             stakeKeySet = true;
           } else if (stakeKeysList.length === 1) {
             setStakeKey(stakeKeysList[0]);
             const stakeAddress = Address.from_bytes(
-              Buffer.from(stakeKeysList[0], 'hex'),
+              Buffer.from(stakeKeysList[0], 'hex') as any,
             ).to_bech32();
             setStakeKeyBech32(stakeAddress);
             setItemToLocalStorage(
@@ -441,6 +445,9 @@ function CardanoProvider(props: Props) {
           updateSharedState({
             isWalletListModalOpen: false,
             dRepIDBech32: dRepIDs?.dRepIDBech32 || '',
+            stakeKey: Address.from_bytes(
+              Buffer.from(stakeKeysList[0], 'hex') as any,
+            ).to_bech32(),
           });
           return { status: 'ok', stakeKey: stakeKeySet };
         } catch (e) {
@@ -564,7 +571,7 @@ function CardanoProvider(props: Props) {
         true,
       );
       txVkeyWitnesses = TransactionWitnessSet.from_bytes(
-        Buffer.from(txVkeyWitnesses, 'hex'),
+        Buffer.from(txVkeyWitnesses, 'hex') as any,
       );
       transactionWitnessSet.set_vkeys(txVkeyWitnesses.vkeys());
       const signedTx = Transaction.new(tx.body(), transactionWitnessSet);
@@ -629,7 +636,7 @@ function CardanoProvider(props: Props) {
         true,
       );
       txVkeyWitnesses = TransactionWitnessSet.from_bytes(
-        Buffer.from(txVkeyWitnesses, 'hex'),
+        Buffer.from(txVkeyWitnesses, 'hex') as any,
       );
       transactionWitnessSet.set_vkeys(txVkeyWitnesses.vkeys());
       const signedTx = Transaction.new(tx.body(), transactionWitnessSet);
diff --git a/frontend/src/hooks/useGetUserNotificationQuery.ts b/frontend/src/hooks/useGetUserNotificationQuery.ts
index 31daf8ebfcf90d1c916db9223a60d98444d65ade..954e88fc0fae8bc00f20061d301f9aba570b8874 100644
--- a/frontend/src/hooks/useGetUserNotificationQuery.ts
+++ b/frontend/src/hooks/useGetUserNotificationQuery.ts
@@ -1,12 +1,16 @@
 import { useQuery } from 'react-query';
-import {getUserNotifications} from "@/services/requests/getUserNotifications";
+import { getUserNotifications } from '@/services/requests/getUserNotifications';
 
-export const useGetUserNotificationQuery = () => {
-  const { data, isLoading } = useQuery({
-    queryKey: 'notifications',
-    queryFn: async () =>
-      await getUserNotifications(),
+export const useGetUserNotificationQuery = ({
+  recipientId,
+}: {
+  recipientId: string;
+}) => {
+  const { data, isLoading, refetch } = useQuery({
+    queryKey: ['notifications', recipientId],
+    queryFn: async () => await getUserNotifications({ recipientId }),
+    enabled: !!recipientId,
   });
 
-  return { notifications: data, loading: isLoading };
+  return { notifications: data, loading: isLoading, refetch };
 };
diff --git a/frontend/src/services/requests/getSession.ts b/frontend/src/services/requests/getSession.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb5c21ae8f9a41c9440e1fe6bec6666280dff65d
--- /dev/null
+++ b/frontend/src/services/requests/getSession.ts
@@ -0,0 +1,12 @@
+import axiosInstance from '../axiosInstance';
+type Payload = {
+  stakeKey: string;
+  signature: string;
+  key: string;
+};
+export const getSession = async ({ payload }: { payload: Payload }) => {
+  const response = await axiosInstance.post('auth/session', {
+    payload,
+  });
+  return response.data;
+};
diff --git a/frontend/src/services/requests/getUserNotifications.ts b/frontend/src/services/requests/getUserNotifications.ts
index 7cf25e96db0e1ebff2624f9d96607da123f275f6..5f12c601a842cfa5fffd63cefcee51c7bd729344 100644
--- a/frontend/src/services/requests/getUserNotifications.ts
+++ b/frontend/src/services/requests/getUserNotifications.ts
@@ -1,7 +1,11 @@
+import { Notification } from '../../../types/commonTypes';
 import axiosInstance from '../axiosInstance';
 
-export const getUserNotifications = async () => {
-  const response = await axiosInstance.get(`/notifications` );
-
-  return response.data;
-};
+export const getUserNotifications = async ({
+  recipientId,
+}: {
+  recipientId: string;
+}) => {
+  const response = await axiosInstance.get(`/notifications/${recipientId}/all`);
+  return response.data as Notification[];
+}
diff --git a/frontend/src/services/requests/postNotificationRequests.ts b/frontend/src/services/requests/postNotificationRequests.ts
new file mode 100644
index 0000000000000000000000000000000000000000..23433e39d89b9e9851bab7699aca9cfb953095ed
--- /dev/null
+++ b/frontend/src/services/requests/postNotificationRequests.ts
@@ -0,0 +1,53 @@
+import axiosInstance from '../axiosInstance';
+
+export const postCreateNotification = async ({
+  recipientId,
+  title,
+  message,
+  type,
+  isRead,
+  isArchived,
+  isPersistent,
+}: {
+  recipientId: string;
+  title: string;
+  message: string;
+  type: string;
+  isRead?: boolean;
+  isArchived?: boolean;
+  isPersistent?: boolean;
+}) => {
+  const response = await axiosInstance.post(`/notifications/${recipientId}/new`, {
+    title,
+    message,
+    type,
+    isRead,
+    isArchived,
+    isPersistent,
+  });
+  return response.data;
+};
+
+
+export const postMarkNotificationAsRead = async ({
+  notificationId,
+}: {
+  notificationId: string;
+}) => {
+  const response = await axiosInstance.post(
+    `/notifications/${notificationId}/read`,
+  );
+  return response.data;
+};
+
+
+export const postMarkNotificationAsUnread = async ({
+  notificationId,
+}: {
+  notificationId: string;
+}) => {
+  const response = await axiosInstance.post(
+    `/notifications/${notificationId}/unread`,
+  );
+  return response.data;
+};
diff --git a/frontend/types/commonTypes.ts b/frontend/types/commonTypes.ts
index 7cc8230e831a44f4919d2dee3c4aab79e27d64a6..c4c226003141c34142cfafa2229af6b5480fa9c2 100644
--- a/frontend/types/commonTypes.ts
+++ b/frontend/types/commonTypes.ts
@@ -43,6 +43,19 @@ export type IPFSResponse = {
   ipfs_hash: string;
   size: number;
 };
+export type NotificationType = 'info' | 'warning' | 'error';  
+export type Notification = {
+  id: number;
+  title: string;
+  message: string;
+  type: NotificationType;
+  createdAt: Date;
+  isRead: boolean;
+  isArchived: boolean;
+  deletedAt: Date;
+  isPersistent: boolean;
+  recipient: string;
+};
 export type Metrics = {
   totalRegisteredDReps: number;
   totalActiveDReps: number;
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 03a7ce0a7518fb5065cc750bdb6d8ff58b9f3aba..486563663134a5aef15cd270ba800e7f64224b18 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -4752,6 +4752,11 @@ data-view-byte-offset@^1.0.0:
     es-errors "^1.3.0"
     is-data-view "^1.0.1"
 
+date-fns@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14"
+  integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==
+
 dayjs@^1.10.4:
   version "1.11.10"
   resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz"