diff --git a/apiserver/plane/app/serializers/page.py b/apiserver/plane/app/serializers/page.py
index b69221081f4..1fd2f4d3c84 100644
--- a/apiserver/plane/app/serializers/page.py
+++ b/apiserver/plane/app/serializers/page.py
@@ -54,6 +54,8 @@ def create(self, validated_data):
         labels = validated_data.pop("labels", None)
         project_id = self.context["project_id"]
         owned_by_id = self.context["owned_by_id"]
+        description = self.context["description"]
+        description_binary = self.context["description_binary"]
         description_html = self.context["description_html"]
 
         # Get the workspace id from the project
@@ -62,6 +64,8 @@ def create(self, validated_data):
         # Create the page
         page = Page.objects.create(
             **validated_data,
+            description=description,
+            description_binary=description_binary,
             description_html=description_html,
             owned_by_id=owned_by_id,
             workspace_id=project.workspace_id,
diff --git a/apiserver/plane/app/urls/page.py b/apiserver/plane/app/urls/page.py
index b49f1d4a28d..f7eb7e42429 100644
--- a/apiserver/plane/app/urls/page.py
+++ b/apiserver/plane/app/urls/page.py
@@ -8,6 +8,7 @@
     SubPagesEndpoint,
     PagesDescriptionViewSet,
     PageVersionEndpoint,
+    PageDuplicateEndpoint,
 )
 
 
@@ -78,4 +79,9 @@
         PageVersionEndpoint.as_view(),
         name="page-versions",
     ),
+    path(
+        "workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:page_id>/duplicate/",
+        PageDuplicateEndpoint.as_view(),
+        name="page-duplicate",
+    ),
 ]
diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py
index 581a1065d96..7c1e801f9d0 100644
--- a/apiserver/plane/app/views/__init__.py
+++ b/apiserver/plane/app/views/__init__.py
@@ -155,6 +155,7 @@
     PageLogEndpoint,
     SubPagesEndpoint,
     PagesDescriptionViewSet,
+    PageDuplicateEndpoint,
 )
 from .page.version import PageVersionEndpoint
 
diff --git a/apiserver/plane/app/views/page/base.py b/apiserver/plane/app/views/page/base.py
index 46ce81ce179..8f22845a227 100644
--- a/apiserver/plane/app/views/page/base.py
+++ b/apiserver/plane/app/views/page/base.py
@@ -121,6 +121,8 @@ def create(self, request, slug, project_id):
             context={
                 "project_id": project_id,
                 "owned_by_id": request.user.id,
+                "description": request.data.get("description", {}),
+                "description_binary": request.data.get("description_binary", None),
                 "description_html": request.data.get("description_html", "<p></p>"),
             },
         )
@@ -553,3 +555,33 @@ def partial_update(self, request, slug, project_id, pk):
             return Response({"message": "Updated successfully"})
         else:
             return Response({"error": "No binary data provided"})
+
+
+class PageDuplicateEndpoint(BaseAPIView):
+    @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
+    def post(self, request, slug, project_id, page_id):
+        page = Page.objects.filter(
+            pk=page_id, workspace__slug=slug, projects__id=project_id
+        ).values()
+        new_page_data = list(page)[0]
+        new_page_data.name = f"{new_page_data.name} (Copy)"
+
+        serializer = PageSerializer(
+            data=new_page_data,
+            context={
+                "project_id": project_id,
+                "owned_by_id": request.user.id,
+                "description": new_page_data.description,
+                "description_binary": new_page_data.description_binary,
+                "description_html": new_page_data.description_html,
+            },
+        )
+
+        if serializer.is_valid():
+            serializer.save()
+            # capture the page transaction
+            page_transaction.delay(request.data, None, serializer.data["id"])
+            page = Page.objects.get(pk=serializer.data["id"])
+            serializer = PageDetailSerializer(page)
+            return Response(serializer.data, status=status.HTTP_201_CREATED)
+        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
diff --git a/packages/editor/src/core/constants/document-collaborative-events.ts b/packages/editor/src/core/constants/document-collaborative-events.ts
index 5e79efc7a71..72e8b1dbded 100644
--- a/packages/editor/src/core/constants/document-collaborative-events.ts
+++ b/packages/editor/src/core/constants/document-collaborative-events.ts
@@ -3,4 +3,6 @@ export const DocumentCollaborativeEvents = {
   unlock: { client: "unlocked", server: "unlock" },
   archive: { client: "archived", server: "archive" },
   unarchive: { client: "unarchived", server: "unarchive" },
+  "make-public": { client: "made-public", server: "make-public" },
+  "make-private": { client: "made-private", server: "make-private" },
 } as const;
diff --git a/packages/ui/src/dropdowns/context-menu/item.tsx b/packages/ui/src/dropdowns/context-menu/item.tsx
index 99ef790e3f6..83124392082 100644
--- a/packages/ui/src/dropdowns/context-menu/item.tsx
+++ b/packages/ui/src/dropdowns/context-menu/item.tsx
@@ -36,19 +36,23 @@ export const ContextMenuItem: React.FC<ContextMenuItemProps> = (props) => {
       onMouseEnter={handleActiveItem}
       disabled={item.disabled}
     >
-      {item.icon && <item.icon className={cn("h-3 w-3", item.iconClassName)} />}
-      <div>
-        <h5>{item.title}</h5>
-        {item.description && (
-          <p
-            className={cn("text-custom-text-300 whitespace-pre-line", {
-              "text-custom-text-400": item.disabled,
-            })}
-          >
-            {item.description}
-          </p>
-        )}
-      </div>
+      {item.customContent ?? (
+        <>
+          {item.icon && <item.icon className={cn("h-3 w-3", item.iconClassName)} />}
+          <div>
+            <h5>{item.title}</h5>
+            {item.description && (
+              <p
+                className={cn("text-custom-text-300 whitespace-pre-line", {
+                  "text-custom-text-400": item.disabled,
+                })}
+              >
+                {item.description}
+              </p>
+            )}
+          </div>
+        </>
+      )}
     </button>
   );
 };
diff --git a/packages/ui/src/dropdowns/context-menu/root.tsx b/packages/ui/src/dropdowns/context-menu/root.tsx
index f251696d212..e4265f1007b 100644
--- a/packages/ui/src/dropdowns/context-menu/root.tsx
+++ b/packages/ui/src/dropdowns/context-menu/root.tsx
@@ -11,7 +11,8 @@ import { usePlatformOS } from "../../hooks/use-platform-os";
 
 export type TContextMenuItem = {
   key: string;
-  title: string;
+  customContent?: React.ReactNode;
+  title?: string;
   description?: string;
   icon?: React.FC<any>;
   action: () => void;
diff --git a/packages/ui/src/dropdowns/custom-menu.tsx b/packages/ui/src/dropdowns/custom-menu.tsx
index 39f01d1ed27..f21da438196 100644
--- a/packages/ui/src/dropdowns/custom-menu.tsx
+++ b/packages/ui/src/dropdowns/custom-menu.tsx
@@ -54,7 +54,7 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => {
     if (referenceElement) referenceElement.focus();
   };
   const closeDropdown = () => {
-    isOpen && onMenuClose && onMenuClose();
+    if (isOpen) onMenuClose?.();
     setIsOpen(false);
   };
 
@@ -216,7 +216,7 @@ const MenuItem: React.FC<ICustomMenuItemProps> = (props) => {
           )}
           onClick={(e) => {
             close();
-            onClick && onClick(e);
+            onClick?.(e);
           }}
           disabled={disabled}
         >
diff --git a/web/ce/components/pages/index.ts b/web/ce/components/pages/index.ts
index 6f3d30c9a95..c4131c5f95a 100644
--- a/web/ce/components/pages/index.ts
+++ b/web/ce/components/pages/index.ts
@@ -1,2 +1,3 @@
 export * from "./editor";
+export * from "./modals";
 export * from "./extra-actions";
diff --git a/web/ce/components/pages/modals/index.ts b/web/ce/components/pages/modals/index.ts
new file mode 100644
index 00000000000..da78df1c843
--- /dev/null
+++ b/web/ce/components/pages/modals/index.ts
@@ -0,0 +1 @@
+export * from "./move-page-modal";
diff --git a/web/ce/components/pages/modals/move-page-modal.tsx b/web/ce/components/pages/modals/move-page-modal.tsx
new file mode 100644
index 00000000000..3fac0f6a042
--- /dev/null
+++ b/web/ce/components/pages/modals/move-page-modal.tsx
@@ -0,0 +1,10 @@
+// store types
+import { IPage } from "@/store/pages/page";
+
+export type TMovePageModalProps = {
+  isOpen: boolean;
+  onClose: () => void;
+  page: IPage;
+};
+
+export const MovePageModal: React.FC<TMovePageModalProps> = () => null;
diff --git a/web/core/components/pages/dropdowns/actions.tsx b/web/core/components/pages/dropdowns/actions.tsx
new file mode 100644
index 00000000000..f979d7f43bd
--- /dev/null
+++ b/web/core/components/pages/dropdowns/actions.tsx
@@ -0,0 +1,195 @@
+"use client";
+
+import { useMemo, useState } from "react";
+import { observer } from "mobx-react";
+import {
+  ArchiveRestoreIcon,
+  Copy,
+  ExternalLink,
+  FileOutput,
+  Globe2,
+  Link,
+  Lock,
+  LockKeyhole,
+  LockKeyholeOpen,
+  Trash2,
+} from "lucide-react";
+// plane editor
+import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
+// plane ui
+import { ArchiveIcon, ContextMenu, CustomMenu, TContextMenuItem } from "@plane/ui";
+// components
+import { DeletePageModal } from "@/components/pages";
+// constants
+import { EPageAccess } from "@/constants/page";
+// helpers
+import { cn } from "@/helpers/common.helper";
+// hooks
+import { usePageOperations } from "@/hooks/use-page-operations";
+// plane web components
+import { MovePageModal } from "@/plane-web/components/pages";
+// store types
+import { IPage } from "@/store/pages/page";
+
+export type TPageActions =
+  | "full-screen"
+  | "copy-markdown"
+  | "toggle-lock"
+  | "toggle-access"
+  | "open-in-new-tab"
+  | "copy-link"
+  | "make-a-copy"
+  | "archive-restore"
+  | "delete"
+  | "version-history"
+  | "export"
+  | "move";
+
+type Props = {
+  editorRef?: EditorRefApi | EditorReadOnlyRefApi | null;
+  extraOptions?: (TContextMenuItem & { key: TPageActions })[];
+  optionsOrder: TPageActions[];
+  page: IPage;
+  parentRef?: React.RefObject<HTMLElement>;
+};
+
+export const PageActions: React.FC<Props> = observer((props) => {
+  const { editorRef, extraOptions, optionsOrder, page, parentRef } = props;
+  // states
+  const [deletePageModal, setDeletePageModal] = useState(false);
+  const [movePageModal, setMovePageModal] = useState(false);
+  // page operations
+  const { pageOperations } = usePageOperations({
+    editorRef,
+    page,
+  });
+  // derived values
+  const {
+    access,
+    archived_at,
+    is_locked,
+    canCurrentUserArchivePage,
+    canCurrentUserChangeAccess,
+    canCurrentUserDeletePage,
+    canCurrentUserDuplicatePage,
+    canCurrentUserLockPage,
+    canCurrentUserMovePage,
+  } = page;
+  // menu items
+  const MENU_ITEMS: (TContextMenuItem & { key: TPageActions })[] = useMemo(
+    () => [
+      {
+        key: "toggle-lock",
+        action: pageOperations.toggleLock,
+        title: is_locked ? "Unlock" : "Lock",
+        icon: is_locked ? LockKeyholeOpen : LockKeyhole,
+        shouldRender: canCurrentUserLockPage,
+      },
+      {
+        key: "toggle-access",
+        action: pageOperations.toggleAccess,
+        title: access === EPageAccess.PUBLIC ? "Make private" : "Make public",
+        icon: access === EPageAccess.PUBLIC ? Lock : Globe2,
+        shouldRender: canCurrentUserChangeAccess && !archived_at,
+      },
+      {
+        key: "open-in-new-tab",
+        action: pageOperations.openInNewTab,
+        title: "Open in new tab",
+        icon: ExternalLink,
+        shouldRender: true,
+      },
+      {
+        key: "copy-link",
+        action: pageOperations.copyLink,
+        title: "Copy link",
+        icon: Link,
+        shouldRender: true,
+      },
+      {
+        key: "make-a-copy",
+        action: pageOperations.duplicate,
+        title: "Make a copy",
+        icon: Copy,
+        shouldRender: canCurrentUserDuplicatePage,
+      },
+      {
+        key: "archive-restore",
+        action: pageOperations.toggleArchive,
+        title: !!archived_at ? "Restore" : "Archive",
+        icon: !!archived_at ? ArchiveRestoreIcon : ArchiveIcon,
+        shouldRender: canCurrentUserArchivePage,
+      },
+      {
+        key: "delete",
+        action: () => setDeletePageModal(true),
+        title: "Delete",
+        icon: Trash2,
+        shouldRender: canCurrentUserDeletePage && !!archived_at,
+      },
+
+      {
+        key: "move",
+        action: () => setMovePageModal(true),
+        title: "Move",
+        icon: FileOutput,
+        shouldRender: canCurrentUserMovePage,
+      },
+    ],
+    [
+      access,
+      archived_at,
+      is_locked,
+      canCurrentUserArchivePage,
+      canCurrentUserChangeAccess,
+      canCurrentUserDeletePage,
+      canCurrentUserDuplicatePage,
+      canCurrentUserLockPage,
+      canCurrentUserMovePage,
+      pageOperations,
+    ]
+  );
+  if (extraOptions) {
+    MENU_ITEMS.push(...extraOptions);
+  }
+  // arrange options
+  const arrangedOptions = useMemo(
+    () =>
+      optionsOrder
+        .map((key) => MENU_ITEMS.find((item) => item.key === key))
+        .filter((item) => !!item) as (TContextMenuItem & { key: TPageActions })[],
+    [optionsOrder, MENU_ITEMS]
+  );
+
+  return (
+    <>
+      <MovePageModal isOpen={movePageModal} onClose={() => setMovePageModal(false)} page={page} />
+      <DeletePageModal isOpen={deletePageModal} onClose={() => setDeletePageModal(false)} pageId={page.id ?? ""} />
+      {parentRef && <ContextMenu parentRef={parentRef} items={arrangedOptions} />}
+      <CustomMenu placement="bottom-end" optionsClassName="max-h-[90vh]" ellipsis closeOnSelect>
+        {arrangedOptions.map((item) => {
+          if (item.shouldRender === false) return null;
+          return (
+            <CustomMenu.MenuItem
+              key={item.key}
+              onClick={(e) => {
+                e.preventDefault();
+                e.stopPropagation();
+                item.action?.();
+              }}
+              className={cn("flex items-center gap-2", item.className)}
+              disabled={item.disabled}
+            >
+              {item.customContent ?? (
+                <>
+                  {item.icon && <item.icon className="size-3" />}
+                  {item.title}
+                </>
+              )}
+            </CustomMenu.MenuItem>
+          );
+        })}
+      </CustomMenu>
+    </>
+  );
+});
diff --git a/web/core/components/pages/dropdowns/index.ts b/web/core/components/pages/dropdowns/index.ts
index 16d9c337209..74ebad1d675 100644
--- a/web/core/components/pages/dropdowns/index.ts
+++ b/web/core/components/pages/dropdowns/index.ts
@@ -1,2 +1,2 @@
+export * from "./actions";
 export * from "./edit-information-popover";
-export * from "./quick-actions";
diff --git a/web/core/components/pages/dropdowns/quick-actions.tsx b/web/core/components/pages/dropdowns/quick-actions.tsx
deleted file mode 100644
index 6bed6be2c65..00000000000
--- a/web/core/components/pages/dropdowns/quick-actions.tsx
+++ /dev/null
@@ -1,131 +0,0 @@
-"use client";
-
-import { useState } from "react";
-import { observer } from "mobx-react";
-import { ArchiveRestoreIcon, ExternalLink, Link, Lock, Trash2, UsersRound } from "lucide-react";
-import { ArchiveIcon, ContextMenu, CustomMenu, TContextMenuItem, TOAST_TYPE, setToast } from "@plane/ui";
-// components
-import { DeletePageModal } from "@/components/pages";
-// helpers
-import { copyUrlToClipboard } from "@/helpers/string.helper";
-// store
-import { IPage } from "@/store/pages/page";
-
-type Props = {
-  page: IPage;
-  pageLink: string;
-  parentRef: React.RefObject<HTMLElement>;
-};
-
-export const PageQuickActions: React.FC<Props> = observer((props) => {
-  const { page, pageLink, parentRef } = props;
-  // states
-  const [deletePageModal, setDeletePageModal] = useState(false);
-  // store hooks
-  const {
-    access,
-    archive,
-    archived_at,
-    makePublic,
-    makePrivate,
-    restore,
-    canCurrentUserArchivePage,
-    canCurrentUserChangeAccess,
-    canCurrentUserDeletePage,
-  } = page;
-
-  const handleCopyText = () =>
-    copyUrlToClipboard(pageLink).then(() => {
-      setToast({
-        type: TOAST_TYPE.SUCCESS,
-        title: "Link Copied!",
-        message: "Page link copied to clipboard.",
-      });
-    });
-
-  const handleOpenInNewTab = () => window.open(`/${pageLink}`, "_blank");
-
-  const MENU_ITEMS: TContextMenuItem[] = [
-    {
-      key: "make-public-private",
-      action: async () => {
-        const changedPageType = access === 0 ? "private" : "public";
-
-        try {
-          if (access === 0) await makePrivate();
-          else await makePublic();
-
-          setToast({
-            type: TOAST_TYPE.SUCCESS,
-            title: "Success!",
-            message: `The page has been marked ${changedPageType} and moved to the ${changedPageType} section.`,
-          });
-        } catch (err) {
-          setToast({
-            type: TOAST_TYPE.ERROR,
-            title: "Error!",
-            message: `The page couldn't be marked ${changedPageType}. Please try again.`,
-          });
-        }
-      },
-      title: access === 0 ? "Make private" : "Make public",
-      icon: access === 0 ? Lock : UsersRound,
-      shouldRender: canCurrentUserChangeAccess && !archived_at,
-    },
-    {
-      key: "open-new-tab",
-      action: handleOpenInNewTab,
-      title: "Open in new tab",
-      icon: ExternalLink,
-      shouldRender: true,
-    },
-    {
-      key: "copy-link",
-      action: handleCopyText,
-      title: "Copy link",
-      icon: Link,
-      shouldRender: true,
-    },
-    {
-      key: "archive-restore",
-      action: archived_at ? restore : archive,
-      title: archived_at ? "Restore" : "Archive",
-      icon: archived_at ? ArchiveRestoreIcon : ArchiveIcon,
-      shouldRender: canCurrentUserArchivePage,
-    },
-    {
-      key: "delete",
-      action: () => setDeletePageModal(true),
-      title: "Delete",
-      icon: Trash2,
-      shouldRender: canCurrentUserDeletePage && !!archived_at,
-    },
-  ];
-
-  return (
-    <>
-      <DeletePageModal isOpen={deletePageModal} onClose={() => setDeletePageModal(false)} pageId={page.id ?? ""} />
-      <ContextMenu parentRef={parentRef} items={MENU_ITEMS} />
-      <CustomMenu placement="bottom-end" ellipsis closeOnSelect>
-        {MENU_ITEMS.map((item) => {
-          if (!item.shouldRender) return null;
-          return (
-            <CustomMenu.MenuItem
-              key={item.key}
-              onClick={(e) => {
-                e.preventDefault();
-                e.stopPropagation();
-                item.action();
-              }}
-              className="flex items-center gap-2"
-              disabled={item.disabled}
-            >
-              {item.icon && <item.icon className="h-3 w-3" />}
-              {item.title}
-            </CustomMenu.MenuItem>
-          );
-        })}
-      </CustomMenu>
-    </>
-  );
-});
diff --git a/web/core/components/pages/editor/header/extra-options.tsx b/web/core/components/pages/editor/header/extra-options.tsx
index f21959cd93d..bfc6d35eaf7 100644
--- a/web/core/components/pages/editor/header/extra-options.tsx
+++ b/web/core/components/pages/editor/header/extra-options.tsx
@@ -16,14 +16,12 @@ import useOnlineStatus from "@/hooks/use-online-status";
 import { IPage } from "@/store/pages/page";
 
 type Props = {
-  editorRef: React.RefObject<EditorRefApi>;
-  handleDuplicatePage: () => void;
+  editorRef: EditorRefApi | EditorReadOnlyRefApi | null;
   page: IPage;
-  readOnlyEditorRef: React.RefObject<EditorReadOnlyRefApi>;
 };
 
 export const PageExtraOptions: React.FC<Props> = observer((props) => {
-  const { editorRef, handleDuplicatePage, page, readOnlyEditorRef } = props;
+  const { editorRef, page } = props;
   // derived values
   const {
     archived_at,
@@ -85,12 +83,8 @@ export const PageExtraOptions: React.FC<Props> = observer((props) => {
           iconClassName="text-custom-text-100"
         />
       )}
-      <PageInfoPopover editorRef={isContentEditable ? editorRef.current : readOnlyEditorRef.current} />
-      <PageOptionsDropdown
-        editorRef={isContentEditable ? editorRef.current : readOnlyEditorRef.current}
-        handleDuplicatePage={handleDuplicatePage}
-        page={page}
-      />
+      <PageInfoPopover editorRef={editorRef} />
+      <PageOptionsDropdown editorRef={editorRef} page={page} />
     </div>
   );
 });
diff --git a/web/core/components/pages/editor/header/mobile-root.tsx b/web/core/components/pages/editor/header/mobile-root.tsx
index ac831796cbe..003237d915a 100644
--- a/web/core/components/pages/editor/header/mobile-root.tsx
+++ b/web/core/components/pages/editor/header/mobile-root.tsx
@@ -1,5 +1,5 @@
 import { observer } from "mobx-react";
-import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/editor";
+import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
 // components
 import { Header, EHeaderVariant } from "@plane/ui";
 import { PageExtraOptions, PageSummaryPopover, PageToolbar } from "@/components/pages";
@@ -9,56 +9,34 @@ import { usePageFilters } from "@/hooks/use-page-filters";
 import { IPage } from "@/store/pages/page";
 
 type Props = {
-  editorReady: boolean;
-  editorRef: React.RefObject<EditorRefApi>;
-  handleDuplicatePage: () => void;
+  editorRef: EditorRefApi | EditorReadOnlyRefApi | null;
   page: IPage;
-  readOnlyEditorReady: boolean;
-  readOnlyEditorRef: React.RefObject<EditorReadOnlyRefApi>;
   setSidePeekVisible: (sidePeekState: boolean) => void;
   sidePeekVisible: boolean;
 };
 
 export const PageEditorMobileHeaderRoot: React.FC<Props> = observer((props) => {
-  const {
-    editorReady,
-    editorRef,
-    handleDuplicatePage,
-    page,
-    readOnlyEditorReady,
-    readOnlyEditorRef,
-    setSidePeekVisible,
-    sidePeekVisible,
-  } = props;
+  const { editorRef, page, setSidePeekVisible, sidePeekVisible } = props;
   // derived values
   const { isContentEditable } = page;
   // page filters
   const { isFullWidth } = usePageFilters();
 
-  if (!editorRef.current && !readOnlyEditorRef.current) return null;
-
   return (
     <>
       <Header variant={EHeaderVariant.SECONDARY}>
         <div className="flex-shrink-0 my-auto">
           <PageSummaryPopover
-            editorRef={isContentEditable ? editorRef.current : readOnlyEditorRef.current}
+            editorRef={editorRef}
             isFullWidth={isFullWidth}
             sidePeekVisible={sidePeekVisible}
             setSidePeekVisible={setSidePeekVisible}
           />
         </div>
-        <PageExtraOptions
-          editorRef={editorRef}
-          handleDuplicatePage={handleDuplicatePage}
-          page={page}
-          readOnlyEditorRef={readOnlyEditorRef}
-        />
+        <PageExtraOptions editorRef={editorRef} page={page} />
       </Header>
       <Header variant={EHeaderVariant.TERNARY}>
-        {(editorReady || readOnlyEditorReady) && isContentEditable && editorRef.current && (
-          <PageToolbar editorRef={editorRef?.current} />
-        )}
+        {isContentEditable && editorRef && <PageToolbar editorRef={editorRef as EditorRefApi} />}
       </Header>
     </>
   );
diff --git a/web/core/components/pages/editor/header/options-dropdown.tsx b/web/core/components/pages/editor/header/options-dropdown.tsx
index ff0987a9dc2..3793eee9d28 100644
--- a/web/core/components/pages/editor/header/options-dropdown.tsx
+++ b/web/core/components/pages/editor/header/options-dropdown.tsx
@@ -1,29 +1,18 @@
 "use client";
 
-import { useState } from "react";
+import { useMemo, useState } from "react";
 import { observer } from "mobx-react";
-import { useParams, useRouter } from "next/navigation";
-import {
-  ArchiveRestoreIcon,
-  ArrowUpToLine,
-  Clipboard,
-  Copy,
-  History,
-  Link,
-  Lock,
-  LockOpen,
-  LucideIcon,
-} from "lucide-react";
+import { useRouter } from "next/navigation";
+import { ArrowUpToLine, Clipboard, History } from "lucide-react";
 // document editor
 import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
 // ui
-import { ArchiveIcon, CustomMenu, type ISvgIcons, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui";
+import { TContextMenuItem, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui";
 // components
-import { ExportPageModal } from "@/components/pages";
+import { ExportPageModal, PageActions, TPageActions } from "@/components/pages";
 // helpers
-import { copyTextToClipboard, copyUrlToClipboard } from "@/helpers/string.helper";
+import { copyTextToClipboard } from "@/helpers/string.helper";
 // hooks
-import { useCollaborativePageActions } from "@/hooks/use-collaborative-page-actions";
 import { usePageFilters } from "@/hooks/use-page-filters";
 import { useQueryParams } from "@/hooks/use-query-params";
 // store
@@ -31,123 +20,74 @@ import { IPage } from "@/store/pages/page";
 
 type Props = {
   editorRef: EditorRefApi | EditorReadOnlyRefApi | null;
-  handleDuplicatePage: () => void;
   page: IPage;
 };
 
 export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
-  const { editorRef, handleDuplicatePage, page } = props;
+  const { editorRef, page } = props;
+  // states
+  const [isExportModalOpen, setIsExportModalOpen] = useState(false);
   // router
   const router = useRouter();
   // store values
-  const {
-    name,
-    archived_at,
-    is_locked,
-    id,
-    canCurrentUserArchivePage,
-    canCurrentUserDuplicatePage,
-    canCurrentUserLockPage,
-  } = page;
-  // states
-  const [isExportModalOpen, setIsExportModalOpen] = useState(false);
-  // store hooks
-  const { workspaceSlug, projectId } = useParams();
+  const { name } = page;
   // page filters
   const { isFullWidth, handleFullWidth } = usePageFilters();
   // update query params
   const { updateQueryParams } = useQueryParams();
-  // collaborative actions
-  const { executeCollaborativeAction } = useCollaborativePageActions(editorRef, page);
-
   // menu items list
-  const MENU_ITEMS: {
-    key: string;
-    action: () => void;
-    label: string;
-    icon: LucideIcon | React.FC<ISvgIcons>;
-    shouldRender: boolean;
-  }[] = [
-    {
-      key: "copy-markdown",
-      action: () => {
-        if (!editorRef) return;
-        copyTextToClipboard(editorRef.getMarkDown()).then(() =>
-          setToast({
-            type: TOAST_TYPE.SUCCESS,
-            title: "Success!",
-            message: "Markdown copied to clipboard.",
-          })
-        );
+  const EXTRA_MENU_OPTIONS: (TContextMenuItem & { key: TPageActions })[] = useMemo(
+    () => [
+      {
+        key: "full-screen",
+        action: () => handleFullWidth(!isFullWidth),
+        customContent: (
+          <>
+            Full width
+            <ToggleSwitch value={isFullWidth} onChange={() => {}} />
+          </>
+        ),
+        className: "flex items-center justify-between gap-2",
       },
-      label: "Copy markdown",
-      icon: Clipboard,
-      shouldRender: true,
-    },
-    {
-      key: "copy-page-link",
-      action: () => {
-        const pageLink = projectId
-          ? `${workspaceSlug?.toString()}/projects/${projectId?.toString()}/pages/${id}`
-          : `${workspaceSlug?.toString()}/pages/${id}`;
-        copyUrlToClipboard(pageLink).then(() =>
-          setToast({
-            type: TOAST_TYPE.SUCCESS,
-            title: "Success!",
-            message: "Page link copied to clipboard.",
-          })
-        );
+      {
+        key: "copy-markdown",
+        action: () => {
+          if (!editorRef) return;
+          copyTextToClipboard(editorRef.getMarkDown()).then(() =>
+            setToast({
+              type: TOAST_TYPE.SUCCESS,
+              title: "Success!",
+              message: "Markdown copied to clipboard.",
+            })
+          );
+        },
+        title: "Copy markdown",
+        icon: Clipboard,
+        shouldRender: true,
       },
-      label: "Copy page link",
-      icon: Link,
-      shouldRender: true,
-    },
-    {
-      key: "make-a-copy",
-      action: handleDuplicatePage,
-      label: "Make a copy",
-      icon: Copy,
-      shouldRender: canCurrentUserDuplicatePage,
-    },
-    {
-      key: "lock-unlock-page",
-      action: is_locked
-        ? () => executeCollaborativeAction({ type: "sendMessageToServer", message: "unlock" })
-        : () => executeCollaborativeAction({ type: "sendMessageToServer", message: "lock" }),
-      label: is_locked ? "Unlock page" : "Lock page",
-      icon: is_locked ? LockOpen : Lock,
-      shouldRender: canCurrentUserLockPage,
-    },
-    {
-      key: "archive-restore-page",
-      action: archived_at
-        ? () => executeCollaborativeAction({ type: "sendMessageToServer", message: "unarchive" })
-        : () => executeCollaborativeAction({ type: "sendMessageToServer", message: "archive" }),
-      label: archived_at ? "Restore page" : "Archive page",
-      icon: archived_at ? ArchiveRestoreIcon : ArchiveIcon,
-      shouldRender: canCurrentUserArchivePage,
-    },
-    {
-      key: "version-history",
-      action: () => {
-        // add query param, version=current to the route
-        const updatedRoute = updateQueryParams({
-          paramsToAdd: { version: "current" },
-        });
-        router.push(updatedRoute);
+      {
+        key: "version-history",
+        action: () => {
+          // add query param, version=current to the route
+          const updatedRoute = updateQueryParams({
+            paramsToAdd: { version: "current" },
+          });
+          router.push(updatedRoute);
+        },
+        title: "Version history",
+        icon: History,
+        shouldRender: true,
       },
-      label: "Version history",
-      icon: History,
-      shouldRender: true,
-    },
-    {
-      key: "export",
-      action: () => setIsExportModalOpen(true),
-      label: "Export",
-      icon: ArrowUpToLine,
-      shouldRender: true,
-    },
-  ];
+      {
+        key: "export",
+        action: () => setIsExportModalOpen(true),
+        title: "Export",
+        icon: ArrowUpToLine,
+        shouldRender: true,
+      },
+    ],
+    [editorRef, handleFullWidth, isFullWidth, router, updateQueryParams]
+  );
 
   return (
     <>
@@ -157,24 +97,23 @@ export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
         onClose={() => setIsExportModalOpen(false)}
         pageTitle={name ?? ""}
       />
-      <CustomMenu maxHeight="lg" placement="bottom-start" verticalEllipsis closeOnSelect>
-        <CustomMenu.MenuItem
-          className="hidden md:flex w-full items-center justify-between gap-2"
-          onClick={() => handleFullWidth(!isFullWidth)}
-        >
-          Full width
-          <ToggleSwitch value={isFullWidth} onChange={() => {}} />
-        </CustomMenu.MenuItem>
-        {MENU_ITEMS.map((item) => {
-          if (!item.shouldRender) return null;
-          return (
-            <CustomMenu.MenuItem key={item.key} onClick={item.action} className="flex items-center gap-2">
-              <item.icon className="h-3 w-3" />
-              {item.label}
-            </CustomMenu.MenuItem>
-          );
-        })}
-      </CustomMenu>
+      <PageActions
+        editorRef={editorRef}
+        extraOptions={EXTRA_MENU_OPTIONS}
+        optionsOrder={[
+          "full-screen",
+          "copy-markdown",
+          "copy-link",
+          "toggle-lock",
+          "make-a-copy",
+          "move",
+          "archive-restore",
+          "delete",
+          "version-history",
+          "export",
+        ]}
+        page={page}
+      />
     </>
   );
 });
diff --git a/web/core/components/pages/editor/header/root.tsx b/web/core/components/pages/editor/header/root.tsx
index 9640f4e43b6..c0dd1d3fd2f 100644
--- a/web/core/components/pages/editor/header/root.tsx
+++ b/web/core/components/pages/editor/header/root.tsx
@@ -13,7 +13,6 @@ import { IPage } from "@/store/pages/page";
 type Props = {
   editorReady: boolean;
   editorRef: React.RefObject<EditorRefApi>;
-  handleDuplicatePage: () => void;
   page: IPage;
   readOnlyEditorReady: boolean;
   readOnlyEditorRef: React.RefObject<EditorReadOnlyRefApi>;
@@ -22,22 +21,16 @@ type Props = {
 };
 
 export const PageEditorHeaderRoot: React.FC<Props> = observer((props) => {
-  const {
-    editorReady,
-    editorRef,
-    handleDuplicatePage,
-    page,
-    readOnlyEditorReady,
-    readOnlyEditorRef,
-    setSidePeekVisible,
-    sidePeekVisible,
-  } = props;
+  const { editorReady, editorRef, page, readOnlyEditorReady, readOnlyEditorRef, setSidePeekVisible, sidePeekVisible } =
+    props;
   // derived values
   const { isContentEditable } = page;
   // page filters
   const { isFullWidth } = usePageFilters();
+  // derived values
+  const resolvedEditorRef = isContentEditable ? editorRef.current : readOnlyEditorRef.current;
 
-  if (!editorRef.current && !readOnlyEditorRef.current) return null;
+  if (!resolvedEditorRef) return null;
 
   return (
     <>
@@ -62,20 +55,11 @@ export const PageEditorHeaderRoot: React.FC<Props> = observer((props) => {
             <PageToolbar editorRef={editorRef?.current} />
           )}
         </Header.LeftItem>
-        <PageExtraOptions
-          editorRef={editorRef}
-          handleDuplicatePage={handleDuplicatePage}
-          page={page}
-          readOnlyEditorRef={readOnlyEditorRef}
-        />
+        <PageExtraOptions editorRef={resolvedEditorRef} page={page} />
       </Header>
       <div className="md:hidden">
         <PageEditorMobileHeaderRoot
-          editorRef={editorRef}
-          readOnlyEditorRef={readOnlyEditorRef}
-          editorReady={editorReady}
-          readOnlyEditorReady={readOnlyEditorReady}
-          handleDuplicatePage={handleDuplicatePage}
+          editorRef={resolvedEditorRef}
           page={page}
           sidePeekVisible={sidePeekVisible}
           setSidePeekVisible={setSidePeekVisible}
diff --git a/web/core/components/pages/editor/page-root.tsx b/web/core/components/pages/editor/page-root.tsx
index ff1f3519e93..6cc353a709a 100644
--- a/web/core/components/pages/editor/page-root.tsx
+++ b/web/core/components/pages/editor/page-root.tsx
@@ -3,14 +3,9 @@ import { observer } from "mobx-react";
 import { useSearchParams } from "next/navigation";
 // editor
 import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
-// types
-import { TPage } from "@plane/types";
-// ui
-import { setToast, TOAST_TYPE } from "@plane/ui";
 // components
 import { PageEditorHeaderRoot, PageEditorBody, PageVersionsOverlay, PagesVersionEditor } from "@/components/pages";
 // hooks
-import { useProjectPages } from "@/hooks/store";
 import { useAppRouter } from "@/hooks/use-app-router";
 import { usePageFallback } from "@/hooks/use-page-fallback";
 import { useQueryParams } from "@/hooks/use-query-params";
@@ -42,10 +37,8 @@ export const PageRoot = observer((props: TPageRootProps) => {
   const router = useAppRouter();
   // search params
   const searchParams = useSearchParams();
-  // store hooks
-  const { createPage } = useProjectPages();
   // derived values
-  const { access, description_html, name, isContentEditable, updateDescription } = page;
+  const { isContentEditable, updateDescription } = page;
   // page fallback
   usePageFallback({
     editorRef,
@@ -59,26 +52,6 @@ export const PageRoot = observer((props: TPageRootProps) => {
   // update query params
   const { updateQueryParams } = useQueryParams();
 
-  const handleCreatePage = async (payload: Partial<TPage>) => await createPage(payload);
-
-  const handleDuplicatePage = async () => {
-    const formData: Partial<TPage> = {
-      name: "Copy of " + name,
-      description_html: editorRef.current?.getDocument().html ?? description_html ?? "<p></p>",
-      access,
-    };
-
-    await handleCreatePage(formData)
-      .then((res) => router.push(`/${workspaceSlug}/projects/${projectId}/pages/${res?.id}`))
-      .catch(() =>
-        setToast({
-          type: TOAST_TYPE.ERROR,
-          title: "Error!",
-          message: "Page could not be duplicated. Please try again later.",
-        })
-      );
-  };
-
   const version = searchParams.get("version");
   useEffect(() => {
     if (!version) {
@@ -135,7 +108,6 @@ export const PageRoot = observer((props: TPageRootProps) => {
       <PageEditorHeaderRoot
         editorReady={editorReady}
         editorRef={editorRef}
-        handleDuplicatePage={handleDuplicatePage}
         page={page}
         readOnlyEditorReady={readOnlyEditorReady}
         readOnlyEditorRef={readOnlyEditorRef}
diff --git a/web/core/components/pages/list/block-item-action.tsx b/web/core/components/pages/list/block-item-action.tsx
index 740b44c814b..38d1b4e8370 100644
--- a/web/core/components/pages/list/block-item-action.tsx
+++ b/web/core/components/pages/list/block-item-action.tsx
@@ -4,60 +4,34 @@ import React, { FC } from "react";
 import { observer } from "mobx-react";
 import { Earth, Info, Lock, Minus } from "lucide-react";
 // ui
-import { Avatar, FavoriteStar, TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
+import { Avatar, FavoriteStar, Tooltip } from "@plane/ui";
 // components
-import { PageQuickActions } from "@/components/pages/dropdowns";
+import { PageActions } from "@/components/pages";
 // helpers
 import { renderFormattedDate } from "@/helpers/date-time.helper";
 import { getFileURL } from "@/helpers/file.helper";
 // hooks
 import { useMember, usePage } from "@/hooks/store";
+import { usePageOperations } from "@/hooks/use-page-operations";
 
 type Props = {
-  workspaceSlug: string;
-  projectId: string;
   pageId: string;
   parentRef: React.RefObject<HTMLElement>;
 };
 
 export const BlockItemAction: FC<Props> = observer((props) => {
-  const { workspaceSlug, projectId, pageId, parentRef } = props;
+  const { pageId, parentRef } = props;
   // store hooks
   const page = usePage(pageId);
   const { getUserDetails } = useMember();
+  // page operations
+  const { pageOperations } = usePageOperations({
+    page,
+  });
   // derived values
-  const {
-    access,
-    created_at,
-    is_favorite,
-    owned_by,
-    canCurrentUserFavoritePage,
-    addToFavorites,
-    removePageFromFavorites,
-  } = page;
+  const { access, created_at, is_favorite, owned_by, canCurrentUserFavoritePage } = page;
   const ownerDetails = owned_by ? getUserDetails(owned_by) : undefined;
 
-  // handlers
-  const handleFavorites = () => {
-    if (is_favorite) {
-      removePageFromFavorites().then(() =>
-        setToast({
-          type: TOAST_TYPE.SUCCESS,
-          title: "Success!",
-          message: "Page removed from favorites.",
-        })
-      );
-    } else {
-      addToFavorites().then(() =>
-        setToast({
-          type: TOAST_TYPE.SUCCESS,
-          title: "Success!",
-          message: "Page added to favorites.",
-        })
-      );
-    }
-  };
-
   return (
     <>
       {/* page details */}
@@ -87,17 +61,25 @@ export const BlockItemAction: FC<Props> = observer((props) => {
           onClick={(e) => {
             e.preventDefault();
             e.stopPropagation();
-            handleFavorites();
+            pageOperations.toggleFavorite();
           }}
           selected={is_favorite}
         />
       )}
 
       {/* quick actions dropdown */}
-      <PageQuickActions
-        parentRef={parentRef}
+      <PageActions
+        optionsOrder={[
+          "toggle-lock",
+          "toggle-access",
+          "open-in-new-tab",
+          "copy-link",
+          "make-a-copy",
+          "archive-restore",
+          "delete",
+        ]}
         page={page}
-        pageLink={`${workspaceSlug}/projects/${projectId}/pages/${pageId}`}
+        parentRef={parentRef}
       />
     </>
   );
diff --git a/web/core/components/pages/list/block.tsx b/web/core/components/pages/list/block.tsx
index abb373a6495..dbe1e3486d3 100644
--- a/web/core/components/pages/list/block.tsx
+++ b/web/core/components/pages/list/block.tsx
@@ -40,9 +40,7 @@ export const PageListBlock: FC<TPageListBlock> = observer((props) => {
       }
       title={getPageName(name)}
       itemLink={`/${workspaceSlug}/projects/${projectId}/pages/${pageId}`}
-      actionableItems={
-        <BlockItemAction workspaceSlug={workspaceSlug} projectId={projectId} pageId={pageId} parentRef={parentRef} />
-      }
+      actionableItems={<BlockItemAction pageId={pageId} parentRef={parentRef} />}
       isMobile={isMobile}
       parentRef={parentRef}
     />
diff --git a/web/core/hooks/use-collaborative-page-actions.tsx b/web/core/hooks/use-collaborative-page-actions.tsx
index 6ec9f799050..cd89607d644 100644
--- a/web/core/hooks/use-collaborative-page-actions.tsx
+++ b/web/core/hooks/use-collaborative-page-actions.tsx
@@ -14,7 +14,13 @@ type CollaborativeActionEvent =
   | { type: "sendMessageToServer"; message: TDocumentEventsServer }
   | { type: "receivedMessageFromServer"; message: TDocumentEventsClient };
 
-export const useCollaborativePageActions = (editorRef: EditorRefApi | EditorReadOnlyRefApi | null, page: IPage) => {
+type Props = {
+  editorRef?: EditorRefApi | EditorReadOnlyRefApi | null;
+  page: IPage;
+};
+
+export const useCollaborativePageActions = (props: Props) => {
+  const { editorRef, page } = props;
   // currentUserAction local state to track if the current action is being processed, a
   // local action is basically the action performed by the current user to avoid double operations
   const [currentActionBeingProcessed, setCurrentActionBeingProcessed] = useState<TDocumentEventsClient | null>(null);
@@ -37,6 +43,14 @@ export const useCollaborativePageActions = (editorRef: EditorRefApi | EditorRead
         execute: (shouldSync) => page.restore(shouldSync),
         errorMessage: "Page could not be restored. Please try again later.",
       },
+      [DocumentCollaborativeEvents["make-public"].client]: {
+        execute: (shouldSync) => page.makePublic(shouldSync),
+        errorMessage: "Page could not be made public. Please try again later.",
+      },
+      [DocumentCollaborativeEvents["make-private"].client]: {
+        execute: (shouldSync) => page.makePrivate(shouldSync),
+        errorMessage: "Page could not be made private. Please try again later.",
+      },
     }),
     [page]
   );
@@ -64,6 +78,7 @@ export const useCollaborativePageActions = (editorRef: EditorRefApi | EditorRead
   );
 
   useEffect(() => {
+    if (!editorRef) return;
     if (currentActionBeingProcessed) {
       const serverEventName = getServerEventName(currentActionBeingProcessed);
       if (serverEventName) {
@@ -73,9 +88,12 @@ export const useCollaborativePageActions = (editorRef: EditorRefApi | EditorRead
   }, [currentActionBeingProcessed, editorRef]);
 
   useEffect(() => {
-    const realTimeStatelessMessageListener = editorRef?.listenToRealTimeUpdate();
+    if (!editorRef) return;
 
+    const realTimeStatelessMessageListener = editorRef?.listenToRealTimeUpdate();
+    console.log(realTimeStatelessMessageListener);
     const handleStatelessMessage = (message: { payload: TDocumentEventsClient }) => {
+      console.log("aaa", message);
       if (currentActionBeingProcessed === message.payload) {
         setCurrentActionBeingProcessed(null);
         return;
diff --git a/web/core/hooks/use-page-operations.ts b/web/core/hooks/use-page-operations.ts
new file mode 100644
index 00000000000..7990252a6b5
--- /dev/null
+++ b/web/core/hooks/use-page-operations.ts
@@ -0,0 +1,207 @@
+import { useMemo } from "react";
+import { useParams } from "next/navigation";
+// plane editor
+import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
+// plane ui
+import { setToast, TOAST_TYPE } from "@plane/ui";
+// helpers
+import { copyUrlToClipboard } from "@/helpers/string.helper";
+// hooks
+import { useCollaborativePageActions } from "@/hooks/use-collaborative-page-actions";
+// store types
+import { IPage } from "@/store/pages/page";
+
+export type TPageOperations = {
+  toggleLock: () => void;
+  toggleAccess: () => void;
+  toggleFavorite: () => void;
+  openInNewTab: () => void;
+  copyLink: () => void;
+  duplicate: () => void;
+  toggleArchive: () => void;
+};
+
+type Props = {
+  editorRef?: EditorRefApi | EditorReadOnlyRefApi | null;
+  page: IPage;
+};
+
+export const usePageOperations = (
+  props: Props
+): {
+  pageOperations: TPageOperations;
+} => {
+  const { page } = props;
+  // params
+  const { workspaceSlug, projectId } = useParams();
+  // derived values
+  const {
+    access,
+    addToFavorites,
+    archived_at,
+    duplicate,
+    id,
+    is_favorite,
+    is_locked,
+    makePrivate,
+    makePublic,
+    removePageFromFavorites,
+  } = page;
+  // collaborative actions
+  const { executeCollaborativeAction } = useCollaborativePageActions(props);
+  // page operations
+  const pageOperations: TPageOperations = useMemo(() => {
+    const pageLink = projectId ? `${workspaceSlug}/projects/${projectId}/pages/${id}` : `${workspaceSlug}/pages/${id}`;
+
+    return {
+      copyLink: () => {
+        copyUrlToClipboard(pageLink).then(() => {
+          setToast({
+            type: TOAST_TYPE.SUCCESS,
+            title: "Link Copied!",
+            message: "Page link copied to clipboard.",
+          });
+        });
+      },
+      duplicate: async () => {
+        try {
+          await duplicate();
+          setToast({
+            type: TOAST_TYPE.SUCCESS,
+            title: "Success!",
+            message: "Page duplicated successfully.",
+          });
+        } catch {
+          setToast({
+            type: TOAST_TYPE.ERROR,
+            title: "Error!",
+            message: "Page could not be duplicated. Please try again later.",
+          });
+        }
+      },
+      move: async () => {},
+      openInNewTab: () => window.open(`/${pageLink}`, "_blank"),
+      toggleAccess: async () => {
+        const changedPageType = access === 0 ? "private" : "public";
+        try {
+          if (access === 0) await makePrivate();
+          else await makePublic();
+
+          setToast({
+            type: TOAST_TYPE.SUCCESS,
+            title: "Success!",
+            message: `The page has been marked ${changedPageType} and moved to the ${changedPageType} section.`,
+          });
+        } catch {
+          setToast({
+            type: TOAST_TYPE.ERROR,
+            title: "Error!",
+            message: `The page couldn't be marked ${changedPageType}. Please try again.`,
+          });
+        }
+      },
+      toggleArchive: async () => {
+        if (archived_at) {
+          try {
+            await executeCollaborativeAction({ type: "sendMessageToServer", message: "unarchive" });
+            setToast({
+              type: TOAST_TYPE.SUCCESS,
+              title: "Success!",
+              message: "Page restored successfully.",
+            });
+          } catch {
+            setToast({
+              type: TOAST_TYPE.ERROR,
+              title: "Error!",
+              message: "Page could not be restored. Please try again later.",
+            });
+          }
+        } else {
+          try {
+            await executeCollaborativeAction({ type: "sendMessageToServer", message: "archive" });
+            setToast({
+              type: TOAST_TYPE.SUCCESS,
+              title: "Success!",
+              message: "Page archived successfully.",
+            });
+          } catch {
+            setToast({
+              type: TOAST_TYPE.ERROR,
+              title: "Error!",
+              message: "Page could not be archived. Please try again later.",
+            });
+          }
+        }
+      },
+      toggleFavorite: () => {
+        if (is_favorite) {
+          removePageFromFavorites().then(() =>
+            setToast({
+              type: TOAST_TYPE.SUCCESS,
+              title: "Success!",
+              message: "Page removed from favorites.",
+            })
+          );
+        } else {
+          addToFavorites().then(() =>
+            setToast({
+              type: TOAST_TYPE.SUCCESS,
+              title: "Success!",
+              message: "Page added to favorites.",
+            })
+          );
+        }
+      },
+      toggleLock: async () => {
+        if (is_locked) {
+          try {
+            await executeCollaborativeAction({ type: "sendMessageToServer", message: "unlock" });
+            setToast({
+              type: TOAST_TYPE.SUCCESS,
+              title: "Success!",
+              message: "Page unlocked successfully.",
+            });
+          } catch {
+            setToast({
+              type: TOAST_TYPE.ERROR,
+              title: "Error!",
+              message: "Page could not be unlocked. Please try again later.",
+            });
+          }
+        } else {
+          try {
+            await executeCollaborativeAction({ type: "sendMessageToServer", message: "lock" });
+            setToast({
+              type: TOAST_TYPE.SUCCESS,
+              title: "Success!",
+              message: "Page locked successfully.",
+            });
+          } catch {
+            setToast({
+              type: TOAST_TYPE.ERROR,
+              title: "Error!",
+              message: "Page could not be locked. Please try again later.",
+            });
+          }
+        }
+      },
+    };
+  }, [
+    access,
+    addToFavorites,
+    archived_at,
+    duplicate,
+    executeCollaborativeAction,
+    id,
+    is_favorite,
+    is_locked,
+    makePrivate,
+    makePublic,
+    projectId,
+    removePageFromFavorites,
+    workspaceSlug,
+  ]);
+  return {
+    pageOperations,
+  };
+};
diff --git a/web/core/services/page/project-page.service.ts b/web/core/services/page/project-page.service.ts
index 00d9401a69a..b0583742eda 100644
--- a/web/core/services/page/project-page.service.ts
+++ b/web/core/services/page/project-page.service.ts
@@ -158,4 +158,12 @@ export class ProjectPageService extends APIService {
         throw error;
       });
   }
+
+  async duplicate(workspaceSlug: string, projectId: string, pageId: string): Promise<TPage> {
+    return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/duplicate/`)
+      .then((response) => response?.data)
+      .catch((error) => {
+        throw error?.response?.data;
+      });
+  }
 }
diff --git a/web/core/store/pages/page.ts b/web/core/store/pages/page.ts
index d609cab6498..383e6d8ef19 100644
--- a/web/core/store/pages/page.ts
+++ b/web/core/store/pages/page.ts
@@ -23,6 +23,7 @@ export interface IPage extends TPage {
   canCurrentUserArchivePage: boolean;
   canCurrentUserDeletePage: boolean;
   canCurrentUserFavoritePage: boolean;
+  canCurrentUserMovePage: boolean;
   isContentEditable: boolean;
   // helpers
   oldName: string;
@@ -32,8 +33,8 @@ export interface IPage extends TPage {
   update: (pageData: Partial<TPage>) => Promise<TPage | undefined>;
   updateTitle: (title: string) => void;
   updateDescription: (document: TDocumentPayload) => Promise<void>;
-  makePublic: () => Promise<void>;
-  makePrivate: () => Promise<void>;
+  makePublic: (shouldSync?: boolean) => Promise<void>;
+  makePrivate: (shouldSync?: boolean) => Promise<void>;
   lock: (shouldSync?: boolean) => Promise<void>;
   unlock: (shouldSync?: boolean) => Promise<void>;
   archive: (shouldSync?: boolean) => Promise<void>;
@@ -41,6 +42,7 @@ export interface IPage extends TPage {
   updatePageLogo: (logo_props: TLogoProps) => Promise<void>;
   addToFavorites: () => Promise<void>;
   removePageFromFavorites: () => Promise<void>;
+  duplicate: () => Promise<void>;
 }
 
 export class Page implements IPage {
@@ -133,6 +135,7 @@ export class Page implements IPage {
       canCurrentUserArchivePage: computed,
       canCurrentUserDeletePage: computed,
       canCurrentUserFavoritePage: computed,
+      canCurrentUserMovePage: computed,
       isContentEditable: computed,
       // actions
       update: action,
@@ -147,6 +150,7 @@ export class Page implements IPage {
       updatePageLogo: action,
       addToFavorites: action,
       removePageFromFavorites: action,
+      duplicate: action,
     });
 
     this.pageService = new ProjectPageService();
@@ -296,6 +300,19 @@ export class Page implements IPage {
     return !!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER;
   }
 
+  /**
+   * @description returns true if the current logged in user can move the page
+   */
+  get canCurrentUserMovePage() {
+    const { workspaceSlug, projectId } = this.store.router;
+
+    const currentUserProjectRole = this.store.user.permission.projectPermissionsByWorkspaceSlugAndProjectId(
+      workspaceSlug?.toString() || "",
+      projectId?.toString() || ""
+    );
+    return this.isCurrentUserOwner || currentUserProjectRole === EUserPermissions.ADMIN;
+  }
+
   /**
    * @description returns true if the page can be edited
    */
@@ -398,44 +415,48 @@ export class Page implements IPage {
   /**
    * @description make the page public
    */
-  makePublic = async () => {
+  makePublic = async (shouldSync: boolean = true) => {
     const { workspaceSlug, projectId } = this.store.router;
     if (!workspaceSlug || !projectId || !this.id) return undefined;
 
     const pageAccess = this.access;
     runInAction(() => (this.access = EPageAccess.PUBLIC));
 
-    try {
-      await this.pageService.updateAccess(workspaceSlug, projectId, this.id, {
-        access: EPageAccess.PUBLIC,
-      });
-    } catch (error) {
-      runInAction(() => {
-        this.access = pageAccess;
-      });
-      throw error;
+    if (shouldSync) {
+      try {
+        await this.pageService.updateAccess(workspaceSlug, projectId, this.id, {
+          access: EPageAccess.PUBLIC,
+        });
+      } catch (error) {
+        runInAction(() => {
+          this.access = pageAccess;
+        });
+        throw error;
+      }
     }
   };
 
   /**
    * @description make the page private
    */
-  makePrivate = async () => {
+  makePrivate = async (shouldSync: boolean = true) => {
     const { workspaceSlug, projectId } = this.store.router;
     if (!workspaceSlug || !projectId || !this.id) return undefined;
 
     const pageAccess = this.access;
     runInAction(() => (this.access = EPageAccess.PRIVATE));
 
-    try {
-      await this.pageService.updateAccess(workspaceSlug, projectId, this.id, {
-        access: EPageAccess.PRIVATE,
-      });
-    } catch (error) {
-      runInAction(() => {
-        this.access = pageAccess;
-      });
-      throw error;
+    if (shouldSync) {
+      try {
+        await this.pageService.updateAccess(workspaceSlug, projectId, this.id, {
+          access: EPageAccess.PRIVATE,
+        });
+      } catch (error) {
+        runInAction(() => {
+          this.access = pageAccess;
+        });
+        throw error;
+      }
     }
   };
 
@@ -588,4 +609,13 @@ export class Page implements IPage {
       throw error;
     });
   };
+
+  /**
+   * @description duplicate the page
+   */
+  duplicate = async () => {
+    const { workspaceSlug, projectId } = this.store.router;
+    if (!workspaceSlug || !projectId || !this.id) return undefined;
+    await this.pageService.duplicate(workspaceSlug, projectId, this.id);
+  };
 }
diff --git a/web/core/store/pages/project-page.store.ts b/web/core/store/pages/project-page.store.ts
index 7cb8f0014cc..9b10caa1374 100644
--- a/web/core/store/pages/project-page.store.ts
+++ b/web/core/store/pages/project-page.store.ts
@@ -18,6 +18,8 @@ type TLoader = "init-loader" | "mutation-loader" | undefined;
 
 type TError = { title: string; description: string };
 
+export const ROLE_PERMISSIONS_TO_CREATE_PAGE = [EUserPermissions.ADMIN, EUserPermissions.MEMBER];
+
 export interface IProjectPageStore {
   // observables
   loader: TLoader;
@@ -42,6 +44,7 @@ export interface IProjectPageStore {
   getPageById: (workspaceSlug: string, projectId: string, pageId: string) => Promise<TPage | undefined>;
   createPage: (pageData: Partial<TPage>) => Promise<TPage | undefined>;
   removePage: (pageId: string) => Promise<void>;
+  movePage: (workspaceSlug: string, projectId: string, pageId: string, newProjectId: string) => Promise<void>;
 }
 
 export class ProjectPageStore implements IProjectPageStore {
@@ -76,6 +79,7 @@ export class ProjectPageStore implements IProjectPageStore {
       getPageById: action,
       createPage: action,
       removePage: action,
+      movePage: action,
     });
     this.rootStore = store;
     // service
@@ -107,7 +111,7 @@ export class ProjectPageStore implements IProjectPageStore {
       workspaceSlug?.toString() || "",
       projectId?.toString() || ""
     );
-    return !!currentUserProjectRole && currentUserProjectRole >= EUserPermissions.MEMBER;
+    return !!currentUserProjectRole && ROLE_PERMISSIONS_TO_CREATE_PAGE.includes(currentUserProjectRole);
   }
 
   /**
@@ -292,4 +296,13 @@ export class ProjectPageStore implements IProjectPageStore {
       throw error;
     }
   };
+
+  /**
+   * @description move a page to a new project
+   * @param {string} workspaceSlug
+   * @param {string} projectId
+   * @param {string} pageId
+   * @param {string} newProjectId
+   */
+  movePage = async (workspaceSlug: string, projectId: string, pageId: string, newProjectId: string) => {};
 }