diff --git a/frontend/.vscode/tasks.json b/frontend/.vscode/tasks.json
index 305fb5bf38..8bce9eb24b 100644
--- a/frontend/.vscode/tasks.json
+++ b/frontend/.vscode/tasks.json
@@ -257,7 +257,7 @@
       "label": "AF: Tauri UI Dev",
       "type": "shell",
       "isBackground": true,
-      "command": "pnpm sync:i18n && pnpm run dev",
+      "command": "pnpm run tauri:dev",
       "options": {
         "cwd": "${workspaceFolder}/appflowy_tauri"
       }
@@ -297,6 +297,6 @@
       "options": {
         "cwd": "${workspaceFolder}/appflowy_flutter"
       }
-    },
+    }
   ]
 }
\ No newline at end of file
diff --git a/frontend/appflowy_tauri/package.json b/frontend/appflowy_tauri/package.json
index b1e6f8e53d..4cc3b04a1b 100644
--- a/frontend/appflowy_tauri/package.json
+++ b/frontend/appflowy_tauri/package.json
@@ -51,7 +51,7 @@
     "quill-delta": "^5.1.0",
     "react": "^18.2.0",
     "react-beautiful-dnd": "^13.1.1",
-    "react-calendar": "^4.1.0",
+    "react-big-calendar": "^1.8.5",
     "react-color": "^2.19.3",
     "react-datepicker": "^4.23.0",
     "react-dom": "^18.2.0",
diff --git a/frontend/appflowy_tauri/pnpm-lock.yaml b/frontend/appflowy_tauri/pnpm-lock.yaml
index cc90341993..18b6eedbb7 100644
--- a/frontend/appflowy_tauri/pnpm-lock.yaml
+++ b/frontend/appflowy_tauri/pnpm-lock.yaml
@@ -1,9 +1,5 @@
 lockfileVersion: '6.0'
 
-settings:
-  autoInstallPeers: true
-  excludeLinksFromLockfile: false
-
 dependencies:
   '@emoji-mart/data':
     specifier: ^1.1.2
@@ -104,9 +100,9 @@ dependencies:
   react-beautiful-dnd:
     specifier: ^13.1.1
     version: 13.1.1(react-dom@18.2.0)(react@18.2.0)
-  react-calendar:
-    specifier: ^4.1.0
-    version: 4.2.1(react-dom@18.2.0)(react@18.2.0)
+  react-big-calendar:
+    specifier: ^1.8.5
+    version: 1.8.5(react-dom@18.2.0)(react@18.2.0)
   react-color:
     specifier: ^2.19.3
     version: 2.19.3(react@18.2.0)
@@ -1882,6 +1878,15 @@ packages:
     engines: {node: '>=14'}
     dev: false
 
+  /@restart/hooks@0.4.15(react@18.2.0):
+    resolution: {integrity: sha512-cZFXYTxbpzYcieq/mBwSyXgqnGMHoBVh3J7MU0CCoIB4NRZxV9/TuwTBAaLMqpNhC3zTPMCgkQ5Ey07L02Xmcw==}
+    peerDependencies:
+      react: '>=16.8.0'
+    dependencies:
+      dequal: 2.0.3
+      react: 18.2.0
+    dev: false
+
   /@rollup/pluginutils@5.0.2:
     resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
     engines: {node: '>=14.0.0'}
@@ -2302,14 +2307,9 @@ packages:
       '@types/lodash': 4.14.194
     dev: true
 
-  /@types/lodash.memoize@4.1.7:
-    resolution: {integrity: sha512-lGN7WeO4vO6sICVpf041Q7BX/9k1Y24Zo3FY0aUezr1QlKznpjzsDk3T3wvH8ofYzoK0QupN9TWcFAFZlyPwQQ==}
-    dependencies:
-      '@types/lodash': 4.14.194
-    dev: false
-
   /@types/lodash@4.14.194:
     resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==}
+    dev: true
 
   /@types/lodash@4.14.202:
     resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==}
@@ -2477,6 +2477,10 @@ packages:
     resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==}
     dev: true
 
+  /@types/warning@3.0.3:
+    resolution: {integrity: sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==}
+    dev: false
+
   /@types/yargs-parser@21.0.0:
     resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==}
 
@@ -2631,10 +2635,6 @@ packages:
       - supports-color
     dev: true
 
-  /@wojtekmaj/date-utils@1.1.3:
-    resolution: {integrity: sha512-rHrDuTl1cx5LYo8F4K4HVauVjwzx4LwrKfEk4br4fj4nK8JjJZ8IG6a6pBHkYmPLBQHCOEDwstb0WNXMGsmdOw==}
-    dev: false
-
   /abab@2.0.6:
     resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
     dev: true
@@ -3232,6 +3232,10 @@ packages:
       whatwg-url: 11.0.0
     dev: true
 
+  /date-arithmetic@4.1.0:
+    resolution: {integrity: sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg==}
+    dev: false
+
   /date-fns@2.30.0:
     resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
     engines: {node: '>=0.11'}
@@ -3291,6 +3295,11 @@ packages:
     engines: {node: '>=0.4.0'}
     dev: true
 
+  /dequal@2.0.3:
+    resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+    engines: {node: '>=6'}
+    dev: false
+
   /derive-valtio@0.1.0(valtio@1.12.1):
     resolution: {integrity: sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==}
     peerDependencies:
@@ -3916,13 +3925,6 @@ packages:
       get-intrinsic: 1.2.1
     dev: true
 
-  /get-user-locale@2.2.1:
-    resolution: {integrity: sha512-3814zipTZ2MvczOcppEXB3jXu+0HWwj5WmPI6//SeCnUIUaRXu7W4S54eQZTEPadlMZefE+jAlPOn+zY3tD4Qw==}
-    dependencies:
-      '@types/lodash.memoize': 4.1.7
-      lodash.memoize: 4.1.2
-    dev: false
-
   /glob-parent@5.1.2:
     resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
     engines: {node: '>= 6'}
@@ -3958,6 +3960,10 @@ packages:
       once: 1.4.0
       path-is-absolute: 1.0.1
 
+  /globalize@0.1.1:
+    resolution: {integrity: sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==}
+    dev: false
+
   /globals@11.12.0:
     resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
     engines: {node: '>=4'}
@@ -4175,6 +4181,12 @@ packages:
       side-channel: 1.0.4
     dev: true
 
+  /invariant@2.2.4:
+    resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
+    dependencies:
+      loose-envify: 1.4.0
+    dev: false
+
   /is-arguments@1.1.1:
     resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
     engines: {node: '>= 0.4'}
@@ -5039,6 +5051,7 @@ packages:
 
   /lodash.memoize@4.1.2:
     resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
+    dev: true
 
   /lodash.merge@4.6.2:
     resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
@@ -5070,6 +5083,11 @@ packages:
     dependencies:
       yallist: 4.0.0
 
+  /luxon@3.4.4:
+    resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==}
+    engines: {node: '>=12'}
+    dev: false
+
   /magic-string@0.27.0:
     resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
     engines: {node: '>=12'}
@@ -5108,6 +5126,10 @@ packages:
     resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
     dev: false
 
+  /memoize-one@6.0.0:
+    resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
+    dev: false
+
   /merge-stream@2.0.0:
     resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
 
@@ -5154,6 +5176,16 @@ packages:
     hasBin: true
     dev: true
 
+  /moment-timezone@0.5.44:
+    resolution: {integrity: sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==}
+    dependencies:
+      moment: 2.30.1
+    dev: false
+
+  /moment@2.30.1:
+    resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+    dev: false
+
   /ms@2.1.2:
     resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
 
@@ -5692,19 +5724,30 @@ packages:
       - react-native
     dev: false
 
-  /react-calendar@4.2.1(react-dom@18.2.0)(react@18.2.0):
-    resolution: {integrity: sha512-T5oKXD+KLy/g6bmJJkZ7E9wj0iRMesWMZcrC7q2kI6ybOsu9NlPQx8uXJzG4A4C3Sh5Xi0deznyzWIVsUpF8tA==}
+  /react-big-calendar@1.8.5(react-dom@18.2.0)(react@18.2.0):
+    resolution: {integrity: sha512-cra8WPfoTSQthFfqxi0k9xm/Shv5jWSw19LkNzpSJcnQhP6XGes/eJjd8P8g/iwaJjXIWPpg3+HB5wO5wabRyA==}
     peerDependencies:
-      react: ^16.8.0 || ^17.0.0 || ^18.0.0
-      react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+      react: ^16.14.0 || ^17 || ^18
+      react-dom: ^16.14.0 || ^17 || ^18
     dependencies:
-      '@types/react': 18.2.6
-      '@wojtekmaj/date-utils': 1.1.3
+      '@babel/runtime': 7.23.4
       clsx: 1.2.1
-      get-user-locale: 2.2.1
+      date-arithmetic: 4.1.0
+      dayjs: 1.11.9
+      dom-helpers: 5.2.1
+      globalize: 0.1.1
+      invariant: 2.2.4
+      lodash: 4.17.21
+      lodash-es: 4.17.21
+      luxon: 3.4.4
+      memoize-one: 6.0.0
+      moment: 2.30.1
+      moment-timezone: 0.5.44
       prop-types: 15.8.1
       react: 18.2.0
       react-dom: 18.2.0(react@18.2.0)
+      react-overlays: 5.2.1(react-dom@18.2.0)(react@18.2.0)
+      uncontrollable: 7.2.1(react@18.2.0)
     dev: false
 
   /react-color@2.19.3(react@18.2.0):
@@ -5826,6 +5869,10 @@ packages:
       react: 18.2.0
     dev: false
 
+  /react-lifecycles-compat@3.0.4:
+    resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
+    dev: false
+
   /react-onclickoutside@6.13.0(react-dom@18.2.0)(react@18.2.0):
     resolution: {integrity: sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==}
     peerDependencies:
@@ -5836,6 +5883,24 @@ packages:
       react-dom: 18.2.0(react@18.2.0)
     dev: false
 
+  /react-overlays@5.2.1(react-dom@18.2.0)(react@18.2.0):
+    resolution: {integrity: sha512-GLLSOLWr21CqtJn8geSwQfoJufdt3mfdsnIiQswouuQ2MMPns+ihZklxvsTDKD3cR2tF8ELbi5xUsvqVhR6WvA==}
+    peerDependencies:
+      react: '>=16.3.0'
+      react-dom: '>=16.3.0'
+    dependencies:
+      '@babel/runtime': 7.23.4
+      '@popperjs/core': 2.11.8
+      '@restart/hooks': 0.4.15(react@18.2.0)
+      '@types/warning': 3.0.3
+      dom-helpers: 5.2.1
+      prop-types: 15.8.1
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+      uncontrollable: 7.2.1(react@18.2.0)
+      warning: 4.0.3
+    dev: false
+
   /react-popper@2.3.0(@popperjs/core@2.11.8)(react-dom@18.2.0)(react@18.2.0):
     resolution: {integrity: sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==}
     peerDependencies:
@@ -6780,6 +6845,18 @@ packages:
       which-boxed-primitive: 1.0.2
     dev: true
 
+  /uncontrollable@7.2.1(react@18.2.0):
+    resolution: {integrity: sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==}
+    peerDependencies:
+      react: '>=15.0.0'
+    dependencies:
+      '@babel/runtime': 7.23.4
+      '@types/react': 18.2.6
+      invariant: 2.2.4
+      react: 18.2.0
+      react-lifecycles-compat: 3.0.4
+    dev: false
+
   /universalify@0.2.0:
     resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
     engines: {node: '>= 4.0.0'}
@@ -7119,3 +7196,7 @@ packages:
   /yocto-queue@0.1.0:
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
diff --git a/frontend/appflowy_tauri/src/appflowy_app/AppMain.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/AppMain.hooks.ts
index ea052d869a..cd61b2108d 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/AppMain.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/AppMain.hooks.ts
@@ -1,31 +1,39 @@
 import { useAppDispatch, useAppSelector } from '$app/stores/store';
 import { useCallback, useEffect, useMemo } from 'react';
-import { UserSettingController } from '$app/stores/effects/user/user_setting_controller';
 import { currentUserActions } from '$app_reducers/current-user/slice';
 import { Theme as ThemeType, ThemeMode } from '$app/stores/reducers/current-user/slice';
 import { createTheme } from '@mui/material/styles';
 import { getDesignTokens } from '$app/utils/mui';
 import { useTranslation } from 'react-i18next';
+import { ThemeModePB } from '@/services/backend';
+import { UserService } from '$app/application/user/user.service';
 
 export function useUserSetting() {
   const dispatch = useAppDispatch();
   const { i18n } = useTranslation();
-  const currentUser = useAppSelector((state) => state.currentUser);
-  const userSettingController = useMemo(() => {
-    if (!currentUser?.id) return;
-    const controller = new UserSettingController(currentUser.id);
 
-    return controller;
-  }, [currentUser?.id]);
+  const handleSystemThemeChange = useCallback(() => {
+    const mode = window.matchMedia('(prefers-color-scheme: dark)').matches ? ThemeMode.Dark : ThemeMode.Light;
+
+    dispatch(currentUserActions.setUserSetting({ themeMode: mode }));
+  }, [dispatch]);
 
   const loadUserSetting = useCallback(async () => {
-    if (!userSettingController) return;
-    const settings = await userSettingController.getAppearanceSetting();
+    const settings = await UserService.getAppearanceSetting();
 
     if (!settings) return;
     dispatch(currentUserActions.setUserSetting(settings));
+
+    if (settings.themeMode === ThemeModePB.System) {
+      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
+
+      handleSystemThemeChange();
+
+      mediaQuery.addEventListener('change', handleSystemThemeChange);
+    }
+
     await i18n.changeLanguage(settings.language);
-  }, [dispatch, i18n, userSettingController]);
+  }, [dispatch, handleSystemThemeChange, i18n]);
 
   useEffect(() => {
     void loadUserSetting();
@@ -35,12 +43,26 @@ export function useUserSetting() {
     return state.currentUser.userSetting || {};
   });
 
+  useEffect(() => {
+    const html = document.documentElement;
+
+    html?.setAttribute('data-dark-mode', String(themeMode === ThemeMode.Dark));
+    html?.setAttribute('data-theme', themeType);
+  }, [themeType, themeMode]);
+
+  useEffect(() => {
+    return () => {
+      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
+
+      mediaQuery.removeEventListener('change', handleSystemThemeChange);
+    };
+  }, [dispatch, handleSystemThemeChange]);
+
   const muiTheme = useMemo(() => createTheme(getDesignTokens(themeMode)), [themeMode]);
 
   return {
     muiTheme,
     themeMode,
     themeType,
-    userSettingController,
   };
 }
diff --git a/frontend/appflowy_tauri/src/appflowy_app/AppMain.tsx b/frontend/appflowy_tauri/src/appflowy_app/AppMain.tsx
index f5e5359888..c418791461 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/AppMain.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/AppMain.tsx
@@ -1,44 +1,26 @@
 import React from 'react';
 import { Route, Routes } from 'react-router-dom';
 import { ProtectedRoutes } from '$app/components/auth/ProtectedRoutes';
-import { AllIcons } from '$app/components/tests/AllIcons';
-import { ColorPalette } from '$app/components/tests/ColorPalette';
-import { TestAPI } from '$app/components/tests/TestAPI';
-import { BoardPage } from '$app/views/BoardPage';
 import { DatabasePage } from '$app/views/DatabasePage';
-import { LoginPage } from '$app/views/LoginPage';
-import { GetStarted } from '$app/components/auth/GetStarted/GetStarted';
-import { SignUpPage } from '$app/views/SignUpPage';
-import { ConfirmAccountPage } from '$app/views/ConfirmAccountPage';
+
 import { ThemeProvider } from '@mui/material';
 import { useUserSetting } from '$app/AppMain.hooks';
-import { UserSettingControllerContext } from '$app/components/_shared/app-hooks/useUserSettingControllerContext';
 import TrashPage from '$app/views/TrashPage';
 import DocumentPage from '$app/views/DocumentPage';
 
 function AppMain() {
-  const { muiTheme, userSettingController } = useUserSetting();
+  const { muiTheme } = useUserSetting();
 
   return (
-    <UserSettingControllerContext.Provider value={userSettingController}>
-      <ThemeProvider theme={muiTheme}>
-        <Routes>
-          <Route path={'/'} element={<ProtectedRoutes />}>
-            <Route path={'/page/all-icons'} element={<AllIcons />} />
-            <Route path={'/page/colors'} element={<ColorPalette />} />
-            <Route path={'/page/api-test'} element={<TestAPI />} />
-            <Route path={'/page/document/:id'} element={<DocumentPage />} />
-            <Route path={'/page/board/:id'} element={<BoardPage />} />
-            <Route path={'/page/grid/:id'} element={<DatabasePage />} />
-            <Route path={'/trash'} id={'trash'} element={<TrashPage />} />
-          </Route>
-          <Route path={'/auth/login'} element={<LoginPage />}></Route>
-          <Route path={'/auth/getStarted'} element={<GetStarted />}></Route>
-          <Route path={'/auth/signUp'} element={<SignUpPage />}></Route>
-          <Route path={'/auth/confirm-account'} element={<ConfirmAccountPage />}></Route>
-        </Routes>
-      </ThemeProvider>
-    </UserSettingControllerContext.Provider>
+    <ThemeProvider theme={muiTheme}>
+      <Routes>
+        <Route path={'/'} element={<ProtectedRoutes />}>
+          <Route path={'/page/document/:id'} element={<DocumentPage />} />
+          <Route path={'/page/grid/:id'} element={<DatabasePage />} />
+          <Route path={'/trash'} id={'trash'} element={<TrashPage />} />
+        </Route>
+      </Routes>
+    </ThemeProvider>
   );
 }
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_listeners.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_listeners.ts
similarity index 94%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_listeners.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_listeners.ts
index 0bdfcba241..c5c94daebc 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_listeners.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_listeners.ts
@@ -1,4 +1,4 @@
-import { Database } from '$app/components/database/application';
+import { Database } from '$app/application/database';
 import { getCell } from './cell_service';
 
 export function didDeleteCells({ database, rowId, fieldId }: { database: Database; rowId?: string; fieldId?: string }) {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_service.ts
similarity index 98%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_service.ts
index 16cd8a1b64..c1ca8d7583 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_service.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_service.ts
@@ -5,7 +5,7 @@ import {
   ChecklistCellDataChangesetPB,
   DateChangesetPB,
   FieldType,
-} from '@/services/backend';
+} from '../../../../services/backend';
 import {
   DatabaseEventGetCell,
   DatabaseEventUpdateCell,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_types.ts
similarity index 95%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_types.ts
index b8cc81b20b..4633e2b2fe 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/cell_types.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/cell/cell_types.ts
@@ -6,11 +6,8 @@ import {
   SelectOptionCellDataPB,
   TimestampCellDataPB,
   URLCellDataPB,
-} from '@/services/backend';
-import {
-  SelectOption,
-  pbToSelectOption,
-} from '$app/components/database/application/field/select_option/select_option_types';
+} from '../../../../services/backend';
+import { SelectOption, pbToSelectOption } from '../field/select_option/select_option_types';
 
 export interface Cell {
   rowId: string;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/cell/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/cell/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/cell/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/database/database_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/database/database_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/database/database_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/database/database_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/database/database_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/database/database_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/database/database_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/database/database_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/database/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/database/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/database/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/database/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/database_view/database_view_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/database_view/database_view_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/database_view/database_view_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/database_view/database_view_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/database_view/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/database_view/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/database_view/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/database_view/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_listeners.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_listeners.ts
similarity index 87%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_listeners.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_listeners.ts
index 426cfd6d48..ef36daa20c 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_listeners.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_listeners.ts
@@ -1,6 +1,6 @@
 import { DatabaseFieldChangesetPB, FieldSettingsPB, FieldVisibility } from '@/services/backend';
-import { Database, fieldService } from '$app/components/database/application';
-import { didDeleteCells, didUpdateCells } from '$app/components/database/application/cell/cell_listeners';
+import { Database, fieldService } from '$app/application/database';
+import { didDeleteCells, didUpdateCells } from '$app/application/database/cell/cell_listeners';
 
 export function didUpdateFieldSettings(database: Database, settings: FieldSettingsPB) {
   const { field_id: fieldId, visibility, width } = settings;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_service.ts
similarity index 98%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_service.ts
index dff4ee8e09..219aeb3ea5 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_service.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_service.ts
@@ -26,7 +26,7 @@ import {
 } from '@/services/backend/events/flowy-database2';
 import { Field, pbToField } from './field_types';
 import { bytesToTypeOption } from './type_option';
-import { Database } from '$app/components/database/application';
+import { Database } from '$app/application/database';
 
 export async function getFields(
   viewId: string,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/field_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/field_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/select_option/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/select_option/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/select_option/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/select_option/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/select_option/select_option_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/select_option/select_option_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/select_option/select_option_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/select_option/select_option_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/select_option/select_option_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/select_option/select_option_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/select_option/select_option_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/select_option/select_option_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/type_option/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/type_option/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/type_option/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/type_option/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/type_option/type_option_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/type_option/type_option_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/type_option/type_option_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/type_option/type_option_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/type_option/type_option_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/field/type_option/type_option_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/field/type_option/type_option_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/field/type_option/type_option_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_data.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_data.ts
similarity index 91%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_data.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_data.ts
index 572d8187f1..5d9c9f9be0 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_data.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_data.ts
@@ -5,7 +5,7 @@ import {
   NumberFilterConditionPB,
   TextFilterConditionPB,
 } from '@/services/backend';
-import { UndeterminedFilter } from '$app/components/database/application';
+import { UndeterminedFilter } from '$app/application/database';
 
 export function getDefaultFilter(fieldType: FieldType): UndeterminedFilter['data'] | undefined {
   switch (fieldType) {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_listeners.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_listeners.ts
similarity index 93%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_listeners.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_listeners.ts
index 05618ca6b9..9a0cd46b2c 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_listeners.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_listeners.ts
@@ -1,4 +1,4 @@
-import { Database, pbToFilter } from '$app/components/database/application';
+import { Database, pbToFilter } from '$app/application/database';
 import { FilterChangesetNotificationPB } from '@/services/backend';
 
 const deleteFiltersFromChange = (database: Database, changeset: FilterChangesetNotificationPB) => {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/filter_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/filter/filter_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/filter/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/filter/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/filter/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/group/group_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/group/group_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/group/group_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/group/group_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/group/group_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/group/group_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/group/group_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/group/group_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/group/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/group/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/group/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/group/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/row/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/row/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/row_listeners.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/row/row_listeners.ts
similarity index 96%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/row_listeners.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/row/row_listeners.ts
index a1f975409e..acee8d141b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/row_listeners.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/database/row/row_listeners.ts
@@ -1,7 +1,7 @@
 import { ReorderAllRowsPB, ReorderSingleRowPB, RowsChangePB, RowsVisibilityChangePB } from '@/services/backend';
 import { Database } from '../database';
 import { pbToRowMeta, RowMeta } from './row_types';
-import { didDeleteCells } from '$app/components/database/application/cell/cell_listeners';
+import { didDeleteCells } from '$app/application/database/cell/cell_listeners';
 
 const deleteRowsFromChangeset = (database: Database, changeset: RowsChangePB) => {
   changeset.deleted_rows.forEach((rowId) => {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/row_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/row/row_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/row_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/row/row_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/row_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/row/row_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/row/row_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/row/row_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/index.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/sort/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/sort/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/sort_listeners.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/sort/sort_listeners.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/sort_listeners.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/sort/sort_listeners.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/sort_service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/sort/sort_service.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/sort_service.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/sort/sort_service.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/sort_types.ts b/frontend/appflowy_tauri/src/appflowy_app/application/database/sort/sort_types.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/application/sort/sort_types.ts
rename to frontend/appflowy_tauri/src/appflowy_app/application/database/sort/sort_types.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/application/folder/page.service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/folder/page.service.ts
new file mode 100644
index 0000000000..b529571c91
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/folder/page.service.ts
@@ -0,0 +1,152 @@
+import { Page, PageIcon, parserViewPBToPage } from '$app_reducers/pages/slice';
+import {
+  CreateOrphanViewPayloadPB,
+  CreateViewPayloadPB,
+  MoveNestedViewPayloadPB,
+  RepeatedViewIdPB,
+  UpdateViewIconPayloadPB,
+  UpdateViewPayloadPB,
+  ViewIconPB,
+  ViewIdPB,
+  ViewPB,
+} from '@/services/backend';
+import {
+  FolderEventCreateOrphanView,
+  FolderEventCreateView,
+  FolderEventDeleteView,
+  FolderEventDuplicateView,
+  FolderEventGetView,
+  FolderEventMoveNestedView,
+  FolderEventUpdateView,
+  FolderEventUpdateViewIcon,
+} from '@/services/backend/events/flowy-folder';
+
+export async function getPage(id: string) {
+  const payload = new ViewIdPB({
+    value: id,
+  });
+
+  const result = await FolderEventGetView(payload);
+
+  if (result.ok) {
+    return parserViewPBToPage(result.val);
+  }
+
+  return Promise.reject(result.val);
+}
+
+export const createOrphanPage = async (
+  params: ReturnType<typeof CreateOrphanViewPayloadPB.prototype.toObject>
+): Promise<Page> => {
+  const payload = CreateOrphanViewPayloadPB.fromObject(params);
+
+  const result = await FolderEventCreateOrphanView(payload);
+
+  if (result.ok) {
+    return parserViewPBToPage(result.val);
+  }
+
+  return Promise.reject(result.val);
+};
+
+export const duplicatePage = async (id: string) => {
+  const page = await getPage(id);
+  const payload = ViewPB.fromObject(page);
+
+  const result = await FolderEventDuplicateView(payload);
+
+  if (result.ok) {
+    return result.val;
+  }
+
+  return Promise.reject(result.err);
+};
+
+export const deletePage = async (id: string) => {
+  const payload = new RepeatedViewIdPB({
+    items: [id],
+  });
+
+  const result = await FolderEventDeleteView(payload);
+
+  if (result.ok) {
+    return result.val;
+  }
+
+  return Promise.reject(result.err);
+};
+
+export const createPage = async (params: ReturnType<typeof CreateViewPayloadPB.prototype.toObject>): Promise<string> => {
+  const payload = CreateViewPayloadPB.fromObject(params);
+
+  const result = await FolderEventCreateView(payload);
+
+  if (result.ok) {
+    return result.val.id;
+  }
+
+  return Promise.reject(result.err);
+};
+
+export const movePage = async (params: ReturnType<typeof MoveNestedViewPayloadPB.prototype.toObject>) => {
+  const payload = new MoveNestedViewPayloadPB(params);
+
+  const result = await FolderEventMoveNestedView(payload);
+
+  if (result.ok) {
+    return result.val;
+  }
+
+  return Promise.reject(result.err);
+};
+
+export const getChildPages = async (id: string): Promise<Page[]> => {
+  const payload = new ViewIdPB({
+    value: id,
+  });
+
+  const result = await FolderEventGetView(payload);
+
+  if (result.ok) {
+    return result.val.child_views.map(parserViewPBToPage);
+  }
+
+  return [];
+};
+
+export const updatePage = async (page: { id: string } & Partial<Page>) => {
+  const payload = new UpdateViewPayloadPB();
+
+  payload.view_id = page.id;
+  if (page.name !== undefined) {
+    payload.name = page.name;
+  }
+
+  const result = await FolderEventUpdateView(payload);
+
+  if (result.ok) {
+    return result.val.toObject();
+  }
+
+  return Promise.reject(result.err);
+};
+
+export const updatePageIcon = async (viewId: string, icon?: PageIcon) => {
+  const payload = new UpdateViewIconPayloadPB({
+    view_id: viewId,
+    icon: icon
+      ? new ViewIconPB({
+          ty: icon.ty,
+          value: icon.value,
+        })
+      : undefined,
+  });
+
+  const result = await FolderEventUpdateViewIcon(payload);
+
+  if (result.ok) {
+    return result.val;
+  }
+
+  return Promise.reject(result.err);
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/application/folder/trash.service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/folder/trash.service.ts
new file mode 100644
index 0000000000..dfbe742ca0
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/folder/trash.service.ts
@@ -0,0 +1,68 @@
+import {
+  FolderEventListTrashItems,
+  FolderEventPermanentlyDeleteAllTrashItem,
+  FolderEventPermanentlyDeleteTrashItem,
+  FolderEventRecoverAllTrashItems,
+  FolderEventRestoreTrashItem,
+  RepeatedTrashIdPB,
+  TrashIdPB,
+} from '@/services/backend/events/flowy-folder';
+
+export const getTrash = async () => {
+  const res = await FolderEventListTrashItems();
+
+  if (res.ok) {
+    return res.val.items;
+  }
+
+  return [];
+};
+
+export const putback = async (id: string) => {
+  const payload = new TrashIdPB({
+    id,
+  });
+
+  const res = await FolderEventRestoreTrashItem(payload);
+
+  if (res.ok) {
+    return res.val;
+  }
+
+  return Promise.reject(res.err);
+};
+
+export const deleteTrashItem = async (ids: string[]) => {
+  const items = ids.map((id) => new TrashIdPB({ id }));
+  const payload = new RepeatedTrashIdPB({
+    items,
+  });
+
+  const res = await FolderEventPermanentlyDeleteTrashItem(payload);
+
+  if (res.ok) {
+    return res.val;
+  }
+
+  return Promise.reject(res.err);
+};
+
+export const deleteAll = async () => {
+  const res = await FolderEventPermanentlyDeleteAllTrashItem();
+
+  if (res.ok) {
+    return res.val;
+  }
+
+  return Promise.reject(res.err);
+};
+
+export const restoreAll = async () => {
+  const res = await FolderEventRecoverAllTrashItems();
+
+  if (res.ok) {
+    return res.val;
+  }
+
+  return Promise.reject(res.err);
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/application/folder/workspace.service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/folder/workspace.service.ts
new file mode 100644
index 0000000000..0a1ac683af
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/folder/workspace.service.ts
@@ -0,0 +1,110 @@
+import { CreateViewPayloadPB, UserWorkspaceIdPB, WorkspaceIdPB } from '@/services/backend';
+import { UserEventOpenWorkspace } from '@/services/backend/events/flowy-user';
+import {
+  FolderEventCreateView,
+  FolderEventDeleteWorkspace,
+  FolderEventGetCurrentWorkspaceSetting,
+  FolderEventReadCurrentWorkspace,
+  FolderEventReadWorkspaceViews,
+} from '@/services/backend/events/flowy-folder';
+import { parserViewPBToPage } from '$app_reducers/pages/slice';
+
+export async function openWorkspace(id: string) {
+  const payload = new UserWorkspaceIdPB({
+    workspace_id: id,
+  });
+
+  const result = await UserEventOpenWorkspace(payload);
+
+  if (result.ok) {
+    return result.val;
+  }
+
+  return Promise.reject(result.err);
+}
+
+export async function deleteWorkspace(id: string) {
+  const payload = new WorkspaceIdPB({
+    value: id,
+  });
+
+  const result = await FolderEventDeleteWorkspace(payload);
+
+  if (result.ok) {
+    return result.val;
+  }
+
+  return Promise.reject(result.err);
+}
+
+export async function getWorkspaceChildViews(id: string) {
+  const payload = new WorkspaceIdPB({
+    value: id,
+  });
+
+  const result = await FolderEventReadWorkspaceViews(payload);
+
+  if (result.ok) {
+    return result.val.items.map(parserViewPBToPage);
+  }
+
+  return [];
+}
+
+export async function getWorkspaces() {
+  const result = await FolderEventReadCurrentWorkspace();
+
+  if (result.ok) {
+    const item = result.val;
+
+    return [
+      {
+        id: item.id,
+        name: item.name,
+      },
+    ];
+  }
+
+  return [];
+}
+
+export async function getCurrentWorkspaceSetting() {
+  const res = await FolderEventGetCurrentWorkspaceSetting();
+
+  if (res.ok) {
+    return res.val;
+  }
+
+  return;
+}
+
+export async function getCurrentWorkspace() {
+  const result = await FolderEventReadCurrentWorkspace();
+
+  if (result.ok) {
+    const workspace = result.val;
+
+    return {
+      id: workspace.id,
+      name: workspace.name,
+    };
+  }
+
+  return null;
+}
+
+export async function createCurrentWorkspaceChildView(
+  params: ReturnType<typeof CreateViewPayloadPB.prototype.toObject>
+) {
+  const payload = CreateViewPayloadPB.fromObject(params);
+
+  const result = await FolderEventCreateView(payload);
+
+  if (result.ok) {
+    const view = result.val;
+
+    return view;
+  }
+
+  return Promise.reject(result.err);
+}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/application/notification.ts b/frontend/appflowy_tauri/src/appflowy_app/application/notification.ts
index d76c6c8db9..726bfabaec 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/application/notification.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/notification.ts
@@ -15,6 +15,13 @@ import {
   RowsChangePB,
   RowsVisibilityChangePB,
   SortChangesetNotificationPB,
+  UserNotification,
+  UserProfilePB,
+  FolderNotification,
+  RepeatedViewPB,
+  ViewPB,
+  RepeatedTrashPB,
+  ChildViewUpdatePB,
 } from '@/services/backend';
 
 const Notification = {
@@ -32,6 +39,11 @@ const Notification = {
   [DatabaseNotification.DidUpdateFieldSettings]: FieldSettingsPB,
   [DatabaseNotification.DidUpdateFilter]: FilterChangesetNotificationPB,
   [DocumentNotification.DidReceiveUpdate]: DocEventPB,
+  [UserNotification.DidUpdateUserProfile]: UserProfilePB,
+  [FolderNotification.DidUpdateWorkspaceViews]: RepeatedViewPB,
+  [FolderNotification.DidUpdateView]: ViewPB,
+  [FolderNotification.DidUpdateChildViews]: ChildViewUpdatePB,
+  [FolderNotification.DidUpdateTrash]: RepeatedTrashPB,
 };
 
 type NotificationMap = typeof Notification;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/application/user/auth.service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/user/auth.service.ts
new file mode 100644
index 0000000000..82c0a6779b
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/user/auth.service.ts
@@ -0,0 +1,46 @@
+import { SignInPayloadPB, SignUpPayloadPB } from '@/services/backend';
+import {
+  UserEventSignInWithEmailPassword,
+  UserEventSignOut,
+  UserEventSignUp,
+} from '@/services/backend/events/flowy-user';
+import { nanoid } from '@reduxjs/toolkit';
+import { Log } from '$app/utils/log';
+
+export const AuthService = {
+  signIn: async (params: { email: string; password: string }) => {
+    const payload = SignInPayloadPB.fromObject({ email: params.email, password: params.password });
+
+    const res = await UserEventSignInWithEmailPassword(payload);
+
+    if (res.ok) {
+      return res.val;
+    }
+
+    Log.error(res.val.msg);
+    throw new Error(res.val.msg);
+  },
+
+  signUp: async (params: { name: string; email: string; password: string }) => {
+    const deviceId = nanoid(8);
+    const payload = SignUpPayloadPB.fromObject({
+      name: params.name,
+      email: params.email,
+      password: params.password,
+      device_id: deviceId,
+    });
+
+    const res = await UserEventSignUp(payload);
+
+    if (!res.ok) {
+      Log.error(res.val.msg);
+      throw new Error(res.val.msg);
+    }
+
+    return res.val;
+  },
+
+  signOut: () => {
+    return UserEventSignOut();
+  },
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/application/user/user.service.ts b/frontend/appflowy_tauri/src/appflowy_app/application/user/user.service.ts
new file mode 100644
index 0000000000..f91c39cb71
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/application/user/user.service.ts
@@ -0,0 +1,55 @@
+import { Theme, ThemeMode, UserSetting } from '$app_reducers/current-user/slice';
+import { AppearanceSettingsPB } from '@/services/backend';
+import {
+  UserEventGetAppearanceSetting,
+  UserEventGetUserProfile,
+  UserEventSetAppearanceSetting,
+} from '@/services/backend/events/flowy-user';
+
+export const UserService = {
+  getAppearanceSetting: async (): Promise<Partial<UserSetting> | undefined> => {
+    const appearanceSetting = await UserEventGetAppearanceSetting();
+
+    if (appearanceSetting.ok) {
+      const res = appearanceSetting.val;
+      const { locale, theme = Theme.Default, theme_mode = ThemeMode.Light } = res;
+      let language = 'en';
+
+      if (locale.language_code && locale.country_code) {
+        language = `${locale.language_code}-${locale.country_code}`;
+      } else if (locale.language_code) {
+        language = locale.language_code;
+      }
+
+      return {
+        themeMode: theme_mode,
+        theme: theme as Theme,
+        language: language,
+      };
+    }
+
+    return;
+  },
+
+  setAppearanceSetting: async (params: ReturnType<typeof AppearanceSettingsPB.prototype.toObject>) => {
+    const payload = AppearanceSettingsPB.fromObject(params);
+
+    const res = await UserEventSetAppearanceSetting(payload);
+
+    if (res.ok) {
+      return res.val;
+    }
+
+    return Promise.reject(res.err);
+  },
+
+  getUserProfile: async () => {
+    const res = await UserEventGetUserProfile();
+
+    if (res.ok) {
+      return res.val;
+    }
+
+    return;
+  },
+};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/assets/Icons 16/Page.svg b/frontend/appflowy_tauri/src/appflowy_app/assets/Icons 16/Page.svg
deleted file mode 100644
index f0fb8ce9ce..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/assets/Icons 16/Page.svg	
+++ /dev/null
@@ -1,4 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M9 2.5V6C9 6.55228 9.44772 7 10 7H12" stroke="#333333"/>
-<path d="M3.5 3.5C3.5 2.94771 3.94772 2.5 4.5 2.5H8H8.5C9.12951 2.5 9.72229 2.79639 10.1 3.3L12.1 5.96667C12.3596 6.31286 12.5 6.73393 12.5 7.16667V8V12.5C12.5 13.0523 12.0523 13.5 11.5 13.5H4.5C3.94772 13.5 3.5 13.0523 3.5 12.5V3.5Z" stroke="#333333"/>
-</svg>
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Button.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Button.tsx
deleted file mode 100644
index e455831e74..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Button.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { MouseEventHandler, MouseEvent, ReactNode, useEffect, useState } from 'react';
-
-export const Button = ({
-  size = 'primary',
-  children,
-  onClick,
-}: {
-  size?: 'primary' | 'medium' | 'small' | 'box-small-transparent' | 'medium-transparent';
-  children: ReactNode;
-  onClick?: MouseEventHandler<HTMLButtonElement>;
-}) => {
-  const [cls, setCls] = useState('');
-
-  useEffect(() => {
-    switch (size) {
-      case 'primary':
-        setCls('w-[340px] h-[48px] flex items-center justify-center rounded-lg bg-fill-default text-content-on-fill');
-        break;
-      case 'medium':
-        setCls('w-[170px] h-[48px] flex items-center justify-center rounded-lg bg-fill-default text-content-on-fill');
-        break;
-      case 'small':
-        setCls(
-          'w-[68px] h-[32px] flex items-center justify-center rounded-lg bg-fill-default text-content-on-fill text-xs hover:bg-fill-list-hover'
-        );
-        break;
-      case 'medium-transparent':
-        setCls(
-          'w-[170px] h-[48px] flex items-center justify-center rounded-lg border border-fill-default text-fill-default transition-colors duration-300 hover:bg-content-blue-50 '
-        );
-        break;
-      case 'box-small-transparent':
-        setCls('text-icon-default w-[24px] h-[24px] rounded hover:bg-fill-list-hover');
-        break;
-    }
-  }, [size]);
-
-  const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
-    e.stopPropagation();
-    onClick && onClick(e);
-  };
-
-  return (
-    <button className={cls} onClick={(e) => handleClick(e)}>
-      {children}
-    </button>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/CheckListProgress.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/CheckListProgress.tsx
deleted file mode 100644
index 6f483bd4d2..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/CheckListProgress.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-export const CheckListProgress = ({ completed, max }: { completed: number; max: number }) => {
-  return (
-    <div className={'flex w-full items-center gap-4 py-1'}>
-      {max > 0 && (
-        <>
-          <div className={'flex flex-1 gap-1'}>
-            {completed > 0 && filledCheckListBars({ amount: completed })}
-            {max - completed > 0 && emptyCheckListBars({ amount: max - completed })}
-          </div>
-          <div className={'text-xs text-text-caption'}>{((100 * completed) / max).toFixed(0)}%</div>
-        </>
-      )}
-    </div>
-  );
-};
-
-const filledCheckListBars = ({ amount }: { amount: number }) => {
-  return Array(amount)
-    .fill(0)
-    .map((item, index) => <div key={index} className={'h-[4px] flex-1 flex-shrink-0 rounded bg-fill-hover'}></div>);
-};
-
-const emptyCheckListBars = ({ amount }: { amount: number }) => {
-  return Array(amount)
-    .fill(0)
-    .map((item, index) => <div key={index} className={'bg-tint-9 h-[4px] flex-1 flex-shrink-0 rounded'}></div>);
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Database.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Database.hooks.ts
deleted file mode 100644
index 9b0955793e..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Database.hooks.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { useAppSelector } from '$app/stores/store';
-
-export const useDatabase = () => {
-  const database = useAppSelector((state) => state.database);
-
-  const newField = () => {
-    /* dispatch(
-      databaseActions.addField({
-        field: {
-          fieldId: nanoid(8),
-          fieldType: FieldType.RichText,
-          fieldOptions: {},
-          title: 'new field',
-        },
-      })
-    );*/
-    console.log('depreciated');
-  };
-
-  const renameField = (_fieldId: string, _newTitle: string) => {
-    /*   const field = database.fields[fieldId];
-    field.title = newTitle;
-
-    dispatch(
-      databaseActions.updateField({
-        field,
-      })
-    );*/
-    console.log('depreciated');
-  };
-
-  const newRow = () => {
-    // dispatch(databaseActions.addRow());
-    console.log('depreciated');
-  };
-
-  return {
-    database,
-    newField,
-    renameField,
-    newRow,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/DatabaseFilterItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/DatabaseFilterItem.tsx
deleted file mode 100644
index b0b7d41322..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/DatabaseFilterItem.tsx
+++ /dev/null
@@ -1,175 +0,0 @@
-import { FieldType } from '@/services/backend';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import {
-  IDatabaseFilter,
-  ISelectOption,
-  SupportedOperatorsByType,
-  TDatabaseOperators,
-} from '$app_reducers/database/slice';
-import { useAppSelector } from '$app/stores/store';
-import React, { useEffect, useMemo, useState } from 'react';
-import { FieldSelect } from '$app/components/_shared/DatabaseFilter/FieldSelect';
-import { LogicalOperatorSelect } from '$app/components/_shared/DatabaseFilter/LogicalOperatorSelect';
-import { OperatorSelect } from '$app/components/_shared/DatabaseFilter/OperatorSelect';
-import { FilterValue } from '$app/components/_shared/DatabaseFilter/FilterValue';
-
-export const DatabaseFilterItem = ({
-  data,
-  onSave,
-  onDelete,
-  index,
-}: {
-  data: IDatabaseFilter | null;
-  onSave: (filter: IDatabaseFilter) => void;
-  onDelete?: () => void;
-  index: number;
-}) => {
-  // stores
-  const columns = useAppSelector((state) => state.database.columns);
-  const fields = useAppSelector((state) => state.database.fields);
-  const filtersStore = useAppSelector((state) => state.database.filters);
-
-  // values
-  const [currentLogicalOperator, setCurrentLogicalOperator] = useState<'and' | 'or'>('and');
-  const [currentFieldId, setCurrentFieldId] = useState<string | null>(data?.fieldId ?? null);
-  const [currentOperator, setCurrentOperator] = useState<TDatabaseOperators | null>(data?.operator ?? null);
-  const [currentValue, setCurrentValue] = useState<string[] | string | boolean | null>(data?.value ?? null);
-
-  useEffect(() => {
-    if (data) {
-      setCurrentLogicalOperator(data.logicalOperator);
-      setCurrentFieldId(data.fieldId);
-      setCurrentOperator(data.operator);
-      setCurrentValue(data.value);
-    } else {
-      setCurrentLogicalOperator('and');
-      setCurrentFieldId(null);
-      setCurrentOperator(null);
-      setCurrentValue(null);
-    }
-  }, [data]);
-
-  const [textInputActive, setTextInputActive] = useState(false);
-
-  // shortcut
-  const currentFieldType = useMemo(
-    () => (currentFieldId ? fields[currentFieldId].fieldType : undefined),
-    [currentFieldId, fields]
-  );
-
-  useEffect(() => {
-    // if the user is typing in a text input, don't update the filter
-    if (textInputActive) return;
-
-    if (currentFieldId && currentFieldType !== undefined && currentOperator && currentValue !== null) {
-      if (currentFieldType === FieldType.RichText && (currentValue as string).length === 0) {
-        return;
-      }
-
-      onSave({
-        id: data?.id,
-        logicalOperator: currentLogicalOperator,
-        fieldId: currentFieldId,
-        fieldType: currentFieldType,
-        operator: currentOperator,
-        value: currentValue,
-      });
-    }
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [currentFieldId, currentFieldType, currentOperator, currentValue, textInputActive]);
-
-  // 1. not all field types support filtering
-  // 2. we don't want to show fields that are already in use
-  const supportedColumns = useMemo(
-    () =>
-      columns
-        .filter((column) => SupportedOperatorsByType[fields[column.fieldId].fieldType] !== undefined)
-        .filter((column) => filtersStore.findIndex((filter) => filter?.fieldId === column.fieldId) === -1),
-    [columns, fields, filtersStore]
-  );
-
-  const onSelectFieldClick = (id: string) => {
-    setCurrentFieldId(id);
-
-    switch (fields[id].fieldType) {
-      case FieldType.RichText:
-        setCurrentValue('');
-        setCurrentOperator(null);
-        break;
-      case FieldType.MultiSelect:
-      case FieldType.SingleSelect:
-        setCurrentValue([]);
-        setCurrentOperator(null);
-        break;
-      case FieldType.Checkbox:
-        setCurrentOperator('is');
-        setCurrentValue(false);
-        break;
-      default:
-        setCurrentOperator(null);
-        setCurrentValue(null);
-    }
-  };
-
-  const onSelectOperatorClick = (operator: TDatabaseOperators) => {
-    setCurrentOperator(operator);
-  };
-
-  const onValueOptionClick = (option: ISelectOption) => {
-    const value = currentValue as string[];
-
-    if (value.findIndex((v) => v === option.selectOptionId) === -1) {
-      setCurrentValue([...value, option.selectOptionId]);
-    } else {
-      setCurrentValue(value.filter((v) => v !== option.selectOptionId));
-    }
-  };
-
-  return (
-    <>
-      <div className='flex items-center gap-4'>
-        <div className={'w-[88px]'}>
-          {index === 0 ? (
-            <span className={'text-sm text-text-caption'}>Where</span>
-          ) : (
-            <LogicalOperatorSelect></LogicalOperatorSelect>
-          )}
-        </div>
-
-        <FieldSelect
-          columns={supportedColumns}
-          fields={fields}
-          onSelectFieldClick={onSelectFieldClick}
-          currentFieldId={currentFieldId}
-          currentFieldType={currentFieldType}
-        ></FieldSelect>
-
-        <OperatorSelect
-          currentOperator={currentOperator}
-          currentFieldType={currentFieldType}
-          onSelectOperatorClick={onSelectOperatorClick}
-        ></OperatorSelect>
-
-        <FilterValue
-          currentFieldId={currentFieldId}
-          currentFieldType={currentFieldType}
-          currentValue={currentValue}
-          setCurrentValue={setCurrentValue}
-          fields={fields}
-          textInputActive={textInputActive}
-          setTextInputActive={setTextInputActive}
-          onValueOptionClick={onValueOptionClick}
-        ></FilterValue>
-
-        <button
-          onClick={() => onDelete?.()}
-          className={`rounded p-1 hover:bg-fill-list-hover ${data ? 'opacity-100' : 'opacity-0'}`}
-        >
-          <i className={'block h-[16px] w-[16px]'}>
-            <TrashSvg />
-          </i>
-        </button>
-      </div>
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/DatabaseFilterPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/DatabaseFilterPopup.tsx
deleted file mode 100644
index 5dbc1e50ea..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/DatabaseFilterPopup.tsx
+++ /dev/null
@@ -1,183 +0,0 @@
-import { t } from 'i18next';
-import AddSvg from '../../_shared/svg/AddSvg';
-import { useAppSelector } from '$app/stores/store';
-import { MouseEventHandler, useMemo, useState } from 'react';
-import { DatabaseFilterItem } from '$app/components/_shared/DatabaseFilter/DatabaseFilterItem';
-import { IDatabaseFilter, TDatabaseOperators } from '$app_reducers/database/slice';
-import { FilterController } from '$app/stores/effects/database/filter/filter_controller';
-import {
-  CheckboxFilterPB,
-  FieldType,
-  SelectOptionConditionPB,
-  SelectOptionFilterPB,
-  TextFilterConditionPB,
-  TextFilterPB,
-} from '@/services/backend';
-
-export const DatabaseFilterPopup = ({
-  filterController,
-  onOutsideClick,
-}: {
-  filterController: FilterController;
-  onOutsideClick: () => void;
-}) => {
-  // stores
-  const filtersStore = useAppSelector((state) => state.database.filters);
-
-  // local copy to prevent jitter when adding new filter
-  const [filters, setFilters] = useState<(IDatabaseFilter | null)[]>(filtersStore);
-  const [showBlankFilter, setShowBlankFilter] = useState(filtersStore.length === 0);
-
-  const onAddClick: MouseEventHandler = () => {
-    setShowBlankFilter(true);
-  };
-
-  const transformOperator: (
-    operator: TDatabaseOperators,
-    type: FieldType
-  ) => TextFilterConditionPB | SelectOptionConditionPB = (operator, type) => {
-    switch (type) {
-      case FieldType.RichText:
-        switch (operator) {
-          case 'contains':
-            return TextFilterConditionPB.Contains;
-          case 'doesNotContain':
-            return TextFilterConditionPB.DoesNotContain;
-          case 'endsWith':
-            return TextFilterConditionPB.EndsWith;
-          case 'startWith':
-            return TextFilterConditionPB.StartsWith;
-          case 'is':
-            return TextFilterConditionPB.Is;
-          case 'isNot':
-            return TextFilterConditionPB.IsNot;
-          case 'isEmpty':
-            return TextFilterConditionPB.TextIsEmpty;
-          case 'isNotEmpty':
-            return TextFilterConditionPB.TextIsNotEmpty;
-          default:
-            return TextFilterConditionPB.Is;
-        }
-
-      case FieldType.SingleSelect:
-      case FieldType.MultiSelect:
-        switch (operator) {
-          case 'is':
-          case 'contains':
-            return SelectOptionConditionPB.OptionIs;
-          case 'isNot':
-          case 'doesNotContain':
-            return SelectOptionConditionPB.OptionIsNot;
-          case 'isEmpty':
-            return SelectOptionConditionPB.OptionIsEmpty;
-          case 'isNotEmpty':
-            return SelectOptionConditionPB.OptionIsNotEmpty;
-          default:
-            return SelectOptionConditionPB.OptionIs;
-        }
-
-      default:
-        return TextFilterConditionPB.Is;
-    }
-  };
-
-  const onSaveFilterItem = async (filter: IDatabaseFilter) => {
-    let val: TextFilterPB | SelectOptionFilterPB | CheckboxFilterPB;
-
-    switch (filter.fieldType) {
-      case FieldType.RichText:
-        val = new TextFilterPB({
-          condition: transformOperator(filter.operator, filter.fieldType) as TextFilterConditionPB,
-          content: filter.value as string,
-        });
-        break;
-      case FieldType.SingleSelect:
-      case FieldType.MultiSelect:
-        val = new SelectOptionFilterPB({
-          condition: transformOperator(filter.operator, filter.fieldType) as SelectOptionConditionPB,
-          option_ids: filter.value as string[],
-        });
-        break;
-      default:
-        val = new TextFilterPB({
-          condition: transformOperator('is', FieldType.RichText) as TextFilterConditionPB,
-          content: '',
-        });
-        break;
-    }
-
-    let updatedFilter = filter;
-
-    if (filter.id) {
-      await filterController.updateFilter(filter.id, filter.fieldId, filter.fieldType, val);
-    } else {
-      const newId = await filterController.addFilter(filter.fieldId, filter.fieldType, val);
-
-      updatedFilter = { ...filter, id: newId };
-    }
-
-    const index = filters.findIndex((f) => f?.fieldId === filter.fieldId);
-
-    if (index === -1) {
-      setFilters([...filters, updatedFilter]);
-    } else {
-      setFilters([...filters.slice(0, index), updatedFilter, ...filters.slice(index + 1)]);
-    }
-
-    setShowBlankFilter(false);
-  };
-
-  const onDeleteFilterItem = async (filter: IDatabaseFilter | null) => {
-    if (!filter || !filter.id || !filter.fieldId) return;
-
-    // add blank filter if no filters left
-    if (filters.length === 1) {
-      setShowBlankFilter(true);
-    }
-
-    await filterController.removeFilter(filter.fieldId, filter.fieldType, filter.id);
-
-    // update local copy
-    const index = filters.findIndex((f) => f?.fieldId === filter.fieldId);
-
-    setFilters([...filters.slice(0, index), ...filters.slice(index + 1)]);
-  };
-
-  // null row represents new filter
-  const rows = useMemo(() => (showBlankFilter ? filters.concat([null]) : filters), [filters, showBlankFilter]);
-
-  return (
-    <div
-      className={'fixed inset-0 z-10 flex items-center justify-center overflow-y-auto backdrop-blur-sm'}
-      onClick={onOutsideClick}
-    >
-      <div onClick={(e) => e.stopPropagation()} className='flex flex-col rounded-lg bg-bg-body shadow-md'>
-        <div className='px-6 pt-6 text-sm text-text-caption'>{t('grid.settings.filter')}</div>
-
-        <div className='flex flex-col gap-3 overflow-y-scroll px-6 py-6 text-sm'>
-          {rows.map((filter, index: number) => (
-            <DatabaseFilterItem
-              data={filter}
-              onSave={onSaveFilterItem}
-              onDelete={() => onDeleteFilterItem(filter)}
-              key={index}
-              index={index}
-            ></DatabaseFilterItem>
-          ))}
-        </div>
-
-        <hr />
-
-        <button
-          onClick={onAddClick}
-          className='flex cursor-pointer items-center gap-2 px-6 py-6 text-sm text-text-caption'
-        >
-          <div className='h-5 w-5'>
-            <AddSvg />
-          </div>
-          {t('grid.settings.addFilter')}
-        </button>
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/FieldSelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/FieldSelect.tsx
deleted file mode 100644
index c93e7d370b..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/FieldSelect.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
-import { DropDownShowSvg } from '$app/components/_shared/svg/DropDownShowSvg';
-import ButtonPopoverList from '$app/components/_shared/ButtonPopoverList';
-import React, { useState } from 'react';
-import { DatabaseFieldMap, IDatabaseColumn } from '$app_reducers/database/slice';
-import { FieldType } from '@/services/backend';
-
-interface IFieldSelectProps {
-  columns: IDatabaseColumn[];
-  fields: DatabaseFieldMap;
-  onSelectFieldClick: (fieldId: string) => void;
-  currentFieldId: string | null;
-  currentFieldType: FieldType | undefined;
-}
-
-const WIDTH = 180;
-
-export const FieldSelect = ({
-  columns,
-  fields,
-  onSelectFieldClick,
-  currentFieldId,
-  currentFieldType,
-}: IFieldSelectProps) => {
-  const [showSelect, setShowSelect] = useState(false);
-
-  return (
-    <ButtonPopoverList
-      isVisible={true}
-      popoverOptions={columns.map((column) => ({
-        key: column.fieldId,
-        icon: (
-          <i className={'block h-5 w-5'}>
-            <FieldTypeIcon fieldType={fields[column.fieldId].fieldType}></FieldTypeIcon>
-          </i>
-        ),
-        label: fields[column.fieldId].title,
-        onClick: () => {
-          onSelectFieldClick(column.fieldId);
-          setShowSelect(false);
-        },
-      }))}
-      popoverOrigin={{
-        anchorOrigin: {
-          vertical: 'bottom',
-          horizontal: 'left',
-        },
-        transformOrigin: {
-          vertical: 'top',
-          horizontal: 'left',
-        },
-      }}
-      onClose={() => setShowSelect(false)}
-      sx={{ width: `${WIDTH}px` }}
-    >
-      <div
-        onClick={() => setShowSelect(true)}
-        className={`flex items-center justify-between rounded-lg border px-2 py-1 ${
-          showSelect ? 'border-fill-hover' : 'border-line-border'
-        }`}
-        style={{ width: `${WIDTH}px` }}
-      >
-        {currentFieldType !== undefined && currentFieldId ? (
-          <div className={'flex items-center gap-2'}>
-            <i className={'block h-5 w-5'}>
-              <FieldTypeIcon fieldType={currentFieldType}></FieldTypeIcon>
-            </i>
-            <span>{fields[currentFieldId].title}</span>
-          </div>
-        ) : (
-          <span className={'text-text-placeholder'}>Select a field</span>
-        )}
-        <i className={`h-5 w-5 transition-transform duration-500 ${showSelect ? 'rotate-180' : 'rotate-0'}`}>
-          <DropDownShowSvg></DropDownShowSvg>
-        </i>
-      </div>
-    </ButtonPopoverList>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/FilterValue.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/FilterValue.tsx
deleted file mode 100644
index 28d562e40b..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/FilterValue.tsx
+++ /dev/null
@@ -1,146 +0,0 @@
-import { FieldType } from '@/services/backend';
-import { getBgColor } from '$app/components/_shared/getColor';
-import { DropDownShowSvg } from '$app/components/_shared/svg/DropDownShowSvg';
-import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg';
-import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
-import React, { useRef, useState } from 'react';
-import { DatabaseFieldMap, ISelectOption, ISelectOptionType } from '$app_reducers/database/slice';
-import { CellOption } from '$app/components/_shared/EditRow/Options/CellOption';
-import { Popover } from '@mui/material';
-
-interface IFilterValueProps {
-  currentFieldId: string | null;
-  currentFieldType: FieldType | undefined;
-  currentValue: string[] | string | boolean | null;
-  fields: DatabaseFieldMap;
-  textInputActive: boolean;
-  setTextInputActive: (v: boolean) => void;
-  setCurrentValue: (v: string[] | string | boolean | null) => void;
-  onValueOptionClick: (option: ISelectOption) => void;
-}
-
-const WIDTH = 180;
-
-export const FilterValue = ({
-  currentFieldId,
-  currentFieldType,
-  currentValue,
-  fields,
-  textInputActive,
-  setTextInputActive,
-  setCurrentValue,
-  onValueOptionClick,
-}: IFilterValueProps) => {
-  const [showValueOptions, setShowValueOptions] = useState(false);
-
-  const refValueOptions = useRef<HTMLDivElement>(null);
-
-  const getSelectOption = (optionId: string) => {
-    if (!currentFieldId) return undefined;
-    return (fields[currentFieldId].fieldOptions as ISelectOptionType).selectOptions.find(
-      (option) => option.selectOptionId === optionId
-    );
-  };
-
-  return currentFieldId ? (
-    <>
-      {(currentFieldType === FieldType.MultiSelect || currentFieldType === FieldType.SingleSelect) && (
-        <>
-          <div
-            ref={refValueOptions}
-            onClick={() => setShowValueOptions(true)}
-            className={`flex items-center justify-between rounded-lg border px-2 py-1 ${
-              showValueOptions ? 'border-fill-hover' : 'border-line-border'
-            }`}
-            style={{ width: `${WIDTH}px` }}
-          >
-            {currentValue ? (
-              <div className={'flex flex-1 items-center gap-1 overflow-hidden'}>
-                {(currentValue as string[]).length === 0 && (
-                  <span className={'text-text-placeholder'}>none selected</span>
-                )}
-                {(currentValue as string[]).map((option, i) => (
-                  <span className={`${getBgColor(getSelectOption(option)?.color)} rounded px-2 py-0.5 text-xs`} key={i}>
-                    {getSelectOption(option)?.title}
-                  </span>
-                ))}
-              </div>
-            ) : (
-              <span className={'text-text-placeholder'}>Select an option</span>
-            )}
-
-            <i className={`h-5 w-5 transition-transform duration-500 ${showValueOptions ? 'rotate-180' : 'rotate-0'}`}>
-              <DropDownShowSvg></DropDownShowSvg>
-            </i>
-          </div>
-
-          <Popover
-            open={showValueOptions}
-            anchorOrigin={{
-              vertical: 'bottom',
-              horizontal: 'left',
-            }}
-            transformOrigin={{
-              vertical: 'top',
-              horizontal: 'left',
-            }}
-            anchorEl={refValueOptions.current}
-            onClose={() => setShowValueOptions(false)}
-          >
-            <div style={{ width: `${WIDTH}px` }} className={'flex flex-col gap-2 p-2 text-xs'}>
-              <div className={'font-medium text-text-caption'}>Value option</div>
-              <div className={'flex flex-col gap-1'}>
-                {(fields[currentFieldId].fieldOptions as ISelectOptionType).selectOptions.map((option, index) => (
-                  <CellOption
-                    key={index}
-                    option={option}
-                    checked={(currentValue as string[]).findIndex((o) => o === option.selectOptionId) !== -1}
-                    noSelect={true}
-                    noDetail={true}
-                    onOptionClick={() => onValueOptionClick(option)}
-                  ></CellOption>
-                ))}
-              </div>
-            </div>
-          </Popover>
-        </>
-      )}
-      {currentFieldType === FieldType.RichText && (
-        <div
-          className={`flex items-center justify-between rounded-lg border px-2 py-1 ${
-            textInputActive ? 'border-fill-hover' : 'border-line-border'
-          }`}
-          style={{ width: `${WIDTH}px` }}
-        >
-          <input
-            placeholder={'Enter value'}
-            className={'flex-1'}
-            onFocus={() => setTextInputActive(true)}
-            onBlur={() => setTextInputActive(false)}
-            value={currentValue as string}
-            onChange={(e) => setCurrentValue(e.target.value)}
-          />
-        </div>
-      )}
-      {currentFieldType === FieldType.Checkbox && (
-        <div
-          onClick={() => setCurrentValue(!currentValue)}
-          className={`flex cursor-pointer items-center gap-2 rounded-lg border border-line-border px-2 py-1`}
-          style={{ width: `${WIDTH}px` }}
-        >
-          <button className={'h-5 w-5'}>
-            {currentValue ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>}
-          </button>
-          <span>{currentValue ? 'Checked' : 'Unchecked'}</span>
-        </div>
-      )}
-    </>
-  ) : (
-    <div
-      className={`flex items-center justify-between rounded-lg border border-line-border px-2 py-1`}
-      style={{ width: `${WIDTH}px` }}
-    >
-      <span className={'text-text-placeholder'}>Select field</span>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/LogicalOperatorSelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/LogicalOperatorSelect.tsx
deleted file mode 100644
index e9cbc6d9aa..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/LogicalOperatorSelect.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import ButtonPopoverList from '$app/components/_shared/ButtonPopoverList';
-import { DropDownShowSvg } from '$app/components/_shared/svg/DropDownShowSvg';
-import React, { useState } from 'react';
-
-const LogicalOperators: ('and' | 'or')[] = ['and', 'or'];
-const WIDTH = 88;
-
-export const LogicalOperatorSelect = () => {
-  const [showSelect, setShowSelect] = useState(false);
-
-  return (
-    <ButtonPopoverList
-      isVisible={true}
-      popoverOptions={LogicalOperators.map((operator) => ({
-        key: operator,
-        label: operator,
-        icon: null,
-        onClick: () => {
-          console.log('logical operator: ', operator);
-          setShowSelect(false);
-        },
-      }))}
-      popoverOrigin={{
-        anchorOrigin: {
-          vertical: 'bottom',
-          horizontal: 'left',
-        },
-        transformOrigin: {
-          vertical: 'top',
-          horizontal: 'left',
-        },
-      }}
-      onClose={() => setShowSelect(false)}
-      sx={{ width: `${WIDTH}px` }}
-    >
-      <div
-        onClick={() => setShowSelect(true)}
-        className={`flex items-center justify-between rounded-lg border px-2 py-1 ${
-          showSelect ? 'border-fill-hover' : 'border-line-border'
-        }`}
-        style={{ width: `${WIDTH}px` }}
-      >
-        and
-        <i className={`h-5 w-5 transition-transform duration-500 ${showSelect ? 'rotate-180' : 'rotate-0'}`}>
-          <DropDownShowSvg></DropDownShowSvg>
-        </i>
-      </div>
-    </ButtonPopoverList>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/OperatorSelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/OperatorSelect.tsx
deleted file mode 100644
index 2a9ce61d3d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseFilter/OperatorSelect.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import ButtonPopoverList from '$app/components/_shared/ButtonPopoverList';
-import React, { useState } from 'react';
-import { DropDownShowSvg } from '$app/components/_shared/svg/DropDownShowSvg';
-import { SupportedOperatorsByType, TDatabaseOperators } from '$app_reducers/database/slice';
-import { FieldType } from '@/services/backend';
-
-interface IOperatorSelectProps {
-  currentOperator: TDatabaseOperators | null;
-  currentFieldType: FieldType | undefined;
-  onSelectOperatorClick: (operator: TDatabaseOperators) => void;
-}
-
-const WIDTH = 180;
-
-export const OperatorSelect = ({ currentOperator, currentFieldType, onSelectOperatorClick }: IOperatorSelectProps) => {
-  const [showSelect, setShowSelect] = useState(false);
-
-  return (
-    <ButtonPopoverList
-      isVisible={true}
-      popoverOptions={SupportedOperatorsByType[currentFieldType ? currentFieldType : FieldType.RichText].map(
-        (operatorName, index) => ({
-          icon: null,
-          key: index,
-          label: operatorName,
-          onClick: () => {
-            onSelectOperatorClick(operatorName);
-            setShowSelect(false);
-          },
-        })
-      )}
-      popoverOrigin={{
-        anchorOrigin: {
-          vertical: 'bottom',
-          horizontal: 'left',
-        },
-        transformOrigin: {
-          vertical: 'top',
-          horizontal: 'left',
-        },
-      }}
-      onClose={() => setShowSelect(false)}
-      sx={{ width: `${WIDTH}px` }}
-    >
-      <div
-        onClick={() => setShowSelect(true)}
-        className={`flex items-center justify-between rounded-lg border px-2 py-1 ${
-          showSelect ? 'border-fill-hover' : 'border-line-border'
-        }`}
-        style={{ width: `${WIDTH}px` }}
-      >
-        {currentOperator ? (
-          <span>{currentOperator}</span>
-        ) : (
-          <span className={'text-text-placeholder'}>Select an option</span>
-        )}
-        <i className={`h-5 w-5 transition-transform duration-500 ${showSelect ? 'rotate-180' : 'rotate-0'}`}>
-          <DropDownShowSvg></DropDownShowSvg>
-        </i>
-      </div>
-    </ButtonPopoverList>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/DatabaseSortItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/DatabaseSortItem.tsx
deleted file mode 100644
index 5e096dce6e..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/DatabaseSortItem.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { IDatabaseSort } from '$app_reducers/database/slice';
-import React, { useEffect, useMemo, useState } from 'react';
-import { useAppSelector } from '$app/stores/store';
-import { DragElementSvg } from '$app/components/_shared/svg/DragElementSvg';
-import { SortConditionPB } from '@/services/backend';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import { FieldSelect } from '$app/components/_shared/DatabaseFilter/FieldSelect';
-import { OrderSelect } from '$app/components/_shared/DatabaseSort/OrderSelect';
-
-export const DatabaseSortItem = ({
-  data,
-  onSave,
-  onDelete,
-}: {
-  data: IDatabaseSort | null;
-  onSave: (sortItem: IDatabaseSort) => void;
-  onDelete?: () => void;
-}) => {
-  // stores
-  const columns = useAppSelector((state) => state.database.columns);
-  const fields = useAppSelector((state) => state.database.fields);
-  const sortStore = useAppSelector((state) => state.database.sort);
-
-  // values
-  const [currentFieldId, setCurrentFieldId] = useState<string | null>(data?.fieldId ?? null);
-  const [currentOrder, setCurrentOrder] = useState<SortConditionPB | null>(data?.order ?? null);
-
-  const supportedColumns = useMemo(
-    () => columns.filter((c) => sortStore.findIndex((s) => s.fieldId === c.fieldId) === -1),
-    [columns, sortStore]
-  );
-
-  const currentFieldType = useMemo(
-    () => (currentFieldId ? fields[currentFieldId].fieldType : undefined),
-    [currentFieldId, fields]
-  );
-
-  useEffect(() => {
-    if (data) {
-      setCurrentFieldId(data.fieldId);
-      setCurrentOrder(data.order);
-    } else {
-      setCurrentFieldId(null);
-      setCurrentOrder(null);
-    }
-  }, [data]);
-
-  useEffect(() => {
-    if (currentFieldId && currentOrder !== null) {
-      onSave({
-        id: data?.id,
-        fieldId: currentFieldId,
-        order: currentOrder,
-        fieldType: fields[currentFieldId].fieldType,
-      });
-    }
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [currentFieldId, currentOrder]);
-
-  const onSelectFieldClick = (id: string) => {
-    setCurrentFieldId(id);
-    // set ascending order by default
-    setCurrentOrder(SortConditionPB.Ascending);
-  };
-
-  const onSelectOrderClick = (order: SortConditionPB) => {
-    setCurrentOrder(order);
-  };
-
-  return (
-    <div className={'flex items-center gap-4'}>
-      <button className={'flex-shrink-0 rounded p-1 hover:bg-fill-list-hover'}>
-        <i className={'block h-[16px] w-[16px]'}>
-          <DragElementSvg></DragElementSvg>
-        </i>
-      </button>
-
-      <FieldSelect
-        columns={supportedColumns}
-        fields={fields}
-        onSelectFieldClick={onSelectFieldClick}
-        currentFieldId={currentFieldId}
-        currentFieldType={currentFieldType}
-      ></FieldSelect>
-
-      <OrderSelect currentOrder={currentOrder} onSelectOrderClick={onSelectOrderClick}></OrderSelect>
-
-      <button
-        onClick={() => onDelete?.()}
-        className={`rounded p-1 hover:bg-fill-list-hover ${data ? 'opacity-100' : 'opacity-0'}`}
-      >
-        <i className={'block h-[16px] w-[16px]'}>
-          <TrashSvg />
-        </i>
-      </button>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/DatabaseSortPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/DatabaseSortPopup.tsx
deleted file mode 100644
index 98247e3a1a..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/DatabaseSortPopup.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import { t } from 'i18next';
-import { MouseEventHandler, useMemo, useState } from 'react';
-import { useAppSelector } from '$app/stores/store';
-import { IDatabaseSort } from '$app_reducers/database/slice';
-import { DatabaseSortItem } from '$app/components/_shared/DatabaseSort/DatabaseSortItem';
-import AddSvg from '$app/components/_shared/svg/AddSvg';
-import { SortController } from '$app/stores/effects/database/sort/sort_controller';
-
-export const DatabaseSortPopup = ({
-  sortController,
-  onOutsideClick,
-}: {
-  sortController: SortController;
-  onOutsideClick: () => void;
-}) => {
-  // stores
-  const sortStore = useAppSelector((state) => state.database.sort);
-  const [sort, setSort] = useState<(IDatabaseSort | null)[]>(sortStore);
-
-  const [showBlankSort, setShowBlankSort] = useState(sortStore.length === 0);
-
-  const onSaveSortItem = async (sortItem: IDatabaseSort) => {
-    let updatedSort = sortItem;
-
-    if (sortItem.id) {
-      await sortController.updateSort(sortItem.id, sortItem.fieldId, sortItem.fieldType, sortItem.order);
-    } else {
-      const newId = await sortController.addSort(sortItem.fieldId, sortItem.fieldType, sortItem.order);
-
-      updatedSort = { ...updatedSort, id: newId };
-    }
-
-    // update local copy
-    const index = sort.findIndex((s) => s?.fieldId === sortItem.fieldId);
-
-    if (index === -1) {
-      setSort([...sort, updatedSort]);
-    } else {
-      setSort([...sort.slice(0, index), updatedSort, ...sort.slice(index + 1)]);
-    }
-
-    setShowBlankSort(false);
-  };
-
-  const onDeleteClick = async (sortItem: IDatabaseSort | null) => {
-    if (!sortItem || !sortItem.id) return;
-
-    // add blank sort if no sorts left
-    if (sort.length === 1) {
-      setShowBlankSort(true);
-    }
-
-    await sortController.removeSort(sortItem.fieldId, sortItem.fieldType, sortItem.id);
-
-    const index = sort.findIndex((s) => s?.fieldId === sortItem.fieldId);
-
-    setSort([...sort.slice(0, index), ...sort.slice(index + 1)]);
-  };
-
-  const onAddClick: MouseEventHandler = () => {
-    setShowBlankSort(true);
-  };
-
-  const rows = useMemo(() => (showBlankSort ? [...sort, null] : sort), [sort, showBlankSort]);
-
-  return (
-    <div
-      className={'fixed inset-0 z-10 flex items-center justify-center overflow-y-auto backdrop-blur-sm'}
-      onClick={onOutsideClick}
-    >
-      <div onClick={(e) => e.stopPropagation()} className='flex flex-col rounded-lg bg-white shadow-md'>
-        <div className='px-6 pt-6 text-sm text-text-caption'>{t('grid.settings.sort')}</div>
-
-        <div className='flex flex-col gap-3 overflow-y-scroll px-6 py-6 text-sm'>
-          {rows.map((sortItem, index) => (
-            <DatabaseSortItem
-              key={index}
-              data={sortItem}
-              onSave={onSaveSortItem}
-              onDelete={() => onDeleteClick(sortItem)}
-            />
-          ))}
-        </div>
-
-        <hr />
-
-        <button
-          onClick={onAddClick}
-          className='flex cursor-pointer items-center gap-2 px-6 py-6 text-sm text-text-caption'
-        >
-          <div className='h-5 w-5'>
-            <AddSvg />
-          </div>
-          {t('grid.sort.addSort')}
-        </button>
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/OrderSelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/OrderSelect.tsx
deleted file mode 100644
index c0057371d6..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/DatabaseSort/OrderSelect.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import ButtonPopoverList from '$app/components/_shared/ButtonPopoverList';
-import React, { useState } from 'react';
-import { SortConditionPB } from '@/services/backend';
-import { SortAscSvg } from '$app/components/_shared/svg/SortAscSvg';
-import { SortDescSvg } from '$app/components/_shared/svg/SortDescSvg';
-import { DropDownShowSvg } from '$app/components/_shared/svg/DropDownShowSvg';
-
-interface IOrderSelectProps {
-  currentOrder: SortConditionPB | null;
-  onSelectOrderClick: (order: SortConditionPB) => void;
-}
-
-const WIDTH = 180;
-
-export const OrderSelect = ({ currentOrder, onSelectOrderClick }: IOrderSelectProps) => {
-  const [showSelect, setShowSelect] = useState(false);
-
-  return (
-    <ButtonPopoverList
-      isVisible={true}
-      popoverOptions={[
-        {
-          icon: (
-            <i className={'block h-5 w-5'}>
-              <SortAscSvg></SortAscSvg>
-            </i>
-          ),
-          label: 'Ascending',
-          key: SortConditionPB.Ascending,
-          onClick: () => {
-            onSelectOrderClick(SortConditionPB.Ascending);
-            setShowSelect(false);
-          },
-        },
-        {
-          icon: (
-            <i className={'block h-5 w-5'}>
-              <SortDescSvg></SortDescSvg>
-            </i>
-          ),
-          label: 'Descending',
-          key: SortConditionPB.Descending,
-          onClick: () => {
-            onSelectOrderClick(SortConditionPB.Descending);
-            setShowSelect(false);
-          },
-        },
-      ]}
-      popoverOrigin={{
-        anchorOrigin: {
-          vertical: 'bottom',
-          horizontal: 'left',
-        },
-        transformOrigin: {
-          vertical: 'top',
-          horizontal: 'left',
-        },
-      }}
-      onClose={() => setShowSelect(false)}
-      sx={{ width: `${WIDTH}px` }}
-    >
-      <div
-        onClick={() => setShowSelect(true)}
-        className={`flex w-[180px] items-center justify-between rounded-lg border px-2 py-1 ${
-          showSelect ? 'border-fill-hover' : 'border-line-border'
-        }`}
-      >
-        {currentOrder !== null ? (
-          <SortLabel value={currentOrder}></SortLabel>
-        ) : (
-          <span className={'text-text-caption'}>Select order</span>
-        )}
-        <i className={`h-5 w-5 transition-transform duration-500 ${showSelect ? 'rotate-180' : 'rotate-0'}`}>
-          <DropDownShowSvg></DropDownShowSvg>
-        </i>
-      </div>
-    </ButtonPopoverList>
-  );
-};
-
-const SortLabel = ({ value }: { value: SortConditionPB }) => {
-  return value === SortConditionPB.Ascending ? (
-    <div className={'flex items-center gap-2'}>
-      <i className={'block h-5 w-5'}>
-        <SortAscSvg></SortAscSvg>
-      </i>
-      <span>Ascending</span>
-    </div>
-  ) : (
-    <div className={'flex items-center gap-2'}>
-      <i className={'block h-5 w-5'}>
-        <SortDescSvg></SortDescSvg>
-      </i>
-      <span>Descending</span>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/ChangeFieldTypePopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/ChangeFieldTypePopup.tsx
deleted file mode 100644
index 9f94ddd61d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/ChangeFieldTypePopup.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { FieldType } from '@/services/backend';
-import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
-import { FieldTypeName } from '$app/components/_shared/EditRow/FieldTypeName';
-import { Popover } from '@mui/material';
-
-const typesOrder: FieldType[] = [
-  FieldType.RichText,
-  FieldType.Number,
-  FieldType.DateTime,
-  FieldType.SingleSelect,
-  FieldType.MultiSelect,
-  FieldType.Checkbox,
-  FieldType.URL,
-  FieldType.Checklist,
-];
-
-export const ChangeFieldTypePopup = ({
-  open,
-  anchorEl,
-  onClick,
-  onOutsideClick,
-}: {
-  open: boolean;
-  anchorEl: HTMLDivElement | null;
-  onClick: (newType: FieldType) => void;
-  onOutsideClick: () => void;
-}) => {
-  return (
-    <Popover
-      open={open}
-      anchorEl={anchorEl}
-      anchorOrigin={{
-        vertical: 'top',
-        horizontal: 'right',
-      }}
-      transformOrigin={{
-        vertical: 'top',
-        horizontal: 'left',
-      }}
-      onClose={onOutsideClick}
-    >
-      <div className={'flex flex-col p-2 text-xs'}>
-        {typesOrder.map((t, i) => (
-          <button
-            onClick={() => onClick(t)}
-            key={i}
-            className={'flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 pr-8 hover:bg-fill-list-hover'}
-          >
-            <i className={'h-5 w-5'}>
-              <FieldTypeIcon fieldType={t}></FieldTypeIcon>
-            </i>
-            <span>
-              <FieldTypeName fieldType={t}></FieldTypeName>
-            </span>
-          </button>
-        ))}
-      </div>
-    </Popover>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckList.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckList.tsx
deleted file mode 100644
index 9bd43fd330..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckList.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { SelectOptionCellDataPB } from '@/services/backend';
-import { useEffect, useRef, useState } from 'react';
-import { ISelectOptionType } from '$app_reducers/database/slice';
-import { useAppSelector } from '$app/stores/store';
-import { CheckListProgress } from '$app/components/_shared/CheckListProgress';
-
-export const CheckList = ({
-  data,
-  fieldId,
-  onEditClick,
-}: {
-  data: SelectOptionCellDataPB | undefined;
-  fieldId: string;
-  onEditClick: (left: number, top: number) => void;
-}) => {
-  const ref = useRef<HTMLDivElement>(null);
-  const [allOptionsCount, setAllOptionsCount] = useState(0);
-  const [selectedOptionsCount, setSelectedOptionsCount] = useState(0);
-  const databaseStore = useAppSelector((state) => state.database);
-
-  useEffect(() => {
-    setAllOptionsCount((databaseStore.fields[fieldId]?.fieldOptions as ISelectOptionType)?.selectOptions?.length ?? 0);
-  }, [databaseStore, fieldId]);
-
-  useEffect(() => {
-    setSelectedOptionsCount((data as SelectOptionCellDataPB)?.select_options?.length ?? 0);
-  }, [data]);
-
-  const onClick = () => {
-    if (!ref.current) return;
-    const { left, top } = ref.current.getBoundingClientRect();
-
-    onEditClick(left, top);
-  };
-
-  return (
-    <div
-      ref={ref}
-      onClick={onClick}
-      className={'flex w-full flex-wrap items-center gap-2 px-4 py-1 text-xs text-text-title'}
-    >
-      <CheckListProgress completed={selectedOptionsCount} max={allOptionsCount} />
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListOption.tsx
deleted file mode 100644
index a897f91400..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListOption.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { SelectOptionPB } from '@/services/backend';
-import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg';
-import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
-import { Details2Svg } from '$app/components/_shared/svg/Details2Svg';
-import { ISelectOption } from '$app_reducers/database/slice';
-import { MouseEventHandler } from 'react';
-
-export const CheckListOption = ({
-  option,
-  checked,
-  onToggleOptionClick,
-  openCheckListDetail,
-}: {
-  option: ISelectOption;
-  checked: boolean;
-  onToggleOptionClick: (v: SelectOptionPB) => void;
-  openCheckListDetail: (left: number, top: number, option: SelectOptionPB) => void;
-}) => {
-  const onCheckListDetailClick: MouseEventHandler = (e) => {
-    e.stopPropagation();
-    let target = e.target as HTMLElement;
-
-    while (!(target instanceof HTMLButtonElement)) {
-      if (target.parentElement === null) return;
-      target = target.parentElement;
-    }
-
-    const selectOption = new SelectOptionPB({
-      id: option.selectOptionId,
-      name: option.title,
-    });
-
-    const { right: _left, top: _top } = target.getBoundingClientRect();
-
-    openCheckListDetail(_left, _top, selectOption);
-  };
-
-  return (
-    <div
-      className={'flex cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-fill-list-hover'}
-      onClick={() =>
-        onToggleOptionClick(
-          new SelectOptionPB({
-            id: option.selectOptionId,
-            name: option.title,
-          })
-        )
-      }
-    >
-      <div className={'h-5 w-5'}>
-        {checked ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>}
-      </div>
-      <div className={`flex-1 px-2 py-0.5`}>{option.title}</div>
-      <div className={'flex items-center'}>
-        <button onClick={onCheckListDetailClick} className={'h-6 w-6 p-1'}>
-          <Details2Svg></Details2Svg>
-        </button>
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListPopup.tsx
deleted file mode 100644
index 0bf50c824d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/CheckListPopup.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { SelectOptionCellDataPB, SelectOptionPB } from '@/services/backend';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { ISelectOptionType } from '$app_reducers/database/slice';
-import { useAppSelector } from '$app/stores/store';
-import { useCell } from '$app/components/_shared/database-hooks/useCell';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { useEffect, useState } from 'react';
-import { CheckListProgress } from '$app/components/_shared/CheckListProgress';
-import { NewCheckListOption } from '$app/components/_shared/EditRow/CheckList/NewCheckListOption';
-import { CheckListOption } from '$app/components/_shared/EditRow/CheckList/CheckListOption';
-import { NewCheckListButton } from '$app/components/_shared/EditRow/CheckList/NewCheckListButton';
-
-export const CheckListPopup = ({
-  left,
-  top,
-  cellIdentifier,
-  cellCache,
-  fieldController,
-  openCheckListDetail,
-  onOutsideClick,
-}: {
-  left: number;
-  top: number;
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-  openCheckListDetail: (left: number, top: number, option: SelectOptionPB) => void;
-  onOutsideClick: () => void;
-}) => {
-  const databaseStore = useAppSelector((state) => state.database);
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-
-  const [allOptionsCount, setAllOptionsCount] = useState(0);
-  const [selectedOptionsCount, setSelectedOptionsCount] = useState(0);
-  const [newOptions, setNewOptions] = useState<string[]>([]);
-
-  useEffect(() => {
-    setAllOptionsCount(
-      (databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType)?.selectOptions?.length ?? 0
-    );
-  }, [databaseStore, cellIdentifier]);
-
-  useEffect(() => {
-    setSelectedOptionsCount((data as SelectOptionCellDataPB)?.select_options?.length ?? 0);
-  }, [data]);
-
-  const onToggleOptionClick = async (option: SelectOptionPB) => {
-    if ((data as SelectOptionCellDataPB)?.select_options?.find((selectedOption) => selectedOption.id === option.id)) {
-      await new SelectOptionCellBackendService(cellIdentifier).unselectOption([option.id]);
-    } else {
-      await new SelectOptionCellBackendService(cellIdentifier).selectOption([option.id]);
-    }
-  };
-
-  return (
-    <PopupWindow className={'text-xs'} onOutsideClick={onOutsideClick} left={left} top={top}>
-      <div className={'min-w-[320px]'}>
-        <div className={'px-4 pb-4 pt-8'}>
-          <CheckListProgress completed={selectedOptionsCount} max={allOptionsCount} />
-        </div>
-
-        <div className={'flex flex-col p-2'}>
-          {(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType).selectOptions.map(
-            (option, index) => (
-              <CheckListOption
-                key={index}
-                option={option}
-                checked={
-                  !!(data as SelectOptionCellDataPB)?.select_options?.find((so) => so.id === option.selectOptionId)
-                }
-                onToggleOptionClick={onToggleOptionClick}
-                openCheckListDetail={openCheckListDetail}
-              ></CheckListOption>
-            )
-          )}
-          {newOptions.map((option, index) => (
-            <NewCheckListOption
-              key={index}
-              index={index}
-              option={option}
-              newOptions={newOptions}
-              setNewOptions={setNewOptions}
-              cellIdentifier={cellIdentifier}
-            ></NewCheckListOption>
-          ))}
-        </div>
-        <div className={'h-[1px] bg-line-divider'}></div>
-        <div className={'p-2'}>
-          <NewCheckListButton newOptions={newOptions} setNewOptions={setNewOptions}></NewCheckListButton>
-        </div>
-      </div>
-    </PopupWindow>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/EditCheckListPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/EditCheckListPopup.tsx
deleted file mode 100644
index 4dbd45712e..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/EditCheckListPopup.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { KeyboardEventHandler, useEffect, useRef, useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { SelectOptionPB } from '@/services/backend';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-
-export const EditCheckListPopup = ({
-  left,
-  top,
-  cellIdentifier,
-  editingSelectOption,
-  onOutsideClick,
-}: {
-  left: number;
-  top: number;
-  cellIdentifier: CellIdentifier;
-  editingSelectOption: SelectOptionPB;
-  onOutsideClick: () => void;
-}) => {
-  const inputRef = useRef<HTMLInputElement>(null);
-  const { t } = useTranslation();
-  const [value, setValue] = useState('');
-
-  useEffect(() => {
-    setValue(editingSelectOption.name);
-  }, [editingSelectOption]);
-
-  const onKeyDown: KeyboardEventHandler = async (e) => {
-    if (e.key === 'Enter' && value.length > 0) {
-      await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: value });
-      setValue('');
-    }
-  };
-
-  const onKeyDownWrapper: KeyboardEventHandler = (e) => {
-    if (e.key === 'Escape') {
-      onOutsideClick();
-    }
-  };
-
-  const onBlur = async () => {
-    const svc = new SelectOptionCellBackendService(cellIdentifier);
-
-    await svc.updateOption(
-      new SelectOptionPB({
-        id: editingSelectOption.id,
-        name: value,
-      })
-    );
-  };
-
-  const onDeleteOptionClick = async () => {
-    const svc = new SelectOptionCellBackendService(cellIdentifier);
-
-    await svc.deleteOption([editingSelectOption]);
-    onOutsideClick();
-  };
-
-  return (
-    <PopupWindow
-      className={'p-2 text-xs'}
-      onOutsideClick={async () => {
-        await onBlur();
-        onOutsideClick();
-      }}
-      left={left}
-      top={top}
-    >
-      <div onKeyDown={onKeyDownWrapper} className={'flex flex-col gap-2 p-2'}>
-        <div className={'flex flex-1 items-center gap-2 rounded border border-line-divider bg-fill-list-hover px-2 '}>
-          <input
-            ref={inputRef}
-            className={'py-2'}
-            value={value}
-            onChange={(e) => setValue(e.target.value)}
-            onKeyDown={onKeyDown}
-            onBlur={() => onBlur()}
-          />
-          <div className={'font-mono text-text-caption'}>{value.length}/30</div>
-        </div>
-        <button
-          onClick={() => onDeleteOptionClick()}
-          className={
-            'flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 text-fill-default hover:bg-fill-list-hover'
-          }
-        >
-          <i className={'h-5 w-5'}>
-            <TrashSvg></TrashSvg>
-          </i>
-          <span>{t('grid.selectOption.deleteTag')}</span>
-        </button>
-      </div>
-    </PopupWindow>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListButton.tsx
deleted file mode 100644
index 898fb248dc..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListButton.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import AddSvg from '$app/components/_shared/svg/AddSvg';
-import { useTranslation } from 'react-i18next';
-
-export const NewCheckListButton = ({
-  newOptions,
-  setNewOptions,
-}: {
-  newOptions: string[];
-  setNewOptions: (v: string[]) => void;
-}) => {
-  const { t } = useTranslation();
-
-  const newOptionClick = () => {
-    setNewOptions([...newOptions, '']);
-  };
-
-  return (
-    <button
-      onClick={() => newOptionClick()}
-      className={'flex w-full items-center gap-2 rounded-lg px-2 py-2 hover:bg-line-divider'}
-    >
-      <i className={'h-5 w-5'}>
-        <AddSvg></AddSvg>
-      </i>
-      <span>{t('grid.field.addOption')}</span>
-    </button>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListOption.tsx
deleted file mode 100644
index 940929660a..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/CheckList/NewCheckListOption.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { useTranslation } from 'react-i18next';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-
-export const NewCheckListOption = ({
-  index,
-  option,
-  newOptions,
-  setNewOptions,
-  cellIdentifier,
-}: {
-  index: number;
-  option: string;
-  newOptions: string[];
-  setNewOptions: (v: string[]) => void;
-  cellIdentifier: CellIdentifier;
-}) => {
-  const { t } = useTranslation();
-
-  const updateNewOption = (value: string) => {
-    const newOptionsCopy = [...newOptions];
-
-    newOptionsCopy[index] = value;
-    setNewOptions(newOptionsCopy);
-  };
-
-  const onNewOptionKeyDown = (e: KeyboardEvent) => {
-    if (e.key === 'Enter') {
-      void onSaveNewOptionClick();
-    }
-  };
-
-  const onSaveNewOptionClick = async () => {
-    await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: newOptions[index] });
-    setNewOptions(newOptions.filter((_, i) => i !== index));
-  };
-
-  return (
-    <div className={'flex cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-line-divider'}>
-      <input
-        onKeyDown={(e) => onNewOptionKeyDown(e as unknown as KeyboardEvent)}
-        className={'min-w-0 flex-1 pl-7'}
-        value={option}
-        onChange={(e) => updateNewOption(e.target.value)}
-      />
-      <button
-        onClick={() => onSaveNewOptionClick()}
-        className={'flex items-center gap-2 rounded-lg bg-fill-hover px-4 py-2 text-white hover:bg-main-hovered'}
-      >
-        {t('grid.selectOption.create')}
-      </button>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateFormatPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateFormatPopup.tsx
deleted file mode 100644
index 58e68fd281..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateFormatPopup.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg';
-import { useTranslation } from 'react-i18next';
-import { DateFormatPB } from '@/services/backend';
-import { useDateTimeFormat } from '$app/components/_shared/EditRow/Date/DateTimeFormat.hooks';
-import { useAppSelector } from '$app/stores/store';
-import { useEffect, useState } from 'react';
-import { IDateType } from '$app_reducers/database/slice';
-
-export const DateFormatPopup = ({
-  left,
-  top,
-  cellIdentifier,
-  fieldController,
-  onOutsideClick,
-}: {
-  left: number;
-  top: number;
-  cellIdentifier: CellIdentifier;
-  fieldController: FieldController;
-  onOutsideClick: () => void;
-}) => {
-  const { t } = useTranslation();
-  const { changeDateFormat } = useDateTimeFormat(cellIdentifier, fieldController);
-  const databaseStore = useAppSelector((state) => state.database);
-  const [dateType, setDateType] = useState<IDateType | undefined>();
-
-  useEffect(() => {
-    setDateType(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as IDateType);
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [databaseStore]);
-
-  const changeFormat = async (format: DateFormatPB) => {
-    await changeDateFormat(format);
-    onOutsideClick();
-  };
-
-  return (
-    <PopupWindow className={'p-2 text-xs'} onOutsideClick={onOutsideClick} left={left} top={top}>
-      <PopupItem
-        changeFormat={changeFormat}
-        format={DateFormatPB.Friendly}
-        checked={dateType?.dateFormat === DateFormatPB.Friendly}
-        text={t('grid.field.dateFormatFriendly')}
-      />
-      <PopupItem
-        changeFormat={changeFormat}
-        format={DateFormatPB.ISO}
-        checked={dateType?.dateFormat === DateFormatPB.ISO}
-        text={t('grid.field.dateFormatISO')}
-      />
-      <PopupItem
-        changeFormat={changeFormat}
-        format={DateFormatPB.Local}
-        checked={dateType?.dateFormat === DateFormatPB.Local}
-        text={t('grid.field.dateFormatLocal')}
-      />
-      <PopupItem
-        changeFormat={changeFormat}
-        format={DateFormatPB.US}
-        checked={dateType?.dateFormat === DateFormatPB.US}
-        text={t('grid.field.dateFormatUS')}
-      />
-    </PopupWindow>
-  );
-};
-
-function PopupItem({
-  format,
-  text,
-  changeFormat,
-  checked,
-}: {
-  format: DateFormatPB;
-  text: string;
-  changeFormat: (_: DateFormatPB) => Promise<void>;
-  checked: boolean;
-}) {
-  return (
-    <button
-      onClick={() => changeFormat(format)}
-      className={
-        'flex w-full cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-fill-list-hover'
-      }
-    >
-      {text}
-
-      {checked && (
-        <div className={'ml-8 h-5 w-5 p-1'}>
-          <CheckmarkSvg></CheckmarkSvg>
-        </div>
-      )}
-    </button>
-  );
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DatePickerPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DatePickerPopup.tsx
deleted file mode 100644
index 8d5de41e41..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DatePickerPopup.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { useEffect, useState } from 'react';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import Calendar from 'react-calendar';
-import dayjs from 'dayjs';
-import { useCell } from '$app/components/_shared/database-hooks/useCell';
-import { CalendarData } from '$app/stores/effects/database/cell/controller_builder';
-import { DateCellDataPB } from '@/services/backend';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { DateTypeOptions } from '$app/components/_shared/EditRow/Date/DateTypeOptions';
-
-export const DatePickerPopup = ({
-  left,
-  top,
-  cellIdentifier,
-  cellCache,
-  fieldController,
-  onOutsideClick,
-}: {
-  left: number;
-  top: number;
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-  onOutsideClick: () => void;
-}) => {
-  const { data, cellController } = useCell(cellIdentifier, cellCache, fieldController);
-  const [selectedDate, setSelectedDate] = useState<Date>(new Date());
-
-  useEffect(() => {
-    const date_pb = data as DateCellDataPB | undefined;
-
-    if (!date_pb || !date_pb?.date.length) return;
-
-    setSelectedDate(dayjs(date_pb.date).toDate());
-  }, [data]);
-
-  const onChange = async (v: Date | null | (Date | null)[]) => {
-    if (v instanceof Date) {
-      setSelectedDate(v);
-      const date = new CalendarData(dayjs(v).add(dayjs().utcOffset(), 'minutes').toDate(), false);
-
-      await cellController?.saveCellData(date);
-    }
-  };
-
-  return (
-    <PopupWindow className={'p-2 text-xs'} onOutsideClick={onOutsideClick} left={left} top={top}>
-      <div className={'px-2 pb-2'}>
-        <Calendar onChange={(d) => onChange(d)} value={selectedDate} />
-      </div>
-      <DateTypeOptions cellIdentifier={cellIdentifier} fieldController={fieldController}></DateTypeOptions>
-    </PopupWindow>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTimeFormat.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTimeFormat.hooks.ts
deleted file mode 100644
index 55eb3597da..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTimeFormat.hooks.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { Some } from 'ts-results';
-import { DateFormatPB, DateTypeOptionPB, FieldType, TimeFormatPB } from '@/services/backend';
-import { makeDateTypeOptionContext } from '$app/stores/effects/database/field/type_option/type_option_context';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-
-export const useDateTimeFormat = (cellIdentifier: CellIdentifier, fieldController: FieldController) => {
-  const changeFormat = async (change: (option: DateTypeOptionPB) => void) => {
-    const fieldInfo = fieldController.getField(cellIdentifier.fieldId);
-
-    if (!fieldInfo) return;
-    const typeOptionController = new TypeOptionController(cellIdentifier.viewId, Some(fieldInfo), FieldType.DateTime);
-
-    await typeOptionController.initialize();
-    const dateTypeOptionContext = makeDateTypeOptionContext(typeOptionController);
-    const typeOption = dateTypeOptionContext.getTypeOption();
-
-    change(typeOption);
-    await dateTypeOptionContext.setTypeOption(typeOption);
-  };
-
-  const changeDateFormat = async (format: DateFormatPB) => {
-    await changeFormat((option) => (option.date_format = format));
-  };
-
-  const changeTimeFormat = async (format: TimeFormatPB) => {
-    await changeFormat((option) => (option.time_format = format));
-  };
-
-  const includeTime = async (_include: boolean) => {
-    await changeFormat((_option) => {
-      // option.include_time = include;
-    });
-  };
-
-  return {
-    changeDateFormat,
-    changeTimeFormat,
-    includeTime,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTypeOptions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTypeOptions.tsx
deleted file mode 100644
index c5e813b8b5..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/DateTypeOptions.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-import { DateFormatPopup } from '$app/components/_shared/EditRow/Date/DateFormatPopup';
-import { TimeFormatPopup } from '$app/components/_shared/EditRow/Date/TimeFormatPopup';
-import { MoreSvg } from '$app/components/_shared/svg/MoreSvg';
-import { MouseEventHandler, useEffect, useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { IDateType } from '$app_reducers/database/slice';
-import { useAppSelector } from '$app/stores/store';
-import { useDateTimeFormat } from '$app/components/_shared/EditRow/Date/DateTimeFormat.hooks';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-
-export const DateTypeOptions = ({
-  cellIdentifier,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  fieldController: FieldController;
-}) => {
-  const { t } = useTranslation();
-
-  const [showDateFormatPopup, setShowDateFormatPopup] = useState(false);
-  const [dateFormatTop, setDateFormatTop] = useState(0);
-  const [dateFormatLeft, setDateFormatLeft] = useState(0);
-
-  const [showTimeFormatPopup, setShowTimeFormatPopup] = useState(false);
-  const [timeFormatTop, setTimeFormatTop] = useState(0);
-  const [timeFormatLeft, setTimeFormatLeft] = useState(0);
-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  const [dateType, setDateType] = useState<IDateType | undefined>();
-
-  const databaseStore = useAppSelector((state) => state.database);
-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  const { includeTime } = useDateTimeFormat(cellIdentifier, fieldController);
-
-  useEffect(() => {
-    setDateType(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as IDateType);
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [databaseStore]);
-
-  const onDateFormatClick = (_left: number, _top: number) => {
-    setShowDateFormatPopup(true);
-    setDateFormatLeft(_left + 10);
-    setDateFormatTop(_top);
-  };
-
-  const onTimeFormatClick = (_left: number, _top: number) => {
-    setShowTimeFormatPopup(true);
-    setTimeFormatLeft(_left + 10);
-    setTimeFormatTop(_top);
-  };
-
-  const _onDateFormatClick: MouseEventHandler = (e) => {
-    e.stopPropagation();
-    let target = e.target as HTMLElement;
-
-    while (!(target instanceof HTMLButtonElement)) {
-      if (target.parentElement === null) return;
-      target = target.parentElement;
-    }
-
-    const { right: _left, top: _top } = target.getBoundingClientRect();
-
-    onDateFormatClick(_left, _top);
-  };
-
-  const _onTimeFormatClick: MouseEventHandler = (e) => {
-    e.stopPropagation();
-    let target = e.target as HTMLElement;
-
-    while (!(target instanceof HTMLButtonElement)) {
-      if (target.parentElement === null) return;
-      target = target.parentElement;
-    }
-
-    const { right: _left, top: _top } = target.getBoundingClientRect();
-
-    onTimeFormatClick(_left, _top);
-  };
-
-  const toggleIncludeTime = async () => {
-    // if (dateType?.includeTime) {
-    //   await includeTime(false);
-    // } else {
-    //   await includeTime(true);
-    // }
-  };
-
-  return (
-    <div className={'flex flex-col'}>
-      <hr className={'-mx-2 my-2 border-line-divider'} />
-      <button
-        onClick={_onDateFormatClick}
-        className={
-          'flex w-full cursor-pointer items-center justify-between rounded-lg px-2 py-2 hover:bg-fill-list-hover'
-        }
-      >
-        <span>{t('grid.field.dateFormat')}</span>
-        <i className={'h-5 w-5'}>
-          <MoreSvg></MoreSvg>
-        </i>
-      </button>
-      <hr className={'-mx-2 my-2 border-line-divider'} />
-      <button
-        onClick={() => toggleIncludeTime()}
-        className={
-          'flex w-full cursor-pointer items-center justify-between rounded-lg px-2 py-2 hover:bg-fill-list-hover'
-        }
-      >
-        <div className={'flex items-center gap-2'}>
-          <span>{t('grid.field.includeTime')}</span>
-        </div>
-        {/*<i className={'h-5 w-5'}>*/}
-        {/*  {dateType?.includeTime ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>}*/}
-        {/*</i>*/}
-      </button>
-
-      <button
-        onClick={_onTimeFormatClick}
-        className={
-          'flex w-full cursor-pointer items-center justify-between rounded-lg px-2 py-2 hover:bg-fill-list-hover'
-        }
-      >
-        <span>{t('grid.field.timeFormat')}</span>
-        <i className={'h-5 w-5'}>
-          <MoreSvg></MoreSvg>
-        </i>
-      </button>
-      {showDateFormatPopup && (
-        <DateFormatPopup
-          top={dateFormatTop}
-          left={dateFormatLeft}
-          cellIdentifier={cellIdentifier}
-          fieldController={fieldController}
-          onOutsideClick={() => setShowDateFormatPopup(false)}
-        ></DateFormatPopup>
-      )}
-      {showTimeFormatPopup && (
-        <TimeFormatPopup
-          top={timeFormatTop}
-          left={timeFormatLeft}
-          cellIdentifier={cellIdentifier}
-          fieldController={fieldController}
-          onOutsideClick={() => setShowTimeFormatPopup(false)}
-        ></TimeFormatPopup>
-      )}
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/EditCellDate.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/EditCellDate.tsx
deleted file mode 100644
index 1fb6656c6f..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/EditCellDate.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { MouseEventHandler, useRef } from 'react';
-import { DateCellDataPB } from '@/services/backend';
-
-export const EditCellDate = ({
-  data,
-  onEditClick,
-}: {
-  data?: DateCellDataPB;
-  onEditClick: (left: number, top: number) => void;
-}) => {
-  const ref = useRef<HTMLDivElement>(null);
-
-  const onClick: MouseEventHandler = () => {
-    if (!ref.current) return;
-    const { left, top } = ref.current.getBoundingClientRect();
-
-    onEditClick(left, top);
-  };
-
-  return (
-    <div ref={ref} onClick={onClick} className={'w-full px-4 py-1'}>
-      {data?.date}&nbsp;
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormat.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormat.hooks.ts
deleted file mode 100644
index ad91aa1bd9..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormat.hooks.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { FieldType, NumberFormatPB } from '@/services/backend';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { Some } from 'ts-results';
-import { makeNumberTypeOptionContext } from '$app/stores/effects/database/field/type_option/type_option_context';
-
-export const useNumberFormat = (cellIdentifier: CellIdentifier, fieldController: FieldController) => {
-  const changeNumberFormat = async (format: NumberFormatPB) => {
-    const fieldInfo = fieldController.getField(cellIdentifier.fieldId);
-
-    if (!fieldInfo) return;
-    const typeOptionController = new TypeOptionController(cellIdentifier.viewId, Some(fieldInfo), FieldType.Number);
-
-    await typeOptionController.initialize();
-    const numberTypeOptionContext = makeNumberTypeOptionContext(typeOptionController);
-    const typeOption = numberTypeOptionContext.getTypeOption();
-
-    typeOption.format = format;
-    await numberTypeOptionContext.setTypeOption(typeOption);
-  };
-
-  return {
-    changeNumberFormat,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormatPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormatPopup.tsx
deleted file mode 100644
index df4749befc..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/NumberFormatPopup.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { useNumberFormat } from '$app/components/_shared/EditRow/Date/NumberFormat.hooks';
-import { NumberFormatPB } from '@/services/backend';
-import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg';
-import { useAppSelector } from '$app/stores/store';
-import { useEffect, useState } from 'react';
-import { INumberType } from '$app_reducers/database/slice';
-
-const list = [
-  { format: NumberFormatPB.Num, title: 'Num' },
-  { format: NumberFormatPB.USD, title: 'USD' },
-  { format: NumberFormatPB.CanadianDollar, title: 'CanadianDollar' },
-  { format: NumberFormatPB.EUR, title: 'EUR' },
-  { format: NumberFormatPB.Pound, title: 'Pound' },
-  { format: NumberFormatPB.Yen, title: 'Yen' },
-  { format: NumberFormatPB.Ruble, title: 'Ruble' },
-  { format: NumberFormatPB.Rupee, title: 'Rupee' },
-  { format: NumberFormatPB.Won, title: 'Won' },
-  { format: NumberFormatPB.Yuan, title: 'Yuan' },
-  { format: NumberFormatPB.Real, title: 'Real' },
-  { format: NumberFormatPB.Lira, title: 'Lira' },
-  { format: NumberFormatPB.Rupiah, title: 'Rupiah' },
-  { format: NumberFormatPB.Franc, title: 'Franc' },
-  { format: NumberFormatPB.HongKongDollar, title: 'HongKongDollar' },
-  { format: NumberFormatPB.NewZealandDollar, title: 'NewZealandDollar' },
-  { format: NumberFormatPB.Krona, title: 'Krona' },
-  { format: NumberFormatPB.NorwegianKrone, title: 'NorwegianKrone' },
-  { format: NumberFormatPB.MexicanPeso, title: 'MexicanPeso' },
-  { format: NumberFormatPB.Rand, title: 'Rand' },
-  { format: NumberFormatPB.NewTaiwanDollar, title: 'NewTaiwanDollar' },
-  { format: NumberFormatPB.DanishKrone, title: 'DanishKrone' },
-  { format: NumberFormatPB.Baht, title: 'Baht' },
-  { format: NumberFormatPB.Forint, title: 'Forint' },
-  { format: NumberFormatPB.Koruna, title: 'Koruna' },
-  { format: NumberFormatPB.Shekel, title: 'Shekel' },
-  { format: NumberFormatPB.ChileanPeso, title: 'ChileanPeso' },
-  { format: NumberFormatPB.PhilippinePeso, title: 'PhilippinePeso' },
-  { format: NumberFormatPB.Dirham, title: 'Dirham' },
-  { format: NumberFormatPB.ColombianPeso, title: 'ColombianPeso' },
-  { format: NumberFormatPB.Riyal, title: 'Riyal' },
-  { format: NumberFormatPB.Ringgit, title: 'Ringgit' },
-  { format: NumberFormatPB.Leu, title: 'Leu' },
-  { format: NumberFormatPB.ArgentinePeso, title: 'ArgentinePeso' },
-  { format: NumberFormatPB.UruguayanPeso, title: 'UruguayanPeso' },
-  { format: NumberFormatPB.Percent, title: 'Percent' },
-];
-
-export const NumberFormatPopup = ({
-  left,
-  top,
-  cellIdentifier,
-  fieldController,
-  onOutsideClick,
-}: {
-  left: number;
-  top: number;
-  cellIdentifier: CellIdentifier;
-  fieldController: FieldController;
-  onOutsideClick: () => void;
-}) => {
-  const { changeNumberFormat } = useNumberFormat(cellIdentifier, fieldController);
-  const databaseStore = useAppSelector((state) => state.database);
-  const [numberType, setNumberType] = useState<INumberType | undefined>();
-
-  useEffect(() => {
-    setNumberType(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as INumberType);
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [databaseStore]);
-
-  const changeNumberFormatClick = async (format: NumberFormatPB) => {
-    await changeNumberFormat(format);
-    onOutsideClick();
-  };
-
-  return (
-    <PopupWindow className={'p-2 text-xs'} onOutsideClick={onOutsideClick} left={left} top={top}>
-      <div className={'h-[400px] overflow-auto'}>
-        {list.map((item, index) => (
-          <FormatButton
-            key={index}
-            title={item.title}
-            checked={numberType?.numberFormat === item.format}
-            onClick={() => changeNumberFormatClick(item.format)}
-          ></FormatButton>
-        ))}
-      </div>
-    </PopupWindow>
-  );
-};
-
-const FormatButton = ({ title, checked, onClick }: { title: string; checked: boolean; onClick: () => void }) => {
-  return (
-    <button
-      onClick={() => onClick()}
-      className={
-        'flex w-full cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-fill-list-hover'
-      }
-    >
-      <span className={'block pr-8'}>{title}</span>
-      {checked && (
-        <div className={'h-5 w-5 p-1'}>
-          <CheckmarkSvg></CheckmarkSvg>
-        </div>
-      )}
-    </button>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/TimeFormatPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/TimeFormatPopup.tsx
deleted file mode 100644
index 287d93a091..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Date/TimeFormatPopup.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { useTranslation } from 'react-i18next';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { TimeFormatPB } from '@/services/backend';
-import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg';
-import { useDateTimeFormat } from '$app/components/_shared/EditRow/Date/DateTimeFormat.hooks';
-import { useAppSelector } from '$app/stores/store';
-import { useEffect, useState } from 'react';
-import { IDateType } from '$app_reducers/database/slice';
-
-export const TimeFormatPopup = ({
-  left,
-  top,
-  cellIdentifier,
-  fieldController,
-  onOutsideClick,
-}: {
-  left: number;
-  top: number;
-  cellIdentifier: CellIdentifier;
-  fieldController: FieldController;
-  onOutsideClick: () => void;
-}) => {
-  const { t } = useTranslation();
-  const databaseStore = useAppSelector((state) => state.database);
-  const [dateType, setDateType] = useState<IDateType | undefined>();
-
-  useEffect(() => {
-    setDateType(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as IDateType);
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [databaseStore]);
-
-  const { changeTimeFormat } = useDateTimeFormat(cellIdentifier, fieldController);
-
-  const changeFormat = async (format: TimeFormatPB) => {
-    await changeTimeFormat(format);
-    onOutsideClick();
-  };
-
-  return (
-    <PopupWindow className={'p-2 text-xs'} onOutsideClick={onOutsideClick} left={left} top={top}>
-      <button
-        onClick={() => changeFormat(TimeFormatPB.TwelveHour)}
-        className={
-          'flex w-full cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-fill-list-hover'
-        }
-      >
-        {t('grid.field.timeFormatTwelveHour')}
-
-        {dateType?.timeFormat === TimeFormatPB.TwelveHour && (
-          <div className={'ml-8 h-5 w-5 p-1'}>
-            <CheckmarkSvg></CheckmarkSvg>
-          </div>
-        )}
-      </button>
-      <button
-        onClick={() => changeFormat(TimeFormatPB.TwentyFourHour)}
-        className={
-          'flex w-full cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-fill-list-hover'
-        }
-      >
-        {t('grid.field.timeFormatTwentyFourHour')}
-
-        {dateType?.timeFormat === TimeFormatPB.TwentyFourHour && (
-          <div className={'ml-8 h-5 w-5 p-1'}>
-            <CheckmarkSvg></CheckmarkSvg>
-          </div>
-        )}
-      </button>
-    </PopupWindow>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx
deleted file mode 100644
index 5436633bdb..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditCellWrapper.tsx
+++ /dev/null
@@ -1,143 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { useCell } from '$app/components/_shared/database-hooks/useCell';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { DateCellDataPB, FieldType, SelectOptionCellDataPB, URLCellDataPB } from '@/services/backend';
-import { useAppSelector } from '$app/stores/store';
-import { EditCellText } from '$app/components/_shared/EditRow/InlineEditFields/EditCellText';
-import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
-import { EditCellDate } from '$app/components/_shared/EditRow/Date/EditCellDate';
-import { useRef } from 'react';
-import { CellOptions } from '$app/components/_shared/EditRow/Options/CellOptions';
-import { EditCellNumber } from '$app/components/_shared/EditRow/InlineEditFields/EditCellNumber';
-import { EditCheckboxCell } from '$app/components/_shared/EditRow/InlineEditFields/EditCheckboxCell';
-import { EditCellUrl } from '$app/components/_shared/EditRow/InlineEditFields/EditCellUrl';
-import { Draggable } from 'react-beautiful-dnd';
-import { DragElementSvg } from '$app/components/_shared/svg/DragElementSvg';
-import { CheckList } from '$app/components/_shared/EditRow/CheckList/CheckList';
-
-export const EditCellWrapper = ({
-  index,
-  cellIdentifier,
-  cellCache,
-  fieldController,
-  onEditFieldClick,
-  onEditOptionsClick,
-  onEditDateClick,
-  onEditCheckListClick,
-}: {
-  index: number;
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-  onEditFieldClick: (cell: CellIdentifier, anchorEl: HTMLDivElement) => void;
-  onEditOptionsClick: (cell: CellIdentifier, left: number, top: number) => void;
-  onEditDateClick: (cell: CellIdentifier, left: number, top: number) => void;
-  onEditCheckListClick: (cell: CellIdentifier, left: number, top: number) => void;
-}) => {
-  const { data, cellController } = useCell(cellIdentifier, cellCache, fieldController);
-  const databaseStore = useAppSelector((state) => state.database);
-  const el = useRef<HTMLDivElement>(null);
-
-  const onClick = () => {
-    if (!el.current) return;
-
-    onEditFieldClick(cellIdentifier, el.current);
-  };
-
-  return (
-    <Draggable draggableId={cellIdentifier.fieldId} index={index} key={cellIdentifier.fieldId}>
-      {(provided) => (
-        <div
-          ref={provided.innerRef}
-          {...provided.draggableProps}
-          {...provided.dragHandleProps}
-          className={'flex w-full flex-col items-start gap-2 text-xs'}
-        >
-          <div className={'relative flex cursor-pointer items-center gap-2 rounded-lg transition-colors duration-200'}>
-            <div
-              ref={el}
-              onClick={() => onClick()}
-              className={'text-icon-default flex h-5 w-5 rounded hover:bg-fill-list-hover'}
-            >
-              <DragElementSvg></DragElementSvg>
-            </div>
-
-            <div className={'flex h-5 w-5 flex-shrink-0 items-center justify-center text-text-caption'}>
-              <FieldTypeIcon fieldType={cellIdentifier.fieldType}></FieldTypeIcon>
-            </div>
-            <span className={'overflow-hidden text-ellipsis whitespace-nowrap text-text-caption'}>
-              {databaseStore.fields[cellIdentifier.fieldId]?.title ?? ''}
-            </span>
-          </div>
-
-          <div className={'w-full cursor-pointer rounded-lg pl-3 text-sm hover:bg-content-blue-50'}>
-            {(cellIdentifier.fieldType === FieldType.SingleSelect ||
-              cellIdentifier.fieldType === FieldType.MultiSelect) &&
-              cellController && (
-                <CellOptions
-                  data={data as SelectOptionCellDataPB}
-                  onEditClick={(left, top) => onEditOptionsClick(cellIdentifier, left, top)}
-                ></CellOptions>
-              )}
-
-            {cellIdentifier.fieldType === FieldType.Checklist && cellController && (
-              <CheckList
-                data={data as SelectOptionCellDataPB}
-                fieldId={cellIdentifier.fieldId}
-                onEditClick={(left, top) => onEditCheckListClick(cellIdentifier, left, top)}
-              ></CheckList>
-            )}
-
-            {cellIdentifier.fieldType === FieldType.Checkbox && cellController && (
-              <EditCheckboxCell
-                data={data as 'Yes' | 'No' | undefined}
-                onToggle={async () => {
-                  if (data === 'Yes') {
-                    await cellController?.saveCellData('No');
-                  } else {
-                    await cellController?.saveCellData('Yes');
-                  }
-                }}
-              ></EditCheckboxCell>
-            )}
-
-            {cellIdentifier.fieldType === FieldType.DateTime && (
-              <EditCellDate
-                data={data as DateCellDataPB}
-                onEditClick={(left, top) => onEditDateClick(cellIdentifier, left, top)}
-              ></EditCellDate>
-            )}
-
-            {cellIdentifier.fieldType === FieldType.Number && cellController && (
-              <EditCellNumber
-                data={data as string | undefined}
-                onSave={async (value) => {
-                  await cellController?.saveCellData(value);
-                }}
-              ></EditCellNumber>
-            )}
-
-            {cellIdentifier.fieldType === FieldType.URL && cellController && (
-              <EditCellUrl
-                data={data as URLCellDataPB}
-                onSave={async (value) => {
-                  await cellController?.saveCellData(value);
-                }}
-              ></EditCellUrl>
-            )}
-
-            {cellIdentifier.fieldType === FieldType.RichText && cellController && (
-              <EditCellText
-                data={data as string | undefined}
-                onSave={async (value) => {
-                  await cellController?.saveCellData(value);
-                }}
-              ></EditCellText>
-            )}
-          </div>
-        </div>
-      )}
-    </Draggable>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditFieldPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditFieldPopup.tsx
deleted file mode 100644
index 134807e1a1..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditFieldPopup.tsx
+++ /dev/null
@@ -1,231 +0,0 @@
-import React, { FocusEventHandler, useEffect, useRef, useState } from 'react';
-import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
-import { FieldTypeName } from '$app/components/_shared/EditRow/FieldTypeName';
-import { useTranslation } from 'react-i18next';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { Some } from 'ts-results';
-import { MoreSvg } from '$app/components/_shared/svg/MoreSvg';
-import { useAppSelector } from '$app/stores/store';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import { EyeClosedSvg } from '$app/components/_shared/svg/EyeClosedSvg';
-import { Popover } from '@mui/material';
-import { CopySvg } from '$app/components/_shared/svg/CopySvg';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import { SkipLeftSvg } from '$app/components/_shared/svg/SkipLeftSvg';
-import { SkipRightSvg } from '$app/components/_shared/svg/SkipRightSvg';
-import { EyeOpenSvg } from '$app/components/_shared/svg/EyeOpenSvg';
-
-export const EditFieldPopup = ({
-  open,
-  anchorEl,
-  cellIdentifier,
-  viewId,
-  onOutsideClick,
-  controller,
-  changeFieldTypeClick,
-  onDeletePropertyClick,
-}: {
-  open: boolean;
-  anchorEl: HTMLDivElement | null;
-  cellIdentifier: CellIdentifier;
-  viewId: string;
-  onOutsideClick: () => void;
-  controller: DatabaseController;
-  changeFieldTypeClick: (el: HTMLDivElement) => void;
-  onDeletePropertyClick: (fieldId: string) => void;
-}) => {
-  const fieldsStore = useAppSelector((state) => state.database.fields);
-  const { t } = useTranslation();
-  const changeTypeButtonRef = useRef<HTMLDivElement>(null);
-  const inputRef = useRef<HTMLInputElement>(null);
-  const [name, setName] = useState('');
-
-  useEffect(() => {
-    setName(fieldsStore[cellIdentifier.fieldId].title);
-  }, [fieldsStore, cellIdentifier]);
-
-  // focus input on mount
-  useEffect(() => {
-    if (!inputRef.current || !name) return;
-    inputRef.current.focus();
-  }, [inputRef, name]);
-
-  const selectAll: FocusEventHandler<HTMLInputElement> = (e) => {
-    e.target.selectionStart = 0;
-    e.target.selectionEnd = e.target.value.length;
-  };
-
-  const save = async () => {
-    if (!controller) return;
-    const fieldInfo = controller.fieldController.getField(cellIdentifier.fieldId);
-
-    if (!fieldInfo) return;
-    const typeOptionController = new TypeOptionController(viewId, Some(fieldInfo));
-
-    await typeOptionController.initialize();
-    await typeOptionController.setFieldName(name);
-  };
-
-  const onChangeFieldTypeClick = () => {
-    if (!changeTypeButtonRef.current) return;
-
-    changeFieldTypeClick(changeTypeButtonRef.current);
-  };
-
-  const toggleHideProperty = async () => {
-    // we need to close the popup because after hiding the field, parent element will be removed
-    onOutsideClick();
-    const fieldInfo = controller.fieldController.getField(cellIdentifier.fieldId);
-
-    if (fieldInfo) {
-      const typeController = new TypeOptionController(viewId, Some(fieldInfo));
-
-      await typeController.initialize();
-      if (fieldInfo.field.visibility) {
-        await typeController.hideField();
-      } else {
-        await typeController.showField();
-      }
-    }
-  };
-
-  const onDuplicatePropertyClick = async () => {
-    onOutsideClick();
-    await controller.duplicateField(cellIdentifier.fieldId);
-  };
-
-  const onAddToLeftClick = async () => {
-    onOutsideClick();
-    await controller.addFieldToLeft(cellIdentifier.fieldId);
-  };
-
-  const onAddToRightClick = async () => {
-    onOutsideClick();
-    await controller.addFieldToRight(cellIdentifier.fieldId);
-  };
-
-  return (
-    <Popover
-      anchorEl={anchorEl}
-      open={open}
-      onClose={async () => {
-        await save();
-        onOutsideClick();
-      }}
-      disableRestoreFocus={true}
-      anchorOrigin={{
-        vertical: 'bottom',
-        horizontal: 'left',
-      }}
-      transformOrigin={{
-        vertical: 'top',
-        horizontal: 'left',
-      }}
-    >
-      <div className={'flex flex-col gap-2 p-2 text-xs'}>
-        <input
-          ref={inputRef}
-          onFocus={selectAll}
-          value={name}
-          onChange={(e) => setName(e.target.value)}
-          onBlur={() => save()}
-          className={
-            'flex-1 rounded border border-line-divider px-2 py-2 hover:border-fill-default focus:border-fill-default'
-          }
-        />
-
-        <div
-          ref={changeTypeButtonRef}
-          onClick={() => onChangeFieldTypeClick()}
-          className={
-            'relative flex cursor-pointer items-center justify-between rounded-lg py-2 text-text-title hover:bg-fill-list-hover'
-          }
-        >
-          <button className={'flex cursor-pointer items-center gap-2 rounded-lg pl-2'}>
-            <i className={'h-5 w-5'}>
-              <FieldTypeIcon fieldType={cellIdentifier.fieldType}></FieldTypeIcon>
-            </i>
-            <span>
-              <FieldTypeName fieldType={cellIdentifier.fieldType}></FieldTypeName>
-            </span>
-          </button>
-          <span className={'pr-2'}>
-            <i className={' block h-5 w-5'}>
-              <MoreSvg></MoreSvg>
-            </i>
-          </span>
-        </div>
-
-        <div className={'-mx-2 h-[1px] bg-line-divider'}></div>
-
-        <div className={'grid grid-cols-2'}>
-          <div className={'flex flex-col gap-2'}>
-            <div
-              onClick={toggleHideProperty}
-              className={'flex cursor-pointer items-center gap-2 rounded-lg p-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              {fieldsStore[cellIdentifier.fieldId]?.visible ? (
-                <>
-                  <i className={'block h-5 w-5'}>
-                    <EyeClosedSvg />
-                  </i>
-                  <span>{t('grid.field.hide')}</span>
-                </>
-              ) : (
-                <>
-                  <i className={'block h-5 w-5'}>
-                    <EyeOpenSvg />
-                  </i>
-                  <span>Show</span>
-                </>
-              )}
-            </div>
-            <div
-              onClick={() => onDuplicatePropertyClick()}
-              className={'flex cursor-pointer items-center gap-2 rounded-lg p-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              <i className={'block h-5 w-5'}>
-                <CopySvg />
-              </i>
-              <span>{t('grid.field.duplicate')}</span>
-            </div>
-            <div
-              onClick={() => {
-                onOutsideClick();
-                onDeletePropertyClick(cellIdentifier.fieldId);
-              }}
-              className={'flex cursor-pointer items-center gap-2 rounded-lg p-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              <i className={'block h-5 w-5'}>
-                <TrashSvg />
-              </i>
-              <span>{t('grid.field.delete')}</span>
-            </div>
-          </div>
-
-          <div className={'flex flex-col gap-2'}>
-            <div
-              onClick={onAddToLeftClick}
-              className={'flex cursor-pointer items-center gap-2 rounded-lg p-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              <i className={'block h-5 w-5'}>
-                <SkipLeftSvg />
-              </i>
-              <span>{t('grid.field.insertLeft')}</span>
-            </div>
-            <div
-              onClick={onAddToRightClick}
-              className={'flex cursor-pointer items-center gap-2 rounded-lg p-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              <i className={'block h-5 w-5'}>
-                <SkipRightSvg />
-              </i>
-              <span>{t('grid.field.insertRight')}</span>
-            </div>
-          </div>
-        </div>
-      </div>
-    </Popover>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx
deleted file mode 100644
index 90fe708859..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/EditRow.tsx
+++ /dev/null
@@ -1,367 +0,0 @@
-import { CloseSvg } from '$app/components/_shared/svg/CloseSvg';
-import { useRow } from '$app/components/_shared/database-hooks/useRow';
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import { EditCellWrapper } from '$app/components/_shared/EditRow/EditCellWrapper';
-import AddSvg from '$app/components/_shared/svg/AddSvg';
-import { useTranslation } from 'react-i18next';
-import { EditFieldPopup } from '$app/components/_shared/EditRow/EditFieldPopup';
-import { useEffect, useState } from 'react';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { ChangeFieldTypePopup } from '$app/components/_shared/EditRow/ChangeFieldTypePopup';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { Some } from 'ts-results';
-import { FieldType, SelectOptionPB } from '@/services/backend';
-import { CellOptionsPopup } from '$app/components/_shared/EditRow/Options/CellOptionsPopup';
-import { DatePickerPopup } from '$app/components/_shared/EditRow/Date/DatePickerPopup';
-import { DragDropContext, Droppable, OnDragEndResponder } from 'react-beautiful-dnd';
-import { EditCellOptionPopup } from '$app/components/_shared/EditRow/Options/EditCellOptionPopup';
-import { NumberFormatPopup } from '$app/components/_shared/EditRow/Date/NumberFormatPopup';
-import { CheckListPopup } from '$app/components/_shared/EditRow/CheckList/CheckListPopup';
-import { EditCheckListPopup } from '$app/components/_shared/EditRow/CheckList/EditCheckListPopup';
-import { PropertiesPanel } from '$app/components/_shared/EditRow/PropertiesPanel';
-import { ImageSvg } from '$app/components/_shared/svg/ImageSvg';
-import { PromptWindow } from '$app/components/_shared/PromptWindow';
-import { useAppSelector } from '$app/stores/store';
-
-export const EditRow = ({
-  onClose,
-  viewId,
-  controller,
-  rowInfo,
-}: {
-  onClose: () => void;
-  viewId: string;
-  controller: DatabaseController;
-  rowInfo: RowInfo;
-}) => {
-  const fieldsStore = useAppSelector((state) => state.database.fields);
-  const { cells, onNewColumnClick } = useRow(viewId, controller, rowInfo);
-  const { t } = useTranslation();
-  const [unveil, setUnveil] = useState(false);
-
-  const [editingCell, setEditingCell] = useState<CellIdentifier | null>(null);
-  const [editFieldAnchorEl, setEditFieldAnchorEl] = useState<HTMLDivElement | null>(null);
-  const [showFieldEditor, setShowFieldEditor] = useState(false);
-
-  const [showChangeFieldTypePopup, setShowChangeFieldTypePopup] = useState(false);
-  const [changeFieldTypeAnchorEl, setChangeFieldTypeAnchorEl] = useState<HTMLDivElement | null>(null);
-
-  const [showChangeOptionsPopup, setShowChangeOptionsPopup] = useState(false);
-  const [changeOptionsTop, setChangeOptionsTop] = useState(0);
-  const [changeOptionsLeft, setChangeOptionsLeft] = useState(0);
-
-  const [showDatePicker, setShowDatePicker] = useState(false);
-  const [datePickerTop, setDatePickerTop] = useState(0);
-  const [datePickerLeft, setDatePickerLeft] = useState(0);
-
-  const [showEditCellOption, setShowEditCellOption] = useState(false);
-  const [editCellOptionTop, setEditCellOptionTop] = useState(0);
-  const [editCellOptionLeft, setEditCellOptionLeft] = useState(0);
-
-  const [editingSelectOption, setEditingSelectOption] = useState<SelectOptionPB | undefined>();
-
-  const [showEditCheckList, setShowEditCheckList] = useState(false);
-  const [editCheckListTop, setEditCheckListTop] = useState(0);
-  const [editCheckListLeft, setEditCheckListLeft] = useState(0);
-
-  const [showNumberFormatPopup, setShowNumberFormatPopup] = useState(false);
-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  const [numberFormatTop, setNumberFormatTop] = useState(0);
-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  const [numberFormatLeft, setNumberFormatLeft] = useState(0);
-
-  const [showCheckListPopup, setShowCheckListPopup] = useState(false);
-  const [checkListPopupTop, setCheckListPopupTop] = useState(0);
-  const [checkListPopupLeft, setCheckListPopupLeft] = useState(0);
-
-  const [deletingPropertyId, setDeletingPropertyId] = useState<string | null>(null);
-  const [showDeletePropertyPrompt, setShowDeletePropertyPrompt] = useState(false);
-
-  useEffect(() => {
-    setUnveil(true);
-  }, []);
-
-  const onCloseClick = () => {
-    setUnveil(false);
-    setTimeout(() => {
-      onClose();
-    }, 300);
-  };
-
-  const onEditFieldClick = (cellIdentifier: CellIdentifier, anchorEl: HTMLDivElement) => {
-    setEditFieldAnchorEl(anchorEl);
-    setEditingCell(cellIdentifier);
-    setShowFieldEditor(true);
-  };
-
-  const onOutsideEditFieldClick = () => {
-    setShowFieldEditor(false);
-  };
-
-  const onChangeFieldTypeClick = (el: HTMLDivElement) => {
-    setChangeFieldTypeAnchorEl(el);
-    setShowChangeFieldTypePopup(true);
-  };
-
-  const changeFieldType = async (newType: FieldType) => {
-    if (!editingCell) return;
-
-    const currentField = controller.fieldController.getField(editingCell.fieldId);
-
-    if (!currentField) return;
-
-    const typeOptionController = new TypeOptionController(viewId, Some(currentField));
-
-    await typeOptionController.switchToField(newType);
-
-    setEditingCell(new CellIdentifier(viewId, rowInfo.row.id, editingCell.fieldId, newType));
-
-    setShowChangeFieldTypePopup(false);
-  };
-
-  const onEditOptionsClick = async (cellIdentifier: CellIdentifier, left: number, top: number) => {
-    setEditingCell(cellIdentifier);
-    setChangeOptionsLeft(left);
-    setChangeOptionsTop(top + 40);
-    setShowChangeOptionsPopup(true);
-  };
-
-  const onEditDateClick = async (cellIdentifier: CellIdentifier, left: number, top: number) => {
-    setEditingCell(cellIdentifier);
-    setDatePickerLeft(left);
-    setDatePickerTop(top + 40);
-    setShowDatePicker(true);
-  };
-
-  const onOpenOptionDetailClick = (_left: number, _top: number, _select_option: SelectOptionPB) => {
-    setEditingSelectOption(_select_option);
-    setShowEditCellOption(true);
-    setEditCellOptionLeft(_left);
-    setEditCellOptionTop(_top);
-  };
-
-  const onOpenCheckListDetailClick = (_left: number, _top: number, _select_option: SelectOptionPB) => {
-    setEditingSelectOption(_select_option);
-    setShowEditCheckList(true);
-    setEditCheckListLeft(_left + 10);
-    setEditCheckListTop(_top);
-  };
-
-  const onEditCheckListClick = (cellIdentifier: CellIdentifier, left: number, top: number) => {
-    setEditingCell(cellIdentifier);
-    setShowCheckListPopup(true);
-    setCheckListPopupLeft(left);
-    setCheckListPopupTop(top + 40);
-  };
-
-  const onDragEnd: OnDragEndResponder = (result) => {
-    if (!result.destination?.index) return;
-    const fields = cells
-      .filter((cell) => {
-        return fieldsStore[cell.cellIdentifier.fieldId]?.visible;
-      });
-
-    void controller.moveField({
-      fromFieldId: result.draggableId,
-      toFieldId: fields[result.source.index].fieldId,
-    });
-  };
-
-  const onDeletePropertyClick = (fieldId: string) => {
-    setDeletingPropertyId(fieldId);
-    setShowDeletePropertyPrompt(true);
-  };
-
-  const onDelete = async () => {
-    if (!deletingPropertyId) return;
-    const fieldInfo = controller.fieldController.getField(deletingPropertyId);
-
-    if (!fieldInfo) return;
-    const typeController = new TypeOptionController(viewId, Some(fieldInfo));
-
-    setEditingCell(null);
-
-    await typeController.initialize();
-    await typeController.deleteField();
-    setShowDeletePropertyPrompt(false);
-  };
-
-  return (
-    <>
-      <div
-        className={`fixed inset-0 z-10 flex items-center justify-center bg-black/30 backdrop-blur-sm transition-opacity duration-300 ${unveil ? 'opacity-100' : 'opacity-0'
-          }`}
-        onClick={() => onCloseClick()}
-      >
-        <div
-          onClick={(e) => {
-            e.stopPropagation();
-          }}
-          className={`relative flex h-[90%] w-[70%] flex-col gap-8 rounded-xl bg-bg-body `}
-        >
-          <div onClick={() => onCloseClick()} className={'absolute right-1 top-1'}>
-            <button className={'block h-8 w-8 rounded-lg text-text-title hover:bg-fill-list-hover'}>
-              <CloseSvg></CloseSvg>
-            </button>
-          </div>
-
-          <div className={'flex h-full'}>
-            <div className={'flex h-full flex-1 flex-col border-r border-line-divider pb-4 pt-6'}>
-              <div className={'pb-4 pl-12'}>
-                <button className={'flex items-center gap-2 p-4'}>
-                  <i className={'h-5 w-5'}>
-                    <ImageSvg></ImageSvg>
-                  </i>
-                  <span className={'text-xs'}>Add Cover</span>
-                </button>
-              </div>
-
-              <DragDropContext onDragEnd={onDragEnd}>
-                <Droppable droppableId={'field-list'}>
-                  {(provided) => (
-                    <div
-                      {...provided.droppableProps}
-                      ref={provided.innerRef}
-                      className={`flex flex-1 flex-col gap-8 px-8 pb-8 ${showFieldEditor || showChangeOptionsPopup || showDatePicker ? 'overflow-hidden' : 'overflow-auto'
-                        }`}
-                    >
-                      {cells
-                        .filter((cell) => {
-                          return fieldsStore[cell.cellIdentifier.fieldId]?.visible;
-                        })
-                        .map((cell, cellIndex) => (
-                          <EditCellWrapper
-                            index={cellIndex}
-                            key={cellIndex}
-                            cellIdentifier={cell.cellIdentifier}
-                            cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
-                            fieldController={controller.fieldController}
-                            onEditFieldClick={onEditFieldClick}
-                            onEditOptionsClick={onEditOptionsClick}
-                            onEditDateClick={onEditDateClick}
-                            onEditCheckListClick={onEditCheckListClick}
-                          ></EditCellWrapper>
-                        ))}
-                    </div>
-                  )}
-                </Droppable>
-              </DragDropContext>
-
-              <div className={'border-t border-line-divider px-8 pt-2'}>
-                <button
-                  onClick={() => onNewColumnClick()}
-                  className={'flex w-full items-center gap-2 rounded-lg px-4 py-2 hover:bg-fill-list-hover'}
-                >
-                  <i className={'h-5 w-5'}>
-                    <AddSvg></AddSvg>
-                  </i>
-                  <span>{t('grid.field.newProperty')}</span>
-                </button>
-              </div>
-            </div>
-            <PropertiesPanel
-              viewId={viewId}
-              controller={controller}
-              rowInfo={rowInfo}
-              onDeletePropertyClick={onDeletePropertyClick}
-              onNewColumnClick={onNewColumnClick}
-            ></PropertiesPanel>
-          </div>
-
-          {editingCell && (
-            <EditFieldPopup
-              open={showFieldEditor}
-              anchorEl={editFieldAnchorEl}
-              cellIdentifier={editingCell}
-              viewId={viewId}
-              onOutsideClick={onOutsideEditFieldClick}
-              controller={controller}
-              changeFieldTypeClick={onChangeFieldTypeClick}
-              onDeletePropertyClick={onDeletePropertyClick}
-            ></EditFieldPopup>
-          )}
-          {showChangeFieldTypePopup && (
-            <ChangeFieldTypePopup
-              open={showChangeFieldTypePopup}
-              anchorEl={changeFieldTypeAnchorEl}
-              onClick={(newType) => changeFieldType(newType)}
-              onOutsideClick={() => setShowChangeFieldTypePopup(false)}
-            ></ChangeFieldTypePopup>
-          )}
-          {showChangeOptionsPopup && editingCell && (
-            <CellOptionsPopup
-              top={changeOptionsTop}
-              left={changeOptionsLeft}
-              cellIdentifier={editingCell}
-              cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
-              fieldController={controller.fieldController}
-              onOutsideClick={() => !showEditCellOption && setShowChangeOptionsPopup(false)}
-              openOptionDetail={onOpenOptionDetailClick}
-            ></CellOptionsPopup>
-          )}
-          {showDatePicker && editingCell && (
-            <DatePickerPopup
-              top={datePickerTop}
-              left={datePickerLeft}
-              cellIdentifier={editingCell}
-              cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
-              fieldController={controller.fieldController}
-              onOutsideClick={() => setShowDatePicker(false)}
-            ></DatePickerPopup>
-          )}
-          {showEditCellOption && editingCell && editingSelectOption && (
-            <EditCellOptionPopup
-              top={editCellOptionTop}
-              left={editCellOptionLeft}
-              cellIdentifier={editingCell}
-              editingSelectOption={editingSelectOption}
-              setEditingSelectOption={setEditingSelectOption}
-              onOutsideClick={() => {
-                setShowEditCellOption(false);
-              }}
-            ></EditCellOptionPopup>
-          )}
-          {showNumberFormatPopup && editingCell && (
-            <NumberFormatPopup
-              top={numberFormatTop}
-              left={numberFormatLeft}
-              cellIdentifier={editingCell}
-              fieldController={controller.fieldController}
-              onOutsideClick={() => {
-                setShowNumberFormatPopup(false);
-              }}
-            ></NumberFormatPopup>
-          )}
-          {showCheckListPopup && editingCell && (
-            <CheckListPopup
-              top={checkListPopupTop}
-              left={checkListPopupLeft}
-              cellIdentifier={editingCell}
-              cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
-              fieldController={controller.fieldController}
-              onOutsideClick={() => !showEditCheckList && setShowCheckListPopup(false)}
-              openCheckListDetail={onOpenCheckListDetailClick}
-            ></CheckListPopup>
-          )}
-          {showEditCheckList && editingCell && editingSelectOption && (
-            <EditCheckListPopup
-              top={editCheckListTop}
-              left={editCheckListLeft}
-              cellIdentifier={editingCell}
-              editingSelectOption={editingSelectOption}
-              onOutsideClick={() => setShowEditCheckList(false)}
-            ></EditCheckListPopup>
-          )}
-        </div>
-      </div>
-      {showDeletePropertyPrompt && (
-        <PromptWindow
-          msg={'Are you sure you want to delete this property?'}
-          onYes={() => onDelete()}
-          onCancel={() => setShowDeletePropertyPrompt(false)}
-        ></PromptWindow>
-      )}
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeIcon.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeIcon.tsx
deleted file mode 100644
index 8c82601cba..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeIcon.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { FieldType } from '@/services/backend';
-import { TextTypeSvg } from '$app/components/_shared/svg/TextTypeSvg';
-import { NumberTypeSvg } from '$app/components/_shared/svg/NumberTypeSvg';
-import { DateTypeSvg } from '$app/components/_shared/svg/DateTypeSvg';
-import { SingleSelectTypeSvg } from '$app/components/_shared/svg/SingleSelectTypeSvg';
-import { MultiSelectTypeSvg } from '$app/components/_shared/svg/MultiSelectTypeSvg';
-import { ChecklistTypeSvg } from '$app/components/_shared/svg/ChecklistTypeSvg';
-import { UrlTypeSvg } from '$app/components/_shared/svg/UrlTypeSvg';
-import { CheckboxSvg } from '$app/components/_shared/svg/CheckboxSvg';
-
-export const FieldTypeIcon = ({ fieldType }: { fieldType: FieldType }) => {
-  return (
-    <>
-      {fieldType === FieldType.RichText && <TextTypeSvg></TextTypeSvg>}
-      {fieldType === FieldType.Number && <NumberTypeSvg></NumberTypeSvg>}
-      {fieldType === FieldType.DateTime && <DateTypeSvg></DateTypeSvg>}
-      {fieldType === FieldType.SingleSelect && <SingleSelectTypeSvg></SingleSelectTypeSvg>}
-      {fieldType === FieldType.MultiSelect && <MultiSelectTypeSvg></MultiSelectTypeSvg>}
-      {fieldType === FieldType.Checklist && <ChecklistTypeSvg></ChecklistTypeSvg>}
-      {fieldType === FieldType.URL && <UrlTypeSvg></UrlTypeSvg>}
-      {fieldType === FieldType.Checkbox && <CheckboxSvg></CheckboxSvg>}
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeName.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeName.tsx
deleted file mode 100644
index 06d1f601ce..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/FieldTypeName.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { FieldType } from '@/services/backend';
-import { useTranslation } from 'react-i18next';
-
-export const FieldTypeName = ({ fieldType }: { fieldType: FieldType }) => {
-  const { t } = useTranslation();
-
-  return (
-    <>
-      {fieldType === FieldType.RichText && t('grid.field.textFieldName')}
-      {fieldType === FieldType.Number && t('grid.field.numberFieldName')}
-      {fieldType === FieldType.DateTime && t('grid.field.dateFieldName')}
-      {fieldType === FieldType.SingleSelect && t('grid.field.singleSelectFieldName')}
-      {fieldType === FieldType.MultiSelect && t('grid.field.multiSelectFieldName')}
-      {fieldType === FieldType.Checklist && t('grid.field.checklistFieldName')}
-      {fieldType === FieldType.URL && t('grid.field.urlFieldName')}
-      {fieldType === FieldType.Checkbox && t('grid.field.checkboxFieldName')}
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellNumber.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellNumber.tsx
deleted file mode 100644
index 381f25ae3e..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellNumber.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { useEffect, useState } from 'react';
-
-export const EditCellNumber = ({ data, onSave }: { data: string | undefined; onSave: (value: string) => void }) => {
-  const [value, setValue] = useState('');
-
-  useEffect(() => {
-    setValue(data ?? '');
-  }, [data]);
-
-  // const save = async () => {
-  //   await cellController?.saveCellData(value);
-  // };
-
-  return (
-    <input
-      value={value}
-      onChange={(e) => setValue(e.target.value)}
-      onBlur={() => onSave(value)}
-      className={'w-full px-4 py-1'}
-    ></input>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellText.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellText.tsx
deleted file mode 100644
index 8a92b71ce4..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellText.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { useEffect, useState } from 'react';
-
-export const EditCellText = ({ data, onSave }: { data: string | undefined; onSave: (value: string) => void }) => {
-  const [value, setValue] = useState('');
-  const [contentRows, setContentRows] = useState(1);
-
-  useEffect(() => {
-    setValue(data ?? '');
-  }, [data]);
-
-  useEffect(() => {
-    if (!value?.length) return;
-    setContentRows(Math.max(1, (value ?? '').split('\n').length));
-  }, [value]);
-
-  const onTextFieldChange = async (v: string) => {
-    setValue(v);
-  };
-
-  return (
-    <div>
-      <textarea
-        className={'mt-0.5 h-full w-full resize-none px-4 py-1'}
-        rows={contentRows}
-        value={value}
-        onChange={(e) => onTextFieldChange(e.target.value)}
-        onBlur={() => onSave(value)}
-      />
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellUrl.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellUrl.tsx
deleted file mode 100644
index 4a23fd448f..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCellUrl.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { URLCellDataPB } from '@/services/backend';
-import { useEffect, useState } from 'react';
-
-export const EditCellUrl = ({ data, onSave }: { data: URLCellDataPB | undefined; onSave: (value: string) => void }) => {
-  const [value, setValue] = useState('');
-
-  useEffect(() => {
-    setValue((data as URLCellDataPB)?.url ?? '');
-  }, [data]);
-
-  return (
-    <input
-      value={value}
-      onChange={(e) => setValue(e.target.value)}
-      onBlur={() => onSave(value)}
-      className={'w-full px-4 py-1'}
-    ></input>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCheckboxCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCheckboxCell.tsx
deleted file mode 100644
index efed3a23ba..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/InlineEditFields/EditCheckboxCell.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg';
-import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
-
-export const EditCheckboxCell = ({ data, onToggle }: { data: 'Yes' | 'No' | undefined; onToggle: () => void }) => {
-  // const toggleValue = async () => {
-  //   if (data === 'Yes') {
-  //     await cellController?.saveCellData('No');
-  //   } else {
-  //     await cellController?.saveCellData('Yes');
-  //   }
-  // };
-
-  return (
-    <div onClick={() => onToggle()} className={'block px-4 py-1'}>
-      <button className={'h-5 w-5'}>
-        {data === 'Yes' ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>}
-      </button>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOption.tsx
deleted file mode 100644
index 260c85c2e5..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOption.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import { SelectOptionColorPB, SelectOptionPB } from '@/services/backend';
-import { getBgColor } from '$app/components/_shared/getColor';
-import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg';
-import { Details2Svg } from '$app/components/_shared/svg/Details2Svg';
-import { ISelectOption } from '$app_reducers/database/slice';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { MouseEventHandler } from 'react';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-
-export const CellOption = ({
-  option,
-  checked,
-  cellIdentifier,
-  openOptionDetail,
-  clearValue,
-  noSelect,
-  noDetail,
-  onOptionClick,
-}: {
-  option: ISelectOption;
-  checked: boolean;
-  cellIdentifier?: CellIdentifier;
-  openOptionDetail?: (_left: number, _top: number, _select_option: SelectOptionPB) => void;
-  clearValue?: () => void;
-  noSelect?: boolean;
-  noDetail?: boolean;
-  onOptionClick?: () => void;
-}) => {
-  const onOptionDetailClick: MouseEventHandler = (e) => {
-    e.stopPropagation();
-    let target = e.target as HTMLElement;
-
-    while (!(target instanceof HTMLButtonElement)) {
-      if (target.parentElement === null) return;
-      target = target.parentElement;
-    }
-
-    const selectOption = new SelectOptionPB({
-      id: option.selectOptionId,
-      name: option.title,
-      color: option.color ?? SelectOptionColorPB.Purple,
-    });
-
-    const { right: _left, top: _top } = target.getBoundingClientRect();
-
-    openOptionDetail?.(_left, _top, selectOption);
-  };
-
-  const onToggleOptionClick: MouseEventHandler = async () => {
-    onOptionClick?.();
-    if (noSelect || !cellIdentifier) return;
-    if (checked) {
-      await new SelectOptionCellBackendService(cellIdentifier).unselectOption([option.selectOptionId]);
-    } else {
-      await new SelectOptionCellBackendService(cellIdentifier).selectOption([option.selectOptionId]);
-    }
-
-    clearValue?.();
-  };
-
-  return (
-    <div
-      onClick={onToggleOptionClick}
-      className={'flex cursor-pointer items-center justify-between rounded-lg px-2 py-1.5 hover:bg-fill-list-hover'}
-    >
-      <div className={`${getBgColor(option.color)} rounded px-2 py-0.5 text-text-title`}>{option.title}</div>
-      <div className={'flex items-center'}>
-        {checked && (
-          <button className={'h-5 w-5 p-1'}>
-            <CheckmarkSvg></CheckmarkSvg>
-          </button>
-        )}
-        {!noDetail && (
-          <button onClick={onOptionDetailClick} className={'h-6 w-6 p-1'}>
-            <Details2Svg></Details2Svg>
-          </button>
-        )}
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOptions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOptions.tsx
deleted file mode 100644
index d77c075cd3..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOptions.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { SelectOptionCellDataPB } from '@/services/backend';
-import { getBgColor } from '$app/components/_shared/getColor';
-import { MouseEventHandler, useRef } from 'react';
-
-export const CellOptions = ({
-  data,
-  onEditClick,
-}: {
-  data: SelectOptionCellDataPB | undefined;
-  onEditClick: (left: number, top: number) => void;
-}) => {
-  const ref = useRef<HTMLDivElement>(null);
-
-  const onClick: MouseEventHandler = () => {
-    if (!ref.current) return;
-    const { left, top } = ref.current.getBoundingClientRect();
-
-    onEditClick(left, top);
-  };
-
-  return (
-    <div ref={ref} onClick={onClick} className={'flex w-full flex-wrap items-center gap-2 px-4 py-1 text-xs'}>
-      {data?.select_options?.map((option, index) => (
-        <div className={`${getBgColor(option.color)} rounded px-2 py-0.5 text-text-title`} key={index}>
-          {option?.name ?? ''}
-        </div>
-      ))}
-      &nbsp;
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOptionsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOptionsPopup.tsx
deleted file mode 100644
index 05262d7068..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/CellOptionsPopup.tsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import { KeyboardEventHandler, useEffect, useRef, useState } from 'react';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { useCell } from '$app/components/_shared/database-hooks/useCell';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { SelectOptionCellDataPB, SelectOptionPB } from '@/services/backend';
-import { useTranslation } from 'react-i18next';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { useAppSelector } from '$app/stores/store';
-import { ISelectOptionType } from '$app_reducers/database/slice';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { CellOption } from '$app/components/_shared/EditRow/Options/CellOption';
-import { SelectedOption } from '$app/components/_shared/EditRow/Options/SelectedOption';
-
-export const CellOptionsPopup = ({
-  top,
-  left,
-  cellIdentifier,
-  cellCache,
-  fieldController,
-  onOutsideClick,
-  openOptionDetail,
-}: {
-  top: number;
-  left: number;
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-  onOutsideClick: () => void;
-  openOptionDetail: (_left: number, _top: number, _select_option: SelectOptionPB) => void;
-}) => {
-  const inputRef = useRef<HTMLInputElement>(null);
-  const { t } = useTranslation();
-  const [value, setValue] = useState('');
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-  const databaseStore = useAppSelector((state) => state.database);
-
-  useEffect(() => {
-    if (inputRef?.current) {
-      inputRef.current.focus();
-    }
-  }, [inputRef]);
-
-  const onKeyDown: KeyboardEventHandler = async (e) => {
-    if (e.key === 'Enter' && value.length > 0) {
-      await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: value, isSelect: true });
-      setValue('');
-    }
-  };
-
-  const onKeyDownWrapper: KeyboardEventHandler = (e) => {
-    if (e.key === 'Escape') {
-      onOutsideClick();
-    }
-  };
-
-  return (
-    <PopupWindow className={'p-2 text-xs'} onOutsideClick={onOutsideClick} left={left} top={top}>
-      <div onKeyDown={onKeyDownWrapper} className={'flex flex-col gap-2 p-2'}>
-        <div
-          className={
-            'flex flex-1 items-center gap-2 rounded border border-line-divider px-2 hover:border-fill-default focus:border-fill-default'
-          }
-        >
-          <div className={'flex flex-wrap items-center gap-2 text-text-title'}>
-            {(data as SelectOptionCellDataPB)?.select_options?.map((option, index) => (
-              <SelectedOption
-                option={option}
-                key={index}
-                cellIdentifier={cellIdentifier}
-                clearValue={() => setValue('')}
-              ></SelectedOption>
-            ))}
-          </div>
-          <input
-            ref={inputRef}
-            className={'py-2'}
-            value={value}
-            onChange={(e) => setValue(e.target.value)}
-            placeholder={t('grid.selectOption.searchOption') ?? ''}
-            onKeyDown={onKeyDown}
-          />
-          <div className={'font-mono text-text-caption'}>{value.length}/30</div>
-        </div>
-        <div className={'-mx-4 h-[1px] bg-line-divider'}></div>
-        <div className={'font-medium text-text-caption'}>{t('grid.selectOption.panelTitle') ?? ''}</div>
-        <div className={'flex flex-col gap-1'}>
-          {(databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType).selectOptions.map(
-            (option, index) => (
-              <CellOption
-                key={index}
-                option={option}
-                checked={
-                  !!(data as SelectOptionCellDataPB)?.select_options?.find(
-                    (selectedOption) => selectedOption.id === option.selectOptionId
-                  )
-                }
-                cellIdentifier={cellIdentifier}
-                openOptionDetail={openOptionDetail}
-                clearValue={() => setValue('')}
-              ></CellOption>
-            )
-          )}
-        </div>
-      </div>
-    </PopupWindow>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/EditCellOptionPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/EditCellOptionPopup.tsx
deleted file mode 100644
index 3b6ef80e06..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/EditCellOptionPopup.tsx
+++ /dev/null
@@ -1,236 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { KeyboardEventHandler, useEffect, useRef, useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { SelectOptionColorPB, SelectOptionPB } from '@/services/backend';
-import { getBgColor } from '$app/components/_shared/getColor';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { databaseActions, ISelectOptionType } from '$app_reducers/database/slice';
-import { useAppDispatch, useAppSelector } from '$app/stores/store';
-
-export const EditCellOptionPopup = ({
-  left,
-  top,
-  cellIdentifier,
-  editingSelectOption,
-  setEditingSelectOption,
-  onOutsideClick,
-}: {
-  left: number;
-  top: number;
-  cellIdentifier: CellIdentifier;
-  editingSelectOption: SelectOptionPB;
-  setEditingSelectOption: (option: SelectOptionPB) => void;
-  onOutsideClick: () => void;
-}) => {
-  const inputRef = useRef<HTMLInputElement>(null);
-  const { t } = useTranslation();
-  const [value, setValue] = useState('');
-  const fieldsStore = useAppSelector((state) => state.database.fields);
-  const dispatch = useAppDispatch();
-
-  useEffect(() => {
-    setValue(editingSelectOption.name);
-  }, [editingSelectOption]);
-
-  const onKeyDown: KeyboardEventHandler = async (e) => {
-    if (e.key === 'Enter' && value.length > 0) {
-      await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: value });
-      setValue('');
-    }
-  };
-
-  const onKeyDownWrapper: KeyboardEventHandler = (e) => {
-    if (e.key === 'Escape') {
-      onOutsideClick();
-    }
-  };
-
-  const onBlur = async () => {
-    const svc = new SelectOptionCellBackendService(cellIdentifier);
-
-    await svc.updateOption(
-      new SelectOptionPB({
-        id: editingSelectOption.id,
-        color: editingSelectOption.color,
-        name: value,
-      })
-    );
-  };
-
-  const onUpdateSelectOption = (option: SelectOptionPB) => {
-    const updatingField = fieldsStore[cellIdentifier.fieldId];
-    const allOptions = (updatingField.fieldOptions as ISelectOptionType).selectOptions;
-
-    dispatch(
-      databaseActions.updateField({
-        field: {
-          ...updatingField,
-          fieldOptions: {
-            selectOptions: allOptions.map((o) =>
-              o.selectOptionId === option.id
-                ? {
-                    selectOptionId: option.id,
-                    color: option.color,
-                    title: option.name,
-                  }
-                : o
-            ),
-          },
-        },
-      })
-    );
-
-    setEditingSelectOption(option);
-  };
-
-  const onColorClick = async (color: SelectOptionColorPB) => {
-    const svc = new SelectOptionCellBackendService(cellIdentifier);
-
-    const updatedOption = new SelectOptionPB({
-      id: editingSelectOption.id,
-      color,
-      name: editingSelectOption.name,
-    });
-
-    await svc.updateOption(updatedOption);
-    onUpdateSelectOption(updatedOption);
-  };
-
-  const onDeleteOptionClick = async () => {
-    const svc = new SelectOptionCellBackendService(cellIdentifier);
-
-    await svc.deleteOption([editingSelectOption]);
-    onOutsideClick();
-  };
-
-  return (
-    <PopupWindow
-      className={'p-2 text-xs'}
-      onOutsideClick={async () => {
-        await onBlur();
-        onOutsideClick();
-      }}
-      left={left}
-      top={top}
-    >
-      <div onKeyDown={onKeyDownWrapper} className={'flex flex-col gap-2 p-2'}>
-        <div
-          className={
-            'flex flex-1 items-center gap-2 rounded border border-line-divider px-2 hover:border-fill-hover focus:border-fill-hover'
-          }
-        >
-          <input
-            ref={inputRef}
-            className={'py-2'}
-            value={value}
-            onChange={(e) => setValue(e.target.value)}
-            onKeyDown={onKeyDown}
-            onBlur={() => onBlur()}
-          />
-          <div className={'font-mono text-text-caption'}>{value.length}/30</div>
-        </div>
-        <button
-          onClick={() => onDeleteOptionClick()}
-          className={
-            'text-main-alert flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 hover:bg-fill-list-hover'
-          }
-        >
-          <i className={'h-5 w-5'}>
-            <TrashSvg></TrashSvg>
-          </i>
-          <span>{t('grid.selectOption.deleteTag')}</span>
-        </button>
-        <div className={'-mx-4 h-[1px] bg-line-divider'}></div>
-        <div className={'my-2 font-medium text-text-caption'}>{t('grid.selectOption.colorPanelTitle')}</div>
-        <div className={'flex flex-col'}>
-          <ColorItem
-            title={t('grid.selectOption.purpleColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Purple)}
-            bgColor={getBgColor(SelectOptionColorPB.Purple)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Purple}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.pinkColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Pink)}
-            bgColor={getBgColor(SelectOptionColorPB.Pink)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Pink}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.lightPinkColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.LightPink)}
-            bgColor={getBgColor(SelectOptionColorPB.LightPink)}
-            checked={editingSelectOption.color === SelectOptionColorPB.LightPink}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.orangeColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Orange)}
-            bgColor={getBgColor(SelectOptionColorPB.Orange)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Orange}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.yellowColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Yellow)}
-            bgColor={getBgColor(SelectOptionColorPB.Yellow)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Yellow}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.limeColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Lime)}
-            bgColor={getBgColor(SelectOptionColorPB.Lime)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Lime}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.greenColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Green)}
-            bgColor={getBgColor(SelectOptionColorPB.Green)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Green}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.aquaColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Aqua)}
-            bgColor={getBgColor(SelectOptionColorPB.Aqua)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Aqua}
-          ></ColorItem>
-          <ColorItem
-            title={t('grid.selectOption.blueColor')}
-            onClick={() => onColorClick(SelectOptionColorPB.Blue)}
-            bgColor={getBgColor(SelectOptionColorPB.Blue)}
-            checked={editingSelectOption.color === SelectOptionColorPB.Blue}
-          ></ColorItem>
-        </div>
-      </div>
-    </PopupWindow>
-  );
-};
-
-const ColorItem = ({
-  title,
-  bgColor,
-  onClick,
-  checked,
-}: {
-  title: string;
-  bgColor: string;
-  onClick: () => void;
-  checked: boolean;
-}) => {
-  return (
-    <div
-      className={'flex cursor-pointer items-center justify-between rounded-lg p-2 hover:bg-fill-list-hover'}
-      onClick={() => onClick()}
-    >
-      <div className={'flex items-center gap-2'}>
-        <div className={`h-4 w-4 rounded-full ${bgColor}`}></div>
-        <span>{title}</span>
-      </div>
-      {checked && (
-        <i className={'block h-3 w-3'}>
-          <CheckmarkSvg></CheckmarkSvg>
-        </i>
-      )}
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/MultiSelectTypeOptions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/MultiSelectTypeOptions.tsx
deleted file mode 100644
index f7a87e5507..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/MultiSelectTypeOptions.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { ISelectOptionType } from '$app_reducers/database/slice';
-import { CellOption } from '$app/components/_shared/EditRow/Options/CellOption';
-import { SelectOptionPB } from '@/services/backend';
-import { useAppSelector } from '$app/stores/store';
-import { KeyboardEventHandler, useEffect, useRef, useState } from 'react';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-
-export const MultiSelectTypeOptions = ({
-  cellIdentifier,
-  openOptionDetail,
-}: {
-  cellIdentifier: CellIdentifier;
-  openOptionDetail?: (_left: number, _top: number, _select_option: SelectOptionPB) => void;
-}) => {
-  const inputRef = useRef<HTMLInputElement>(null);
-  const inputContainerRef = useRef<HTMLDivElement>(null);
-  const fieldsStore = useAppSelector((state) => state.database.fields);
-  const [value, setValue] = useState('');
-  const [showInput, setShowInput] = useState(false);
-  const [newInputWidth, setNewInputWidth] = useState(0);
-
-  const onKeyDown: KeyboardEventHandler = async (e) => {
-    if (e.key === 'Enter' && value.length > 0) {
-      await new SelectOptionCellBackendService(cellIdentifier).createOption({ name: value, isSelect: false });
-      setValue('');
-    }
-
-    if (e.key === 'Escape') {
-      setShowInput(false);
-    }
-  };
-
-  useEffect(() => {
-    if (inputRef?.current && showInput) {
-      inputRef.current.focus();
-    }
-  }, [inputRef, showInput, newInputWidth]);
-
-  useEffect(() => {
-    if (inputContainerRef?.current && showInput) {
-      setNewInputWidth(inputContainerRef.current.getBoundingClientRect().width - 56);
-    } else {
-      setNewInputWidth(0);
-    }
-  }, [inputContainerRef, showInput]);
-
-  return (
-    <div className={'flex flex-col'}>
-      <hr className={'-mx-2 my-2 border-line-divider'} />
-      <div className={'flex flex-col gap-1'}>
-        <div className={'flex items-center justify-between px-3 py-1.5'}>
-          <div>Options</div>
-          {!showInput && <button onClick={() => setShowInput(true)}>Add option</button>}
-        </div>
-        {showInput && (
-          <div
-            ref={inputContainerRef}
-            className={`border-shades-3 bg-main-selector flex items-center gap-2 rounded border px-2`}
-          >
-            {newInputWidth > 0 && (
-              <input
-                ref={inputRef}
-                style={{ width: newInputWidth }}
-                className={'py-2'}
-                value={value}
-                onChange={(e) => setValue(e.target.value)}
-                onBlur={() => setShowInput(false)}
-                onKeyDown={onKeyDown}
-              />
-            )}
-            <div className={'font-mono text-text-caption'}>{value.length}/30</div>
-          </div>
-        )}
-
-        {(fieldsStore[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType).selectOptions.map((option, index) => (
-          <CellOption
-            key={index}
-            option={option}
-            noSelect={true}
-            checked={false}
-            cellIdentifier={cellIdentifier}
-            openOptionDetail={openOptionDetail}
-            clearValue={() => setValue('')}
-          ></CellOption>
-        ))}
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/SelectedOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/SelectedOption.tsx
deleted file mode 100644
index f261aff2b9..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/Options/SelectedOption.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { getBgColor } from '$app/components/_shared/getColor';
-import { CloseSvg } from '$app/components/_shared/svg/CloseSvg';
-import { SelectOptionPB } from '@/services/backend';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { MouseEventHandler } from 'react';
-
-export const SelectedOption = ({
-  option,
-  cellIdentifier,
-  clearValue,
-}: {
-  option: SelectOptionPB;
-  cellIdentifier: CellIdentifier;
-  clearValue: () => void;
-}) => {
-  const onUnselectOptionClick: MouseEventHandler = async () => {
-    await new SelectOptionCellBackendService(cellIdentifier).unselectOption([option.id]);
-    clearValue();
-  };
-
-  return (
-    <div className={`${getBgColor(option.color)} flex items-center gap-0.5 rounded px-1 py-0.5 text-content-on-fill`}>
-      <span className={'text-text-title'}>{option?.name ?? ''}</span>
-      <button onClick={onUnselectOptionClick} className={'h-5 w-5 cursor-pointer text-text-title'}>
-        <CloseSvg></CloseSvg>
-      </button>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/PropertiesPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/PropertiesPanel.tsx
deleted file mode 100644
index 35feec5a5d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EditRow/PropertiesPanel.tsx
+++ /dev/null
@@ -1,223 +0,0 @@
-import { DropDownShowSvg } from '$app/components/_shared/svg/DropDownShowSvg';
-import { useState } from 'react';
-import { useRow } from '$app/components/_shared/database-hooks/useRow';
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
-import { useAppSelector } from '$app/stores/store';
-import { Switch } from '$app/components/_shared/Switch';
-import { FieldType } from '@/services/backend';
-import { FieldTypeName } from '$app/components/_shared/EditRow/FieldTypeName';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import { MultiSelectTypeSvg } from '$app/components/_shared/svg/MultiSelectTypeSvg';
-import { DocumentSvg } from '$app/components/_shared/svg/DocumentSvg';
-import { SingleSelectTypeSvg } from '$app/components/_shared/svg/SingleSelectTypeSvg';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { Some } from 'ts-results';
-import { useTranslation } from 'react-i18next';
-
-const typesOrder: FieldType[] = [
-  FieldType.RichText,
-  FieldType.Number,
-  FieldType.DateTime,
-  FieldType.SingleSelect,
-  FieldType.MultiSelect,
-  FieldType.Checkbox,
-  FieldType.URL,
-  FieldType.Checklist,
-];
-
-export const PropertiesPanel = ({
-  viewId,
-  controller,
-  rowInfo,
-  onDeletePropertyClick,
-  onNewColumnClick,
-}: {
-  viewId: string;
-  controller: DatabaseController;
-  rowInfo: RowInfo;
-  onDeletePropertyClick: (fieldId: string) => void;
-  onNewColumnClick: (initialFieldType: FieldType, name?: string) => Promise<void>;
-}) => {
-  const { cells } = useRow(viewId, controller, rowInfo);
-  const databaseStore = useAppSelector((state) => state.database);
-  const { t } = useTranslation();
-
-  const [showAddedProperties, setShowAddedProperties] = useState(true);
-  const [showBasicProperties, setShowBasicProperties] = useState(false);
-  const [showAdvancedProperties, setShowAdvancedProperties] = useState(false);
-
-  const [hoveredPropertyIndex, setHoveredPropertyIndex] = useState(-1);
-
-  const toggleHideProperty = async (v: boolean, index: number) => {
-    const fieldInfo = controller.fieldController.getField(cells[index].fieldId);
-
-    if (fieldInfo) {
-      const typeController = new TypeOptionController(viewId, Some(fieldInfo));
-
-      await typeController.initialize();
-      if (fieldInfo.field.visibility) {
-        await typeController.hideField();
-      } else {
-        await typeController.showField();
-      }
-    }
-  };
-
-  const addSelectedFieldType = async (fieldType: FieldType) => {
-    let name = 'New Field';
-
-    switch (fieldType) {
-      case FieldType.RichText:
-        name = t('grid.field.textFieldName');
-        break;
-      case FieldType.Number:
-        name = t('grid.field.numberFieldName');
-        break;
-      case FieldType.DateTime:
-        name = t('grid.field.dateFieldName');
-        break;
-      case FieldType.SingleSelect:
-        name = t('grid.field.singleSelectFieldName');
-        break;
-      case FieldType.MultiSelect:
-        name = t('grid.field.multiSelectFieldName');
-        break;
-      case FieldType.Checklist:
-        name = t('grid.field.checklistFieldName');
-        break;
-      case FieldType.URL:
-        name = t('grid.field.urlFieldName');
-        break;
-      case FieldType.Checkbox:
-        name = t('grid.field.checkboxFieldName');
-        break;
-    }
-
-    await onNewColumnClick(fieldType, name);
-  };
-
-  return (
-    <div className={'flex flex-col gap-2 overflow-auto px-4 py-12'}>
-      <div
-        onClick={() => setShowAddedProperties(!showAddedProperties)}
-        className={
-          'flex cursor-pointer items-center justify-between gap-8 rounded-lg px-2 py-2 text-text-title hover:bg-fill-list-active'
-        }
-      >
-        <div className={'text-sm'}>Added Properties</div>
-        <i className={`h-5 w-5 transition-transform duration-500 ${showAddedProperties && 'rotate-180'}`}>
-          <DropDownShowSvg></DropDownShowSvg>
-        </i>
-      </div>
-      <div className={'flex flex-col text-xs'} onMouseLeave={() => setHoveredPropertyIndex(-1)}>
-        {showAddedProperties &&
-          cells.map((cell, cellIndex) => (
-            <div
-              key={cellIndex}
-              onMouseEnter={() => setHoveredPropertyIndex(cellIndex)}
-              className={
-                'flex cursor-pointer items-center justify-between gap-4 rounded-lg px-2 py-1 hover:bg-fill-list-hover'
-              }
-            >
-              <div className={'flex items-center gap-2 text-text-title '}>
-                <div className={'flex h-5 w-5 flex-shrink-0 items-center justify-center'}>
-                  <FieldTypeIcon fieldType={cell.cellIdentifier.fieldType}></FieldTypeIcon>
-                </div>
-                <span className={'overflow-hidden text-ellipsis whitespace-nowrap'}>
-                  {databaseStore.fields[cell.cellIdentifier.fieldId]?.title ?? ''}
-                </span>
-              </div>
-              <div className={'flex items-center'}>
-                <i
-                  onClick={() => onDeletePropertyClick(cell.cellIdentifier.fieldId)}
-                  className={`h-[16px] w-[16px] text-text-title transition-opacity duration-300 ${
-                    hoveredPropertyIndex === cellIndex ? 'opacity-100' : 'opacity-0'
-                  }`}
-                >
-                  <TrashSvg></TrashSvg>
-                </i>
-                <Switch
-                  value={!!databaseStore.fields[cell.cellIdentifier.fieldId]?.visible}
-                  setValue={(v) => toggleHideProperty(v, cellIndex)}
-                ></Switch>
-              </div>
-            </div>
-          ))}
-      </div>
-      <div
-        onClick={() => setShowBasicProperties(!showBasicProperties)}
-        className={
-          'flex cursor-pointer items-center justify-between gap-8 rounded-lg px-2 py-2 hover:bg-fill-list-active'
-        }
-      >
-        <div className={'text-sm'}>Basic Properties</div>
-        <i className={`h-5 w-5 transition-transform duration-500 ${showBasicProperties && 'rotate-180'}`}>
-          <DropDownShowSvg></DropDownShowSvg>
-        </i>
-      </div>
-      <div className={'flex flex-col gap-2 text-xs'}>
-        {showBasicProperties && (
-          <div className={'flex flex-col'}>
-            {typesOrder.map((type, i) => (
-              <button
-                onClick={() => addSelectedFieldType(type)}
-                key={i}
-                className={'flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 pr-8 hover:bg-fill-list-hover'}
-              >
-                <i className={'h-5 w-5'}>
-                  <FieldTypeIcon fieldType={type}></FieldTypeIcon>
-                </i>
-                <span>
-                  <FieldTypeName fieldType={type}></FieldTypeName>
-                </span>
-              </button>
-            ))}
-          </div>
-        )}
-      </div>
-      <div
-        onClick={() => setShowAdvancedProperties(!showAdvancedProperties)}
-        className={
-          'flex cursor-pointer items-center justify-between gap-8 rounded-lg px-2 py-2 hover:bg-fill-list-active'
-        }
-      >
-        <div className={'text-sm'}>Advanced Properties</div>
-        <i className={`h-5 w-5 transition-transform duration-500 ${showAdvancedProperties && 'rotate-180'}`}>
-          <DropDownShowSvg></DropDownShowSvg>
-        </i>
-      </div>
-      <div className={'flex flex-col gap-2 text-xs'}>
-        {showAdvancedProperties && (
-          <div className={'flex flex-col'}>
-            <button
-              className={'flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              <i className={'h-5 w-5'}>
-                <MultiSelectTypeSvg></MultiSelectTypeSvg>
-              </i>
-              <span>Last edited time</span>
-            </button>
-            <button
-              className={'flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              <i className={'h-5 w-5'}>
-                <DocumentSvg></DocumentSvg>
-              </i>
-              <span>Document</span>
-            </button>
-            <button
-              className={'flex cursor-pointer items-center gap-2 rounded-lg px-2 py-2 pr-8 hover:bg-fill-list-hover'}
-            >
-              <i className={'h-5 w-5'}>
-                <SingleSelectTypeSvg></SingleSelectTypeSvg>
-              </i>
-              <span>Relation to</span>
-            </button>
-          </div>
-        )}
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/LanguageSelectPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/LanguageSelectPopup.tsx
deleted file mode 100644
index cb77d8cdeb..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/LanguageSelectPopup.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { IPopupItem, PopupSelect } from './PopupSelect';
-import i18n from 'i18next';
-
-const supportedLanguages: { key: string; title: string }[] = [
-  {
-    key: 'en',
-    title: 'English',
-  },
-  { key: 'ar-SA', title: 'ar-SA' },
-  { key: 'ca-ES', title: 'ca-ES' },
-  { key: 'de-DE', title: 'de-DE' },
-  { key: 'es-VE', title: 'es-VE' },
-  { key: 'eu-ES', title: 'eu-ES' },
-  { key: 'fr-CA', title: 'fr-CA' },
-  { key: 'fr-FR', title: 'fr-FR' },
-  { key: 'hu-HU', title: 'hu-HU' },
-  { key: 'id-ID', title: 'id-ID' },
-  { key: 'it-IT', title: 'it-IT' },
-  { key: 'ja-JP', title: 'ja-JP' },
-  { key: 'ko-KR', title: 'ko-KR' },
-  { key: 'pl-PL', title: 'pl-PL' },
-  { key: 'pt-BR', title: 'pt-BR' },
-  { key: 'pt-PT', title: 'pt-PT' },
-  { key: 'ru-RU', title: 'ru-RU' },
-  { key: 'sv', title: 'sv' },
-  { key: 'th-TH', title: 'th-TH' },
-  { key: 'tr-TR', title: 'tr-TR' },
-  { key: 'zh-CN', title: 'zh-CN' },
-  { key: 'zh-TW', title: 'zh-TW' },
-];
-
-export const LanguageSelectPopup = ({ onClose }: { onClose: () => void }) => {
-  const items: IPopupItem[] = supportedLanguages.map<IPopupItem>((item) => ({
-    onClick: () => {
-      void i18n.changeLanguage(item.key);
-      onClose();
-    },
-    title: item.title,
-    icon: <></>,
-  }));
-
-  return (
-    <PopupSelect
-      items={items}
-      className={'absolute top-full right-0 z-10 w-[200px]'}
-      onOutsideClick={onClose}
-      columns={2}
-    ></PopupSelect>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PopupSelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PopupSelect.tsx
deleted file mode 100644
index 6891ce540e..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PopupSelect.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { CSSProperties, MouseEvent, ReactNode, useRef } from 'react';
-import useOutsideClick from './useOutsideClick';
-
-export interface IPopupItem {
-  icon: ReactNode | (() => JSX.Element);
-  title: string;
-  onClick: () => void;
-}
-
-export const PopupSelect = ({
-  items,
-  className = '',
-  onOutsideClick,
-  columns = 1,
-  style,
-}: {
-  items: IPopupItem[];
-  className: string;
-  onOutsideClick?: () => void;
-  columns?: 1 | 2 | 3;
-  style?: CSSProperties;
-}) => {
-  const ref = useRef<HTMLDivElement>(null);
-
-  useOutsideClick(ref, () => onOutsideClick && onOutsideClick());
-
-  const handleClick = (e: MouseEvent, item: IPopupItem) => {
-    e.stopPropagation();
-    item.onClick();
-  };
-
-  return (
-    <div ref={ref} className={`${className} rounded-lg bg-bg-body px-2 py-2 text-text-title shadow-md`} style={style}>
-      <div
-        className={
-          (columns === 2 ? 'grid grid-cols-2' : '') + (columns === 3 ? 'grid grid-cols-3' : '') + ' w-full gap-x-4'
-        }
-      >
-        {items.map((item, index) => (
-          <button
-            key={index}
-            className={'flex w-full cursor-pointer items-center gap-2 rounded-lg px-2 py-2 hover:bg-fill-list-hover'}
-            onClick={(e) => handleClick(e, item)}
-          >
-            <>
-              {typeof item.icon === 'function' ? item.icon() : item.icon}
-              <span className={'flex-shrink-0'}>{item.title}</span>
-            </>
-          </button>
-        ))}
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PopupWindow.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PopupWindow.tsx
deleted file mode 100644
index 0075b61ea9..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PopupWindow.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { CSSProperties, ReactNode, useEffect, useRef, useState } from 'react';
-import useOutsideClick from '$app/components/_shared/useOutsideClick';
-
-export const PopupWindow = ({
-  children,
-  className,
-  onOutsideClick,
-  left,
-  top,
-  style,
-}: {
-  children: ReactNode;
-  className?: string;
-  onOutsideClick: () => void;
-  left: number;
-  top: number;
-  style?: CSSProperties;
-}) => {
-  const ref = useRef<HTMLDivElement>(null);
-
-  useOutsideClick(ref, onOutsideClick);
-
-  const [adjustedTop, setAdjustedTop] = useState(-100);
-  const [adjustedLeft, setAdjustedLeft] = useState(-100);
-  const [stickToBottom, setStickToBottom] = useState(false);
-  const [stickToRight, setStickToRight] = useState(false);
-
-  useEffect(() => {
-    if (!ref.current) return;
-
-    new ResizeObserver(() => {
-      if (!ref.current) return;
-      const { height, width } = ref.current.getBoundingClientRect();
-
-      setAdjustedTop(top);
-      if (top + height > window.innerHeight) {
-        setStickToBottom(true);
-      } else {
-        setStickToBottom(false);
-      }
-
-      setAdjustedLeft(left);
-      if (left + width > window.innerWidth) {
-        setStickToRight(true);
-      } else {
-        setStickToRight(false);
-      }
-    }).observe(ref.current);
-  }, [ref, left, top]);
-
-  return (
-    <div
-      ref={ref}
-      className={
-        'fixed z-10 rounded-lg bg-bg-body shadow-md transition-opacity duration-300 ' +
-        (adjustedTop === -100 && adjustedLeft === -100 ? 'opacity-0 ' : 'opacity-100 ') +
-        (className ?? '')
-      }
-      style={{
-        [stickToBottom ? 'bottom' : 'top']: `${stickToBottom ? '0' : adjustedTop}px`,
-        [stickToRight ? 'right' : 'left']: `${stickToRight ? '0' : adjustedLeft}px`,
-        ...style,
-      }}
-    >
-      {children}
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PromptWindow.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PromptWindow.tsx
deleted file mode 100644
index 97c095eafb..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/PromptWindow.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Button } from '$app/components/_shared/Button';
-
-export const PromptWindow = ({ msg, onYes, onCancel }: { msg: string; onYes: () => void; onCancel: () => void }) => {
-  return (
-    <div
-      className='fixed inset-0 z-20 flex items-center justify-center bg-black/30 backdrop-blur-sm'
-      onClick={() => onCancel()}
-    >
-      <div className={'rounded-xl bg-white p-16'} onClick={(e) => e.stopPropagation()}>
-        <div className={'flex flex-col items-center justify-center gap-8'}>
-          <div className={'text-text-title'}>{msg}</div>
-          <div className={'flex items-center justify-around gap-4'}>
-            <Button onClick={() => onCancel()} size={'medium-transparent'}>
-              Cancel
-            </Button>
-            <Button onClick={() => onYes()} size={'medium'}>
-              Yes
-            </Button>
-          </div>
-        </div>
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/SearchInput.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/SearchInput.tsx
deleted file mode 100644
index 15d020df6e..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/SearchInput.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { SearchSvg } from './svg/SearchSvg';
-import { useState } from 'react';
-
-export const SearchInput = () => {
-  const [active, setActive] = useState(false);
-
-  return (
-    <div className={`flex items-center rounded-lg border p-2 ${active ? 'border-fill-default' : 'border-line-divider'}`}>
-      <i className='mr-2 h-5 w-5'>
-        <SearchSvg />
-      </i>
-      <input
-        onFocus={() => setActive(true)}
-        onBlur={() => setActive(false)}
-        className='w-52 text-sm text-text-placeholder focus:text-text-title'
-        placeholder='Search'
-        type='search'
-      />
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Switch.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Switch.tsx
deleted file mode 100644
index 8edcdf39fd..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Switch.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export const Switch = ({ value, setValue }: { value: boolean; setValue: (v: boolean) => void }) => {
-  return (
-    <label className='form-switch' style={{ transform: 'scale(0.5)', marginRight: '-16px' }}>
-      <input type='checkbox' checked={value} onChange={() => setValue(!value)} />
-      <i></i>
-    </label>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/app-hooks/useUserSettingControllerContext.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/app-hooks/useUserSettingControllerContext.ts
deleted file mode 100644
index d2a459e06a..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/app-hooks/useUserSettingControllerContext.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { UserSettingController } from '$app/stores/effects/user/user_setting_controller';
-import { createContext, useContext } from 'react';
-
-export const UserSettingControllerContext = createContext<UserSettingController | undefined>(undefined);
-export function useUserSettingControllerContext() {
-  const context = useContext(UserSettingControllerContext);
-
-  return context;
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ButtonPopoverList/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/button_menu/ButtonMenu.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/ButtonPopoverList/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/button_menu/ButtonMenu.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/constants.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/constants.ts
deleted file mode 100644
index 48e51e7f9a..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/constants.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const INITIAL_FOLDER_HEIGHT = 40;
-export const FOLDER_MARGIN = 16;
-export const PAGE_ITEM_HEIGHT = 40;
-export const ANIMATION_DURATION = 300;
-export const NAV_PANEL_MINIMUM_WIDTH = 200;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts
deleted file mode 100644
index c01eeada67..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { Some } from 'ts-results';
-import { IDatabaseField, ISelectOption } from '$app_reducers/database/slice';
-import { FieldType, MultiSelectTypeOptionPB, SingleSelectTypeOptionPB } from '@/services/backend';
-import {
-  makeDateTypeOptionContext,
-  makeMultiSelectTypeOptionContext,
-  makeNumberTypeOptionContext,
-  makeSingleSelectTypeOptionContext,
-} from '$app/stores/effects/database/field/type_option/type_option_context';
-import { boardActions } from '$app_reducers/board/slice';
-import { FieldInfo } from '$app/stores/effects/database/field/field_controller';
-import { AppDispatch } from '$app/stores/store';
-
-export default async function (viewId: string, fieldInfo: FieldInfo, dispatch?: AppDispatch): Promise<IDatabaseField> {
-  const field = fieldInfo.field;
-  const typeOptionController = new TypeOptionController(viewId, Some(fieldInfo));
-
-  // temporary hack to set grouping field
-  let groupingFieldSelected = false;
-
-  switch (field.field_type) {
-    case FieldType.SingleSelect:
-    case FieldType.MultiSelect: {
-      let selectOptions: ISelectOption[] = [];
-      let typeOption: SingleSelectTypeOptionPB | MultiSelectTypeOptionPB | undefined;
-
-      if (field.field_type === FieldType.SingleSelect) {
-        typeOption = makeSingleSelectTypeOptionContext(typeOptionController).getTypeOption();
-        if (!groupingFieldSelected) {
-          if (dispatch) {
-            dispatch(boardActions.setGroupingFieldId({ fieldId: field.id }));
-          }
-
-          groupingFieldSelected = true;
-        }
-      }
-
-      if (field.field_type === FieldType.MultiSelect) {
-        typeOption = makeMultiSelectTypeOptionContext(typeOptionController).getTypeOption();
-      }
-
-      if (typeOption) {
-        selectOptions = typeOption.options.map<ISelectOption>((option) => {
-          return {
-            selectOptionId: option.id,
-            title: option.name,
-            color: option.color,
-          };
-        });
-      }
-
-      return {
-        fieldId: field.id,
-        title: field.name,
-        fieldType: field.field_type,
-        visible: field.visibility,
-        width: field.width,
-        fieldOptions: {
-          selectOptions,
-        },
-      };
-    }
-
-    case FieldType.Number: {
-      const typeOption = makeNumberTypeOptionContext(typeOptionController).getTypeOption();
-
-      return {
-        fieldId: field.id,
-        title: field.name,
-        visible: field.visibility,
-        width: field.width,
-        fieldType: field.field_type,
-        fieldOptions: {
-          numberFormat: typeOption.format,
-        },
-      };
-    }
-
-    case FieldType.DateTime: {
-      const typeOption = makeDateTypeOptionContext(typeOptionController).getTypeOption();
-
-      return {
-        fieldId: field.id,
-        title: field.name,
-        visible: field.visibility,
-        width: field.width,
-        fieldType: field.field_type,
-        fieldOptions: {
-          dateFormat: typeOption.date_format,
-          timeFormat: typeOption.time_format,
-        },
-      };
-    }
-
-    default: {
-      return {
-        fieldId: field.id,
-        title: field.name,
-        visible: field.visibility,
-        width: field.width,
-        fieldType: field.field_type,
-      };
-    }
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts
deleted file mode 100644
index 91a516ebeb..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { CellControllerBuilder } from '$app/stores/effects/database/cell/controller_builder';
-import { DateCellDataPB, SelectOptionCellDataPB, URLCellDataPB } from '@/services/backend';
-import { useEffect, useState } from 'react';
-import { CellController } from '$app/stores/effects/database/cell/cell_controller';
-import { useAppDispatch, useAppSelector } from '$app/stores/store';
-import { databaseActions, ISelectOptionType } from '$app_reducers/database/slice';
-
-export const useCell = (cellIdentifier: CellIdentifier, cellCache: CellCache, fieldController: FieldController) => {
-  const [data, setData] = useState<DateCellDataPB | URLCellDataPB | SelectOptionCellDataPB | string | undefined>();
-  // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  const [cellController, setCellController] = useState<CellController<any, any>>();
-  const databaseStore = useAppSelector((state) => state.database);
-  const dispatch = useAppDispatch();
-
-  useEffect(() => {
-    if (!cellIdentifier || !cellCache || !fieldController) return;
-    const builder = new CellControllerBuilder(cellIdentifier, cellCache, fieldController);
-    const c = builder.build();
-
-    setCellController(c);
-
-    c.subscribeChanged({
-      onCellChanged: (cellData) => {
-        if (cellData.some) {
-          const value = cellData.val;
-
-          setData(value);
-
-          // update redux store for database field if there are new select options
-          if (
-            value instanceof SelectOptionCellDataPB &&
-            databaseStore.fields[cellIdentifier.fieldId] &&
-            (databaseStore.fields[cellIdentifier.fieldId].fieldOptions as ISelectOptionType).selectOptions.length !==
-              value.options.length
-          ) {
-            const field = { ...databaseStore.fields[cellIdentifier.fieldId] };
-            const selectOptions = value.options.map((option) => ({
-              selectOptionId: option.id,
-              title: option.name,
-              color: option.color,
-            }));
-
-            dispatch(
-              databaseActions.updateField({
-                field: {
-                  ...field,
-                  fieldOptions: {
-                    ...field.fieldOptions,
-                    selectOptions: selectOptions,
-                  },
-                },
-              })
-            );
-          }
-        }
-      },
-    });
-
-    void (async () => {
-      try {
-        const cellData = await c.getCellData();
-
-        if (cellData.some) {
-          setData(cellData.unwrap());
-        }
-      } catch (e) {
-        // mute for now
-      }
-    })();
-
-    return () => {
-      void c.dispose();
-    };
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [cellIdentifier, cellCache, fieldController]);
-
-  return {
-    cellController,
-    data,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts
deleted file mode 100644
index 70a10d19c7..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts
+++ /dev/null
@@ -1,224 +0,0 @@
-import { useCallback, useEffect, useMemo, useState } from 'react';
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import {
-  databaseActions,
-  DatabaseFieldMap,
-  IDatabaseColumn,
-  IDatabaseFilter,
-  TDatabaseOperators,
-} from '$app/stores/reducers/database/slice';
-import { useAppDispatch } from '$app/stores/store';
-import loadField from './loadField';
-import { FieldInfo } from '$app/stores/effects/database/field/field_controller';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import {
-  FieldType,
-  SelectOptionConditionPB,
-  SelectOptionFilterPB,
-  TextFilterConditionPB,
-  TextFilterPB,
-  ViewLayoutPB,
-} from '@/services/backend';
-import { DatabaseGroupController } from '$app/stores/effects/database/group/group_controller';
-import { OnDragEndResponder } from 'react-beautiful-dnd';
-import { AsyncQueue } from '$app/utils/async_queue';
-
-export const useDatabase = (viewId: string, type?: ViewLayoutPB) => {
-  const dispatch = useAppDispatch();
-  const [controller, setController] = useState<DatabaseController>();
-  const [rows, setRows] = useState<readonly RowInfo[]>([]);
-  const [groups, setGroups] = useState<readonly DatabaseGroupController[]>([]);
-  const [groupByFieldId, setGroupByFieldId] = useState('');
-
-  useEffect(() => {
-    if (!viewId.length) return;
-    const c = new DatabaseController(viewId);
-
-    setController(c);
-
-    return () => void c.dispose();
-  }, [viewId]);
-
-  const loadFields = useCallback(
-    async (fieldInfos: readonly FieldInfo[]) => {
-      const fields: DatabaseFieldMap = {};
-      const columns: IDatabaseColumn[] = [];
-
-      for (const fieldInfo of fieldInfos) {
-        const fieldPB = fieldInfo.field;
-
-        columns.push({
-          fieldId: fieldPB.id,
-          sort: 'none',
-          visible: fieldPB.visibility,
-        });
-
-        const field = await loadField(viewId, fieldInfo, dispatch);
-
-        fields[field.fieldId] = field;
-      }
-
-      dispatch(databaseActions.updateFields({ fields }));
-      dispatch(databaseActions.updateColumns({ columns }));
-    },
-    [viewId, dispatch]
-  );
-
-  const queue = useMemo(() => {
-    return new AsyncQueue<readonly FieldInfo[]>(loadFields);
-  }, [loadFields]);
-
-  const transformCondition: (condition: number, fieldType: FieldType) => TDatabaseOperators = (condition, fieldType) => {
-    switch (fieldType) {
-      case FieldType.RichText:
-        switch (condition) {
-          case TextFilterConditionPB.Contains:
-            return 'contains';
-          case TextFilterConditionPB.DoesNotContain:
-            return 'doesNotContain';
-          case TextFilterConditionPB.EndsWith:
-            return 'endsWith';
-          case TextFilterConditionPB.StartsWith:
-            return 'startWith';
-          case TextFilterConditionPB.Is:
-            return 'is';
-          case TextFilterConditionPB.IsNot:
-            return 'isNot';
-          case TextFilterConditionPB.TextIsEmpty:
-            return 'isEmpty';
-          case TextFilterConditionPB.TextIsNotEmpty:
-            return 'isNotEmpty';
-          default:
-            return 'is';
-        }
-
-      case FieldType.SingleSelect:
-      case FieldType.MultiSelect:
-        switch (condition) {
-          case SelectOptionConditionPB.OptionIs:
-            return 'is';
-          case SelectOptionConditionPB.OptionIsNot:
-            return 'isNot';
-          case SelectOptionConditionPB.OptionIsEmpty:
-            return 'isEmpty';
-          case SelectOptionConditionPB.OptionIsNotEmpty:
-            return 'isNotEmpty';
-          default:
-            return 'is';
-        }
-
-      default:
-        return 'is';
-    }
-  };
-
-  useEffect(() => {
-    void (async () => {
-      if (!controller) return;
-      controller.subscribe({
-        onRowsChanged: (rowInfos) => {
-          // TODO: this is a hack to make sure that the row cache is updated
-          setRows([...rowInfos]);
-        },
-        onFieldsChanged: (fieldInfos) => {
-          queue.enqueue(fieldInfos);
-        },
-        onFiltersChanged: (filters) => {
-          const reduxFilters = filters.map<IDatabaseFilter>((filter) => {
-            switch (filter.field_type) {
-              case FieldType.SingleSelect:
-              case FieldType.MultiSelect:
-                return {
-                  logicalOperator: 'and',
-                  fieldType: filter.field_type,
-                  fieldId: filter.field_id,
-                  id: filter.id,
-                  operator: transformCondition((filter.data as SelectOptionFilterPB).condition, filter.field_type),
-                  value: (filter.data as SelectOptionFilterPB).option_ids,
-                };
-              case FieldType.RichText:
-                return {
-                  logicalOperator: 'and',
-                  fieldType: filter.field_type,
-                  fieldId: filter.field_id,
-                  id: filter.id,
-                  operator: transformCondition((filter.data as TextFilterPB).condition, filter.field_type),
-                  value: (filter.data as TextFilterPB).content,
-                };
-
-              default:
-                return {
-                  logicalOperator: 'and',
-                  fieldType: filter.field_type,
-                  fieldId: filter.field_id,
-                  id: filter.id,
-                  operator: 'is',
-                  value: '',
-                };
-            }
-          });
-
-          dispatch(databaseActions.updateFilters({ filters: reduxFilters }));
-        },
-        onSortChanged: (sorts) => {
-          dispatch(databaseActions.updateSorts({ sorts: [...sorts] }));
-        },
-      });
-
-      const openResult = await controller.open();
-
-      if (openResult.ok) {
-        setRows(
-          openResult.val.map((pb) => {
-            return new RowInfo(viewId, controller.fieldController.fieldInfos, pb);
-          })
-        );
-      }
-
-      if (type === ViewLayoutPB.Board) {
-        const fieldId = await controller.getGroupByFieldId();
-
-        setGroupByFieldId(fieldId.unwrap());
-        setGroups(controller.groups.value);
-      }
-    })();
-
-    return () => {
-      void controller?.dispose();
-    };
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [controller, queue]);
-
-  const onNewRowClick = async (index: number) => {
-    if (!groups) return;
-    if (!controller?.groups) return;
-    const group = groups[index];
-
-    await group.createRow();
-
-    setGroups([...controller.groups.value]);
-  };
-
-  const onDragEnd: OnDragEndResponder = async (result) => {
-    if (!controller) return;
-    const { source, destination } = result;
-    const group = groups.find((g) => g.groupId === source.droppableId);
-
-    if (!group) return;
-
-    if (source.droppableId === destination?.droppableId) {
-      // move inside the block (group)
-      await controller.exchangeGroupRow(
-        group.rows[source.index].id,
-        destination.droppableId,
-        group.rows[destination.index].id
-      );
-    } else {
-      // move to different block (group)
-      if (!destination?.droppableId) return;
-      await controller.moveGroupRow(group.rows[source.index].id, destination.droppableId);
-    }
-  };
-
-  return { loadFields, controller, rows, groups, groupByFieldId, onNewRowClick, onDragEnd };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts
deleted file mode 100644
index 2d08a5b399..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import { RowController } from '$app/stores/effects/database/row/row_controller';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { useEffect, useState } from 'react';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { useAppSelector } from '$app/stores/store';
-import { FieldType } from '@/services/backend';
-import { None } from 'ts-results';
-
-export const useRow = (viewId: string, databaseController: DatabaseController, rowInfo: RowInfo) => {
-  const [cells, setCells] = useState<{ fieldId: string; cellIdentifier: CellIdentifier }[]>([]);
-  const [rowController, setRowController] = useState<RowController>();
-  const databaseStore = useAppSelector((state) => state.database);
-
-  useEffect(() => {
-    if (!databaseController || !rowInfo) return;
-    const rowCache = databaseController.databaseViewCache.getRowCache();
-    const fieldController = databaseController.fieldController;
-    const c = new RowController(rowInfo, fieldController, rowCache);
-
-    setRowController(c);
-
-    return () => {
-      // dispose row controller in future
-    };
-  }, [databaseController, rowInfo]);
-
-  useEffect(() => {
-    if (!rowController) return;
-
-    void (async () => {
-      const cellsPB = await rowController.loadCells();
-      const loadingCells: { fieldId: string; cellIdentifier: CellIdentifier }[] = [];
-
-      for (const [fieldId, cellIdentifier] of cellsPB.entries()) {
-        loadingCells.push({
-          fieldId,
-          cellIdentifier,
-        });
-      }
-
-      setCells(loadingCells);
-    })();
-  }, [rowController, databaseStore.columns]);
-
-  const onNewColumnClick = async (initialFieldType: FieldType = FieldType.RichText, name?: string) => {
-    if (!databaseController) return;
-    const controller = new TypeOptionController(viewId, None, initialFieldType);
-
-    await controller.initialize();
-    if (name) {
-      await controller.setFieldName(name);
-    }
-  };
-
-  return {
-    cells,
-    onNewColumnClick,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/app-dialog/ConfirmDialog.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/delete_confirm_dialog/DeleteConfirmDialog.tsx
similarity index 91%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/app-dialog/ConfirmDialog.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/delete_confirm_dialog/DeleteConfirmDialog.tsx
index e506a74990..5723505b4c 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/app-dialog/ConfirmDialog.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/delete_confirm_dialog/DeleteConfirmDialog.tsx
@@ -12,7 +12,7 @@ interface Props {
   onClose: () => void;
 }
 
-function ConfirmDialog({ open, title, subtitle, onOk, onClose }: Props) {
+function DeleteConfirmDialog({ open, title, subtitle, onOk, onClose }: Props) {
   const { t } = useTranslation();
 
   return (
@@ -42,4 +42,4 @@ function ConfirmDialog({ open, title, subtitle, onOk, onClose }: Props) {
   );
 }
 
-export default ConfirmDialog;
+export default DeleteConfirmDialog;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag-block/drag.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag_block/drag.hooks.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag-block/drag.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag_block/drag.hooks.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag-block/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag_block/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag-block/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/drag_block/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPicker.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPicker.hooks.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPicker.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPicker.hooks.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPicker.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPicker.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPickerCategories.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPickerCategories.tsx
similarity index 98%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPickerCategories.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPickerCategories.tsx
index 10f2574aaf..fff09cf7aa 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPickerCategories.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPickerCategories.tsx
@@ -5,7 +5,7 @@ import {
   getRowsWithCategories,
   PER_ROW_EMOJI_COUNT,
   useVirtualizedCategories,
-} from '$app/components/_shared/EmojiPicker/EmojiPicker.hooks';
+} from '$app/components/_shared/emoji_picker/EmojiPicker.hooks';
 import { useTranslation } from 'react-i18next';
 import { IconButton } from '@mui/material';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPickerHeader.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPickerHeader.tsx
similarity index 99%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPickerHeader.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPickerHeader.tsx
index 06f96e7397..d4867fb517 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/EmojiPicker/EmojiPickerHeader.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/emoji_picker/EmojiPickerHeader.tsx
@@ -6,7 +6,7 @@ import Tooltip from '@mui/material/Tooltip';
 import { randomEmoji } from '$app/utils/emoji';
 import ShuffleIcon from '@mui/icons-material/Shuffle';
 import Popover from '@mui/material/Popover';
-import { useSelectSkinPopoverProps } from '$app/components/_shared/EmojiPicker/EmojiPicker.hooks';
+import { useSelectSkinPopoverProps } from '$app/components/_shared/emoji_picker/EmojiPicker.hooks';
 import { useTranslation } from 'react-i18next';
 
 const skinTones = [
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/getColor.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/getColor.ts
deleted file mode 100644
index dd06cd03a3..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/getColor.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { SelectOptionColorPB } from '@/services/backend';
-
-export const getBgColor = (color: SelectOptionColorPB | undefined): string => {
-  switch (color) {
-    case SelectOptionColorPB.Purple:
-      return 'bg-tint-purple';
-    case SelectOptionColorPB.Pink:
-      return 'bg-tint-pink';
-    case SelectOptionColorPB.LightPink:
-      return 'bg-tint-red';
-    case SelectOptionColorPB.Orange:
-      return 'bg-tint-orange';
-    case SelectOptionColorPB.Yellow:
-      return 'bg-tint-yellow';
-    case SelectOptionColorPB.Lime:
-      return 'bg-tint-lime';
-    case SelectOptionColorPB.Green:
-      return 'bg-tint-green';
-    case SelectOptionColorPB.Aqua:
-      return 'bg-tint-aqua';
-    case SelectOptionColorPB.Blue:
-      return 'bg-tint-blue';
-    default:
-      return '';
-  }
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/KatexMath/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/katex_math/KatexMath.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/KatexMath/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/katex_math/KatexMath.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/KatexMath/index.css b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/katex_math/index.css
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/KatexMath/index.css
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/katex_math/index.css
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/useOutsideClick.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/useOutsideClick.ts
deleted file mode 100644
index 00a6876d25..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/useOutsideClick.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { useEffect } from 'react';
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export default function useOutsideClick(ref: any, handler: (e: MouseEvent | TouchEvent) => void) {
-  useEffect(
-    () => {
-      const listener = (event: MouseEvent | TouchEvent) => {
-        // Do nothing if clicking ref's element or descendent elements
-        if (!ref?.current || ref.current.contains(event.target)) {
-          return;
-        }
-
-        handler(event);
-      };
-
-      document.addEventListener('mousedown', listener);
-      document.addEventListener('touchstart', listener);
-      return () => {
-        document.removeEventListener('mousedown', listener);
-        document.removeEventListener('touchstart', listener);
-      };
-    },
-    // Add ref and handler to effect dependencies
-    // It's worth noting that because passed in handler is a new ...
-    // ... function on every render that will cause this effect ...
-    // ... callback/cleanup to run every render. It's not a big deal ...
-    // ... but to optimize you can wrap handler in useCallback before ...
-    // ... passing it into this hook.
-    [ref, handler]
-  );
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/useResizer.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/useResizer.ts
deleted file mode 100644
index a3367a9ad7..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/useResizer.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import React, { useState } from 'react';
-
-export const useResizer = (onEnd?: (final: number) => void) => {
-  const [movementX, setMovementX] = useState(0);
-  const [movementY, setMovementY] = useState(0);
-  const [newSizeX, setNewSizeX] = useState(0);
-  const [newSizeY, setNewSizeY] = useState(0);
-
-  const onMouseDown = (e1: React.MouseEvent<HTMLElement>, initial = 0) => {
-    const startX = e1.screenX;
-    const startY = e1.screenY;
-
-    setNewSizeX(initial);
-    setNewSizeY(initial);
-
-    const onMouseMove = (e2: MouseEvent) => {
-      setNewSizeX(initial + e2.screenX - startX);
-      setNewSizeY(initial + e2.screenY - startY);
-      setMovementX(e2.movementX);
-      setMovementY(e2.movementY);
-    };
-
-    const onMouseUp = (e2: MouseEvent) => {
-      onEnd?.(initial + e2.screenX - startX);
-      window.removeEventListener('mousemove', onMouseMove);
-      window.removeEventListener('mouseup', onMouseUp);
-    };
-
-    window.addEventListener('mousemove', onMouseMove);
-    window.addEventListener('mouseup', onMouseUp);
-  };
-
-  return {
-    movementX,
-    movementY,
-    newSizeX,
-    newSizeY,
-    onMouseDown,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewBanner.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewBanner.tsx
similarity index 79%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewBanner.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewBanner.tsx
index f53c381bfd..99f444ac26 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewBanner.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewBanner.tsx
@@ -1,6 +1,6 @@
-import ViewIconGroup from '$app/components/_shared/ViewTitle/ViewIconGroup';
+import ViewIconGroup from '$app/components/_shared/view_title/ViewIconGroup';
 import { PageIcon } from '$app_reducers/pages/slice';
-import ViewIcon from '$app/components/_shared/ViewTitle/ViewIcon';
+import ViewIcon from '$app/components/_shared/view_title/ViewIcon';
 
 function ViewBanner({
   icon,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewIcon.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewIcon.tsx
similarity index 94%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewIcon.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewIcon.tsx
index 6aaa947f86..147bd1cbb0 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewIcon.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewIcon.tsx
@@ -1,6 +1,6 @@
 import React, { useCallback, useState } from 'react';
 import Popover from '@mui/material/Popover';
-import EmojiPicker from '$app/components/_shared/EmojiPicker';
+import EmojiPicker from '$app/components/_shared/emoji_picker/EmojiPicker';
 import { PageIcon } from '$app_reducers/pages/slice';
 
 function ViewIcon({ icon, onUpdateIcon }: { icon?: PageIcon; onUpdateIcon: (icon: string) => void }) {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewIconGroup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewIconGroup.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewIconGroup.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewIconGroup.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewTitle.tsx
similarity index 89%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewTitle.tsx
index 3df18b1a87..26f83ac921 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewTitle.tsx
@@ -1,8 +1,8 @@
 import React, { useCallback, useEffect, useState } from 'react';
-import ViewBanner from '$app/components/_shared/ViewTitle/ViewBanner';
+import ViewBanner from '$app/components/_shared/view_title/ViewBanner';
 import { Page, PageIcon } from '$app_reducers/pages/slice';
 import { ViewIconTypePB } from '@/services/backend';
-import ViewTitleInput from '$app/components/_shared/ViewTitle/ViewTitleInput';
+import ViewTitleInput from '$app/components/_shared/view_title/ViewTitleInput';
 
 interface Props {
   view: Page;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewTitleInput.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewTitleInput.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/_shared/ViewTitle/ViewTitleInput.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/_shared/view_title/ViewTitleInput.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ConfirmAccount/ConfirmAccount.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/auth/ConfirmAccount/ConfirmAccount.hooks.ts
deleted file mode 100644
index 2d92317fcc..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ConfirmAccount/ConfirmAccount.hooks.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { useState } from 'react';
-import { currentUserActions } from '../../../stores/reducers/current-user/slice';
-import { useAppDispatch, useAppSelector } from '../../../stores/store';
-import { useNavigate } from 'react-router-dom';
-
-export const useConfirmAccount = () => {
-  const [otpValues, setOtpValues] = useState('');
-  const appDispatch = useAppDispatch();
-  const currentUser = useAppSelector((state) => state.currentUser);
-  const navigate = useNavigate();
-
-  const handleChange = (value: string) => {
-    console.log({ value });
-    setOtpValues(value);
-  };
-
-  const onConfirmClick = () => {
-    appDispatch(
-      currentUserActions.updateUser({
-        ...currentUser,
-        isAuthenticated: true,
-      })
-    );
-    navigate('/');
-  };
-
-  return {
-    otpValues,
-    handleChange,
-    onConfirmClick,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ConfirmAccount/ConfirmAccount.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/auth/ConfirmAccount/ConfirmAccount.tsx
deleted file mode 100644
index cca91cc10d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ConfirmAccount/ConfirmAccount.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import OtpInput from 'react18-input-otp';
-import { AppflowyLogo } from '../../_shared/svg/AppflowyLogo';
-import { useConfirmAccount } from './ConfirmAccount.hooks';
-import { Button } from '../../_shared/Button';
-
-export const ConfirmAccount = () => {
-  const { handleChange, otpValues, onConfirmClick } = useConfirmAccount();
-
-  return (
-    <div className='flex h-screen w-full flex-col items-center justify-center gap-12 text-center'>
-      <div className='flex h-10 w-10 justify-center'>
-        <AppflowyLogo />
-      </div>
-
-      <div className='flex flex-col gap-2'>
-        <span className='text-2xl font-semibold '>Enter the code sent to your phone</span>
-        <div>
-          <span className='block text-gray-500'>Confirm that this phone belongs to you.</span>
-          <span className='block text-gray-500'>
-            Code sent to <span className='text-text-title'>+86 10 6764 5489</span>
-          </span>
-        </div>
-      </div>
-
-      <div className='flex h-24 flex-col gap-4 '>
-        <div className={'flex-1'}>
-          <OtpInput
-            value={otpValues}
-            onChange={handleChange}
-            numInputs={5}
-            isInputNum={true}
-            separator={<span> </span>}
-            inputStyle='border border-gray-300 rounded-lg h-full !w-14 font-semibold   focus:ring-2 focus:ring-fill-hover focus:ring-opacity-50'
-            containerStyle='h-full w-full flex justify-around gap-2 '
-          />
-        </div>
-
-        <a href='#' className='hover:text-content-hover text-xs text-fill-hover'>
-          <span>Send code again</span>
-        </a>
-      </div>
-
-      <Button size={'primary'} onClick={() => onConfirmClick()}>
-        Get Started
-      </Button>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.tsx
deleted file mode 100644
index a98681f46d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-import { AppflowyLogo } from '../../_shared/svg/AppflowyLogo';
-import { EyeClosedSvg } from '../../_shared/svg/EyeClosedSvg';
-import { EyeOpenSvg } from '../../_shared/svg/EyeOpenSvg';
-import { useLogin } from './Login.hooks';
-import { Link } from 'react-router-dom';
-import { Button } from '../../_shared/Button';
-import { useTranslation } from 'react-i18next';
-import { EarthSvg } from '../../_shared/svg/EarthSvg';
-import { useState } from 'react';
-import { LanguageSelectPopup } from '../../_shared/LanguageSelectPopup';
-
-export const Login = () => {
-  const { showPassword, onTogglePassword, onSignInClick, email, setEmail, password, setPassword, authError } =
-    useLogin();
-  const { t } = useTranslation();
-  const [showLanguagePopup, setShowLanguagePopup] = useState(false);
-
-  return (
-    <>
-      <form onSubmit={(e) => e.preventDefault()} method='POST'>
-        <div className='relative flex h-screen w-screen flex-col items-center justify-center gap-12 bg-bg-body text-center text-text-title'>
-          <div className='flex h-10 w-10 justify-center'>
-            <AppflowyLogo />
-          </div>
-
-          <div>
-            <span className='text-2xl font-semibold leading-9'>
-              {t('signIn.loginTitle').replace('@:appName', 'AppFlowy')}
-            </span>
-          </div>
-
-          <div className='flex w-full max-w-[340px]  flex-col gap-6 '>
-            <input
-              type='text'
-              className={`input w-full ${authError && 'error'}`}
-              placeholder={t('signIn.emailHint') ?? ''}
-              value={email}
-              onChange={(e) => setEmail(e.target.value)}
-            />
-            <div className='relative w-full'>
-              {/* Password input field */}
-
-              <input
-                type={showPassword ? 'text' : 'password'}
-                className={`input w-full  !pr-10 ${authError && 'error'}`}
-                placeholder={t('signIn.passwordHint') ?? ''}
-                value={password}
-                onChange={(e) => setPassword(e.target.value)}
-              />
-
-              {/* Show password button */}
-              <button
-                type='button'
-                className='absolute right-0 top-0 flex h-full w-12 items-center justify-center '
-                onClick={onTogglePassword}
-              >
-                <span className='h-6 w-6'>{showPassword ? <EyeClosedSvg /> : <EyeOpenSvg />}</span>
-              </button>
-            </div>
-
-            <div className='flex justify-center'>
-              {/* Forget password link */}
-              <Link to={'/auth/confirm-account'}>
-                <span className='text-xs text-fill-default hover:text-fill-hover'>{t('signIn.forgotPassword')}</span>
-              </Link>
-            </div>
-          </div>
-
-          <div className='flex w-full max-w-[340px] flex-col gap-6 '>
-            <Button size={'primary'} onClick={() => onSignInClick()}>
-              {t('signIn.loginButtonText')}
-            </Button>
-
-            {/* signup link */}
-            <div className='flex justify-center'>
-              <span className='text-xs text-gray-400'>
-                {t('signIn.dontHaveAnAccount')}
-                <Link to={'/auth/signUp'}>
-                  <span className='ml-2 text-fill-default hover:text-fill-hover'>{t('signUp.buttonText')}</span>
-                </Link>
-              </span>
-            </div>
-          </div>
-
-          <div className={'absolute right-0 top-0 px-12 py-8'}>
-            <div className={'relative h-full w-full'}>
-              <button
-                className={'h-8 w-8 text-text-caption hover:text-text-title'}
-                onClick={() => setShowLanguagePopup(true)}
-              >
-                <EarthSvg></EarthSvg>
-              </button>
-              {showLanguagePopup && (
-                <LanguageSelectPopup onClose={() => setShowLanguagePopup(false)}></LanguageSelectPopup>
-              )}
-            </div>
-          </div>
-        </div>
-      </form>
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx
index 3f55079677..341eff871e 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx
@@ -1,28 +1,22 @@
 import { Outlet } from 'react-router-dom';
 import { useAuth } from './auth.hooks';
 import Layout from '$app/components/layout/Layout';
-import { useEffect, useState } from 'react';
-import { GetStarted } from './GetStarted/GetStarted';
+import { useCallback, useEffect, useState } from 'react';
+import { GetStarted } from '$app/components/auth/get_started/GetStarted';
 import { AppflowyLogo } from '../_shared/svg/AppflowyLogo';
 
 export const ProtectedRoutes = () => {
   const { currentUser, checkUser } = useAuth();
   const [isLoading, setIsLoading] = useState(true);
 
-  useEffect(() => {
-    void checkUser().then(async (result) => {
-      await new Promise(() =>
-        setTimeout(() => {
-          setIsLoading(false);
-        }, 1200)
-      );
+  const checkUserStatus = useCallback(async () => {
+    await checkUser();
+    setIsLoading(false);
+  }, [checkUser]);
 
-      if (result.err) {
-        throw new Error(result.val.msg);
-      }
-    });
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, []);
+  useEffect(() => {
+    void checkUserStatus();
+  }, [checkUserStatus]);
 
   if (isLoading) {
     // It's better to make a fading effect to disappear the loading page
@@ -50,6 +44,6 @@ const SplashScreen = ({ isAuthenticated }: { isAuthenticated: boolean }) => {
       </Layout>
     );
   } else {
-    return <GetStarted></GetStarted>;
+    return <GetStarted />;
   }
 };
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/SignUp/SignUp.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/auth/SignUp/SignUp.hooks.ts
deleted file mode 100644
index c97b73117b..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/SignUp/SignUp.hooks.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { useState } from 'react';
-import { useAppDispatch } from '$app/stores/store';
-import { currentUserActions } from '$app_reducers/current-user/slice';
-import { useNavigate } from 'react-router-dom';
-import { useAuth } from '../auth.hooks';
-
-export const useSignUp = () => {
-  const [email, _setEmail] = useState('');
-  const [displayName, _setDisplayName] = useState('');
-  const [password, _setPassword] = useState('');
-  const [repeatedPassword, _setRepeatedPassword] = useState('');
-  const [showPassword, setShowPassword] = useState(false);
-  const [showConfirmPassword, setShowConfirmPassword] = useState(false);
-  const appDispatch = useAppDispatch();
-  const navigate = useNavigate();
-  const { register } = useAuth();
-  const [authError, setAuthError] = useState(false);
-
-  const setEmail = (v: string) => {
-    setAuthError(false);
-    _setEmail(v);
-  };
-
-  const setDisplayName = (v: string) => {
-    setAuthError(false);
-    _setDisplayName(v);
-  };
-
-  const setPassword = (v: string) => {
-    setAuthError(false);
-    _setPassword(v);
-  };
-
-  const setRepeatedPassword = (v: string) => {
-    setAuthError(false);
-    _setRepeatedPassword(v);
-  };
-
-  function onTogglePassword() {
-    setShowPassword(!showPassword);
-  }
-
-  function onToggleConfirmPassword() {
-    setShowConfirmPassword(!showConfirmPassword);
-  }
-
-  async function onSignUpClick() {
-    try {
-      const result = await register(email, password, displayName);
-      const { id, token } = result;
-
-      appDispatch(
-        currentUserActions.updateUser({
-          id,
-          token,
-          email,
-          displayName,
-          isAuthenticated: true,
-        })
-      );
-      navigate('/');
-    } catch (e) {
-      setAuthError(true);
-    }
-  }
-
-  return {
-    email,
-    setEmail,
-    displayName,
-    setDisplayName,
-    password,
-    setPassword,
-    repeatedPassword,
-    setRepeatedPassword,
-    showPassword,
-    onTogglePassword,
-    showConfirmPassword,
-    onToggleConfirmPassword,
-    onSignUpClick,
-    authError,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/SignUp/SignUp.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/auth/SignUp/SignUp.tsx
deleted file mode 100644
index 135536ff05..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/SignUp/SignUp.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-import { AppflowyLogo } from '../../_shared/svg/AppflowyLogo';
-import { EyeClosedSvg } from '../../_shared/svg/EyeClosedSvg';
-import { EyeOpenSvg } from '../../_shared/svg/EyeOpenSvg';
-
-import { useSignUp } from './SignUp.hooks';
-import { Link } from 'react-router-dom';
-import { Button } from '../../_shared/Button';
-import { EarthSvg } from '../../_shared/svg/EarthSvg';
-import { LanguageSelectPopup } from '../../_shared/LanguageSelectPopup';
-import { useTranslation } from 'react-i18next';
-import { useState } from 'react';
-
-export const SignUp = () => {
-  const {
-    showPassword,
-    onTogglePassword,
-    showConfirmPassword,
-    onToggleConfirmPassword,
-    onSignUpClick,
-    email,
-    setEmail,
-    displayName,
-    setDisplayName,
-    password,
-    setPassword,
-    repeatedPassword,
-    setRepeatedPassword,
-    authError,
-  } = useSignUp();
-  const { t } = useTranslation();
-  const [showLanguagePopup, setShowLanguagePopup] = useState(false);
-
-  return (
-    <form method='POST' onSubmit={(e) => e.preventDefault()}>
-      <div className='relative flex h-screen w-full flex-col items-center justify-center gap-12 text-center'>
-        <div className='flex h-10 w-10 justify-center'>
-          <AppflowyLogo />
-        </div>
-
-        <div>
-          <span className='text-2xl font-semibold'>{t('signUp.title').replace('@:appName', 'AppFlowy')}</span>
-        </div>
-
-        <div className='flex w-full max-w-[340px]  flex-col gap-6'>
-          <input
-            type='text'
-            className={`input w-full ${authError && 'error'}`}
-            placeholder={t('signUp.emailHint') ?? ''}
-            value={email}
-            onChange={(e) => setEmail(e.target.value)}
-          />
-          {/* new user should enter his name, need translation for this field */}
-          <input
-            type='text'
-            className={`input w-full ${authError && 'error'}`}
-            placeholder='Name'
-            value={displayName}
-            onChange={(e) => setDisplayName(e.target.value)}
-          />
-          <div className='relative w-full'>
-            <input
-              type={showPassword ? 'text' : 'password'}
-              className={`input w-full !pr-10 ${authError && 'error'}`}
-              placeholder={t('signUp.passwordHint') ?? ''}
-              value={password}
-              onChange={(e) => setPassword(e.target.value)}
-            />
-
-            <button
-              className='absolute right-0 top-0 flex h-full w-12 items-center justify-center '
-              onClick={onTogglePassword}
-              type='button'
-            >
-              <span className='h-6 w-6'>{showPassword ? <EyeClosedSvg /> : <EyeOpenSvg />}</span>
-            </button>
-          </div>
-
-          <div className='relative w-full'>
-            <input
-              type={showConfirmPassword ? 'text' : 'password'}
-              className={`input w-full !pr-10 ${authError && 'error'}`}
-              placeholder={t('signUp.repeatPasswordHint') ?? ''}
-              value={repeatedPassword}
-              onChange={(e) => setRepeatedPassword(e.target.value)}
-            />
-
-            <button
-              className='absolute right-0 top-0 flex h-full w-12 items-center justify-center '
-              onClick={onToggleConfirmPassword}
-              type='button'
-            >
-              <span className='h-6 w-6'>{showConfirmPassword ? <EyeClosedSvg /> : <EyeOpenSvg />}</span>
-            </button>
-          </div>
-        </div>
-
-        <div className='flex w-full max-w-[340px] flex-col gap-6 '>
-          <Button size={'primary'} onClick={() => onSignUpClick()}>
-            {t('signUp.getStartedText')}
-          </Button>
-
-          {/* signup link */}
-          <div className='flex justify-center'>
-            <span className='text-xs text-gray-500'>
-              {t('signUp.alreadyHaveAnAccount')}
-              <Link to={'/auth/login'}>
-                <span className='hover:text-content-hover ml-2 text-fill-hover'>{t('signIn.buttonText')}</span>
-              </Link>
-            </span>
-          </div>
-        </div>
-
-        <div className={'absolute right-0 top-0 px-12 py-8'}>
-          <div className={'relative h-full w-full'}>
-            <button
-              className={'h-8 w-8 text-text-caption hover:text-text-title'}
-              onClick={() => setShowLanguagePopup(true)}
-            >
-              <EarthSvg></EarthSvg>
-            </button>
-            {showLanguagePopup && (
-              <LanguageSelectPopup onClose={() => setShowLanguagePopup(false)}></LanguageSelectPopup>
-            )}
-          </div>
-        </div>
-      </div>
-    </form>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts
index e3afe55c2a..b9342fb210 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts
@@ -1,57 +1,44 @@
-import { currentUserActions } from '../../stores/reducers/current-user/slice';
-import { useAppDispatch, useAppSelector } from '../../stores/store';
-import { UserProfilePB } from '../../../services/backend/events/flowy-user';
-import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc';
-import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder/workspace';
-import { Log } from '../../utils/log';
-import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder';
+import { currentUserActions } from '$app_reducers/current-user/slice';
+import { UserProfilePB } from '@/services/backend/events/flowy-user';
+import { UserService } from '$app/application/user/user.service';
+import { AuthService } from '$app/application/user/auth.service';
+import { useAppSelector, useAppDispatch } from '$app/stores/store';
+import { getCurrentWorkspaceSetting } from '$app/application/folder/workspace.service';
+import { useCallback } from 'react';
 
 export const useAuth = () => {
   const dispatch = useAppDispatch();
   const currentUser = useAppSelector((state) => state.currentUser);
-  const authBackendService = new AuthBackendService();
 
-  async function checkUser() {
-    const result = await UserBackendService.getUserProfile();
+  const checkUser = useCallback(async () => {
+    const userProfile = await UserService.getUserProfile();
 
-    if (result.ok) {
-      const userProfile = result.val;
+    if (!userProfile) return;
+    const workspaceSetting = await getCurrentWorkspaceSetting();
 
-      const workspaceSetting = await _openWorkspace().then((r) => {
-        if (r.ok) {
-          return r.val;
-        } else {
-          return undefined;
-        }
-      });
+    dispatch(
+      currentUserActions.checkUser({
+        id: userProfile.id,
+        token: userProfile.token,
+        email: userProfile.email,
+        displayName: userProfile.name,
+        isAuthenticated: true,
+        workspaceSetting: workspaceSetting,
+      })
+    );
 
-      dispatch(
-        currentUserActions.checkUser({
-          id: userProfile.id,
-          token: userProfile.token,
-          email: userProfile.email,
-          displayName: userProfile.name,
-          isAuthenticated: true,
-          workspaceSetting: workspaceSetting,
-        })
-      );
-    }
+    return userProfile;
+  }, [dispatch]);
 
-    return result;
-  }
+  const register = useCallback(
+    async (email: string, password: string, name: string): Promise<UserProfilePB> => {
+      const userProfile = await AuthService.signUp({ email, password, name });
 
-  async function register(email: string, password: string, name: string): Promise<UserProfilePB> {
-    const authResult = await authBackendService.signUp({ email, password, name });
-
-    if (authResult.ok) {
-      const userProfile = authResult.val;
       // Get the workspace setting after user registered. The workspace setting
       // contains the latest visiting page and the current workspace data.
-      const openWorkspaceResult = await _openWorkspace();
-
-      if (openWorkspaceResult.ok) {
-        const workspaceSetting: WorkspaceSettingPB = openWorkspaceResult.val;
+      const workspaceSetting = await getCurrentWorkspaceSetting();
 
+      if (workspaceSetting) {
         dispatch(
           currentUserActions.updateUser({
             id: userProfile.id,
@@ -64,18 +51,15 @@ export const useAuth = () => {
         );
       }
 
-      return authResult.val;
-    } else {
-      Log.error(authResult.val.msg);
-      throw new Error(authResult.val.msg);
-    }
-  }
+      return userProfile;
+    },
+    [dispatch]
+  );
 
-  async function login(email: string, password: string): Promise<UserProfilePB> {
-    const result = await authBackendService.signIn({ email, password });
-
-    if (result.ok) {
-      const { id, token, name } = result.val;
+  const login = useCallback(
+    async (email: string, password: string): Promise<UserProfilePB> => {
+      const user = await AuthService.signIn({ email, password });
+      const { id, token, name } = user;
 
       dispatch(
         currentUserActions.updateUser({
@@ -86,21 +70,15 @@ export const useAuth = () => {
           isAuthenticated: true,
         })
       );
-      return result.val;
-    } else {
-      Log.error(result.val.msg);
-      throw new Error(result.val.msg);
-    }
-  }
+      return user;
+    },
+    [dispatch]
+  );
 
-  async function logout() {
-    await authBackendService.signOut();
+  const logout = useCallback(async () => {
+    await AuthService.signOut();
     dispatch(currentUserActions.logout());
-  }
-
-  async function _openWorkspace() {
-    return FolderEventGetCurrentWorkspaceSetting();
-  }
+  }, [dispatch]);
 
   return { currentUser, checkUser, register, login, logout };
 };
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/GetStarted/GetStarted.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/auth/get_started/GetStarted.tsx
similarity index 93%
rename from frontend/appflowy_tauri/src/appflowy_app/components/auth/GetStarted/GetStarted.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/auth/get_started/GetStarted.tsx
index f90e3fa188..de387a1c05 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/GetStarted/GetStarted.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/auth/get_started/GetStarted.tsx
@@ -1,8 +1,7 @@
 import { t } from 'i18next';
 import { AppflowyLogo } from '../../_shared/svg/AppflowyLogo';
-
-import { useLogin } from '../Login/Login.hooks';
 import Button from '@mui/material/Button';
+import { useLogin } from '$app/components/auth/get_started/useLogin';
 
 export const GetStarted = () => {
   const { onAutoSignInClick } = useLogin();
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/auth/get_started/useLogin.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/auth/get_started/useLogin.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx
deleted file mode 100644
index a79a2c0a36..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import { SearchInput } from '../_shared/SearchInput';
-import { BoardGroup } from './BoardGroup';
-import { useDatabase } from '../_shared/database-hooks/useDatabase';
-import { ViewLayoutPB } from '@/services/backend';
-import { DragDropContext } from 'react-beautiful-dnd';
-import { useState } from 'react';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import { EditRow } from '$app/components/_shared/EditRow/EditRow';
-import { BoardToolbar } from '$app/components/board/BoardToolbar';
-
-export const Board = ({ viewId, title }: { viewId: string; title: string }) => {
-  const { controller, groups, groupByFieldId, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutPB.Board);
-  const [showBoardRow, setShowBoardRow] = useState(false);
-  const [boardRowInfo, setBoardRowInfo] = useState<RowInfo>();
-
-  const onOpenRow = (rowInfo: RowInfo) => {
-    setBoardRowInfo(rowInfo);
-    setShowBoardRow(true);
-  };
-
-  return (
-    <>
-      <div className='flex w-full items-center justify-between'>
-        <BoardToolbar title={title} />
-
-        <div className='flex shrink-0 items-center gap-4'>
-          <SearchInput />
-        </div>
-      </div>
-      <DragDropContext onDragEnd={onDragEnd}>
-        <div className={'relative w-full flex-1 overflow-auto'}>
-          <div className={'absolute flex h-full flex-shrink-0 items-start justify-start gap-4'}>
-            {controller &&
-              groups &&
-              groups.map((group, index) => (
-                <BoardGroup
-                  key={group.groupId}
-                  viewId={viewId}
-                  controller={controller}
-                  group={group}
-                  groupByFieldId={groupByFieldId}
-                  onNewRowClick={() => onNewRowClick(index)}
-                  onOpenRow={onOpenRow}
-                />
-              ))}
-          </div>
-        </div>
-      </DragDropContext>
-      {controller && showBoardRow && boardRowInfo && (
-        <EditRow
-          onClose={() => setShowBoardRow(false)}
-          viewId={viewId}
-          controller={controller}
-          rowInfo={boardRowInfo}
-        ></EditRow>
-      )}
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx
deleted file mode 100644
index 84e198ee8d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import { Details2Svg } from '../_shared/svg/Details2Svg';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import { useRow } from '../_shared/database-hooks/useRow';
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import { BoardCell } from './BoardCell';
-import { Draggable } from 'react-beautiful-dnd';
-import { MouseEventHandler, useState } from 'react';
-import { PopupWindow } from '$app/components/_shared/PopupWindow';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import { useTranslation } from 'react-i18next';
-import { useAppSelector } from '$app/stores/store';
-
-export const BoardCard = ({
-  index,
-  viewId,
-  controller,
-  rowInfo,
-  groupByFieldId,
-  onOpenRow,
-}: {
-  index: number;
-  viewId: string;
-  controller: DatabaseController;
-  rowInfo: RowInfo;
-  groupByFieldId: string;
-  onOpenRow: (rowId: RowInfo) => void;
-}) => {
-  const databaseStore = useAppSelector((state) => state.database);
-  const { t } = useTranslation();
-
-  const { cells } = useRow(viewId, controller, rowInfo);
-
-  const [showCardPopup, setShowCardPopup] = useState(false);
-  const [cardPopupLeft, setCardPopupLeft] = useState(0);
-  const [cardPopupTop, setCardPopupTop] = useState(0);
-
-  const onDetailClick: MouseEventHandler = (e) => {
-    e.stopPropagation();
-    let target = e.target as HTMLElement;
-
-    while (!(target instanceof HTMLButtonElement)) {
-      if (target.parentElement === null) return;
-      target = target.parentElement;
-    }
-
-    const { right: left, top } = target.getBoundingClientRect();
-
-    setCardPopupLeft(left);
-    setCardPopupTop(top);
-    setShowCardPopup(true);
-  };
-
-  const onDeleteRowClick = async () => {
-    setShowCardPopup(false);
-    await controller.deleteRow(rowInfo.row.id);
-  };
-
-  return (
-    <>
-      <Draggable draggableId={rowInfo.row.id} key={rowInfo.row.id} index={index}>
-        {(provided) => (
-          <div
-            ref={provided.innerRef}
-            {...provided.draggableProps}
-            {...provided.dragHandleProps}
-            onClick={() => onOpenRow(rowInfo)}
-            className={`relative cursor-pointer select-none rounded-lg bg-bg-body px-3 py-2 transition-transform duration-100 hover:bg-content-blue-50 `}
-          >
-            <button
-              onClick={onDetailClick}
-              className={'absolute right-4 top-2.5 h-5 w-5 rounded hover:bg-fill-list-hover'}
-            >
-              <Details2Svg></Details2Svg>
-            </button>
-            <div className={'flex flex-col gap-3'}>
-              {cells
-                .filter(
-                  (cell) => cell.fieldId !== groupByFieldId && databaseStore.fields[cell.cellIdentifier.fieldId]?.visible
-                )
-                .map((cell, cellIndex) => (
-                  <BoardCell
-                    key={cellIndex}
-                    cellIdentifier={cell.cellIdentifier}
-                    cellCache={controller.databaseViewCache.getRowCache().getCellCache()}
-                    fieldController={controller.fieldController}
-                  ></BoardCell>
-                ))}
-            </div>
-          </div>
-        )}
-      </Draggable>
-      {showCardPopup && (
-        <PopupWindow
-          className={'p-2 text-xs'}
-          onOutsideClick={() => setShowCardPopup(false)}
-          left={cardPopupLeft}
-          top={cardPopupTop}
-        >
-          <button
-            key={index}
-            className={'flex w-full cursor-pointer items-center gap-2 rounded-lg px-2 py-2 hover:bg-fill-list-hover'}
-            onClick={() => onDeleteRowClick()}
-          >
-            <i className={'h-5 w-5'}>
-              <TrashSvg></TrashSvg>
-            </i>
-            <span className={'flex-shrink-0'}>{t('grid.row.delete')}</span>
-          </button>
-        </PopupWindow>
-      )}
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx
deleted file mode 100644
index 4075c98c66..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { FieldType } from '@/services/backend';
-import { BoardOptionsCell } from './BoardOptionsCell';
-import { BoardDateCell } from './BoardDateCell';
-import { BoardTextCell } from './BoardTextCell';
-import { BoardUrlCell } from '$app/components/board/BoardUrlCell';
-import { BoardCheckboxCell } from '$app/components/board/BoardCheckboxCell';
-import { BoardCheckListCell } from '$app/components/board/BoardCheckListCell';
-
-export const BoardCell = ({
-  cellIdentifier,
-  cellCache,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-}) => {
-  return (
-    <>
-      {cellIdentifier.fieldType === FieldType.SingleSelect || cellIdentifier.fieldType === FieldType.MultiSelect ? (
-        <BoardOptionsCell
-          cellIdentifier={cellIdentifier}
-          cellCache={cellCache}
-          fieldController={fieldController}
-        ></BoardOptionsCell>
-      ) : cellIdentifier.fieldType === FieldType.Checklist ? (
-        <BoardCheckListCell
-          cellIdentifier={cellIdentifier}
-          cellCache={cellCache}
-          fieldController={fieldController}
-        ></BoardCheckListCell>
-      ) : cellIdentifier.fieldType === FieldType.DateTime ? (
-        <BoardDateCell
-          cellIdentifier={cellIdentifier}
-          cellCache={cellCache}
-          fieldController={fieldController}
-        ></BoardDateCell>
-      ) : cellIdentifier.fieldType === FieldType.URL ? (
-        <BoardUrlCell
-          cellIdentifier={cellIdentifier}
-          cellCache={cellCache}
-          fieldController={fieldController}
-        ></BoardUrlCell>
-      ) : cellIdentifier.fieldType === FieldType.Checkbox ? (
-        <BoardCheckboxCell
-          cellIdentifier={cellIdentifier}
-          cellCache={cellCache}
-          fieldController={fieldController}
-        ></BoardCheckboxCell>
-      ) : (
-        <BoardTextCell
-          cellIdentifier={cellIdentifier}
-          cellCache={cellCache}
-          fieldController={fieldController}
-        ></BoardTextCell>
-      )}
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCheckListCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCheckListCell.tsx
deleted file mode 100644
index e3c1894f9c..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCheckListCell.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { useCell } from '$app/components/_shared/database-hooks/useCell';
-import { useEffect, useState } from 'react';
-import { ISelectOptionType } from '$app_reducers/database/slice';
-import { SelectOptionCellDataPB } from '@/services/backend';
-import { useAppSelector } from '$app/stores/store';
-import { CheckListProgress } from '$app/components/_shared/CheckListProgress';
-
-export const BoardCheckListCell = ({
-  cellIdentifier,
-  cellCache,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-}) => {
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-
-  const databaseStore = useAppSelector((state) => state.database);
-  const [allOptionsCount, setAllOptionsCount] = useState(0);
-  const [selectedOptionsCount, setSelectedOptionsCount] = useState(0);
-
-  useEffect(() => {
-    setAllOptionsCount(
-      (databaseStore.fields[cellIdentifier.fieldId]?.fieldOptions as ISelectOptionType)?.selectOptions?.length ?? 0
-    );
-  }, [databaseStore, cellIdentifier]);
-
-  useEffect(() => {
-    setSelectedOptionsCount((data as SelectOptionCellDataPB)?.select_options?.length ?? 0);
-  }, [data]);
-
-  return <CheckListProgress completed={selectedOptionsCount} max={allOptionsCount} />;
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCheckboxCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCheckboxCell.tsx
deleted file mode 100644
index 3d591c880d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCheckboxCell.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg';
-import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { useCell } from '$app/components/_shared/database-hooks/useCell';
-
-export const BoardCheckboxCell = ({
-  cellIdentifier,
-  cellCache,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-}) => {
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-
-  return (
-    <i className={'h-5 w-5'}>
-      {data === 'Yes' ? <EditorCheckSvg></EditorCheckSvg> : <EditorUncheckSvg></EditorUncheckSvg>}
-    </i>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardDateCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardDateCell.tsx
deleted file mode 100644
index d924c9a54d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardDateCell.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { DateCellDataPB } from '@/services/backend';
-import { useCell } from '../_shared/database-hooks/useCell';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-
-export const BoardDateCell = ({
-  cellIdentifier,
-  cellCache,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-}) => {
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-
-  return <div>{(data as DateCellDataPB | undefined)?.date ?? ''}&nbsp;</div>;
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardFieldsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardFieldsPopup.tsx
deleted file mode 100644
index 6b7d09b34b..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardFieldsPopup.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { useAppSelector } from '$app/stores/store';
-import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
-import { useRef } from 'react';
-import useOutsideClick from '$app/components/_shared/useOutsideClick';
-import { EyeOpenSvg } from '$app/components/_shared/svg/EyeOpenSvg';
-
-export const BoardFieldsPopup = ({ hidePopup }: { hidePopup: () => void }) => {
-  const columns = useAppSelector((state) => state.database.columns);
-  const fields = useAppSelector((state) => state.database.fields);
-  const ref = useRef<HTMLDivElement>(null);
-
-  useOutsideClick(ref, () => hidePopup());
-
-  return (
-    <div ref={ref} className={'absolute left-full top-full z-10 rounded-lg bg-white px-2 py-2 text-xs shadow-md'}>
-      {columns.map((column, index) => (
-        <div
-          className={'flex cursor-pointer items-center justify-between rounded-lg px-2 py-2 hover:bg-fill-list-hover'}
-          key={index}
-        >
-          <div className={'flex items-center gap-2 '}>
-            <i className={'flex h-5 w-5 flex-shrink-0 items-center justify-center'}>
-              <FieldTypeIcon fieldType={fields[column.fieldId].fieldType}></FieldTypeIcon>
-            </i>
-            <span className={'flex-shrink-0'}>{fields[column.fieldId].title}</span>
-          </div>
-          <div className={'ml-12'}>
-            <i className={'block h-5 w-5'}>
-              <EyeOpenSvg></EyeOpenSvg>
-            </i>
-          </div>
-        </div>
-      ))}
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroup.tsx
deleted file mode 100644
index be2b3722d0..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroup.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import { Details2Svg } from '../_shared/svg/Details2Svg';
-import AddSvg from '../_shared/svg/AddSvg';
-import { BoardCard } from './BoardCard';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import { Droppable } from 'react-beautiful-dnd';
-import { DatabaseGroupController } from '$app/stores/effects/database/group/group_controller';
-import { useTranslation } from 'react-i18next';
-import { useEffect, useState } from 'react';
-
-export const BoardGroup = ({
-  viewId,
-  controller,
-  groupByFieldId,
-  onNewRowClick,
-  onOpenRow,
-  group,
-}: {
-  viewId: string;
-  controller: DatabaseController;
-  groupByFieldId: string;
-  onNewRowClick: () => void;
-  onOpenRow: (rowId: RowInfo) => void;
-  group: DatabaseGroupController;
-}) => {
-  const { t } = useTranslation();
-
-  const [rows, setRows] = useState<RowInfo[]>([]);
-
-  useEffect(() => {
-    const reloadRows = () => {
-      setRows(group.rows.map((rowPB) => new RowInfo(viewId, controller.fieldController.fieldInfos, rowPB)));
-    };
-
-    reloadRows();
-    group.subscribe({
-      onRemoveRow: reloadRows,
-      onInsertRow: reloadRows,
-      onUpdateRow: reloadRows,
-      onCreateRow: reloadRows,
-    });
-    return () => {
-      group.unsubscribe();
-    };
-  }, [controller, group, viewId]);
-
-  return (
-    <div className={'flex h-full w-[250px] flex-col rounded-lg bg-bg-base'}>
-      <div className={'flex items-center justify-between p-4'}>
-        <div className={'flex items-center gap-2'}>
-          <span>{group.name}</span>
-          <span className={'text-text-caption'}>({group.rows.length})</span>
-        </div>
-        <div className={'flex items-center gap-2'}>
-          <button className={'h-5 w-5 rounded hover:bg-fill-list-hover'}>
-            <Details2Svg></Details2Svg>
-          </button>
-          <button className={'h-5 w-5 rounded hover:bg-fill-list-hover'}>
-            <AddSvg></AddSvg>
-          </button>
-        </div>
-      </div>
-      <Droppable droppableId={group.groupId}>
-        {(provided) => (
-          <div
-            className={'flex flex-1 flex-col gap-1 overflow-auto px-2'}
-            {...provided.droppableProps}
-            ref={provided.innerRef}
-          >
-            {rows.map((row, index) => {
-              return (
-                <BoardCard
-                  viewId={viewId}
-                  controller={controller}
-                  index={index}
-                  key={row.row.id}
-                  rowInfo={row}
-                  groupByFieldId={groupByFieldId}
-                  onOpenRow={onOpenRow}
-                ></BoardCard>
-              );
-            })}
-          </div>
-        )}
-      </Droppable>
-      <div className={'p-2'}>
-        <button
-          onClick={onNewRowClick}
-          className={'flex w-full items-center gap-2 rounded-lg px-2 py-2 hover:bg-fill-list-hover'}
-        >
-          <span className={'h-5 w-5'}>
-            <AddSvg></AddSvg>
-          </span>
-          <span>{t('board.column.createNewCard')}</span>
-        </button>
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroupFieldsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroupFieldsPopup.tsx
deleted file mode 100644
index b6ac8b2c3d..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardGroupFieldsPopup.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { useAppSelector } from '$app/stores/store';
-import { FieldTypeIcon } from '$app/components/_shared/EditRow/FieldTypeIcon';
-import { useRef } from 'react';
-import useOutsideClick from '$app/components/_shared/useOutsideClick';
-import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg';
-
-export const BoardGroupFieldsPopup = ({ hidePopup }: { hidePopup: () => void }) => {
-  const columns = useAppSelector((state) => state.database.columns);
-  const fields = useAppSelector((state) => state.database.fields);
-  const ref = useRef<HTMLDivElement>(null);
-
-  useOutsideClick(ref, () => hidePopup());
-
-  return (
-    <div ref={ref} className={'absolute left-full top-full z-10 rounded-lg bg-white px-2 py-2 text-xs shadow-md'}>
-      {columns.map((column, index) => (
-        <div
-          className={'flex cursor-pointer items-center justify-between rounded-lg px-2 py-2 hover:bg-fill-list-hover'}
-          key={index}
-        >
-          <div className={'flex items-center gap-2 '}>
-            <i className={'flex h-5 w-5 flex-shrink-0 items-center justify-center'}>
-              <FieldTypeIcon fieldType={fields[column.fieldId].fieldType}></FieldTypeIcon>
-            </i>
-            <span className={'flex-shrink-0'}>{fields[column.fieldId].title}</span>
-          </div>
-          <div className={'ml-12'}>
-            <i className={'block h-3 w-3'}>
-              <CheckmarkSvg></CheckmarkSvg>
-            </i>
-          </div>
-        </div>
-      ))}
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardOptionsCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardOptionsCell.tsx
deleted file mode 100644
index 7841e08423..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardOptionsCell.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { SelectOptionCellDataPB } from '@/services/backend';
-import { useCell } from '../_shared/database-hooks/useCell';
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { getBgColor } from '$app/components/_shared/getColor';
-
-export const BoardOptionsCell = ({
-  cellIdentifier,
-  cellCache,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-}) => {
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-
-  return (
-    <div className={'flex flex-wrap items-center gap-2 py-2 text-xs text-text-title'}>
-      {(data as SelectOptionCellDataPB)?.select_options?.map((option, index) => (
-        <div className={`${getBgColor(option.color)} rounded px-2 py-0.5`} key={index}>
-          {option?.name ?? ''}
-        </div>
-      ))}
-      &nbsp;
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardSettingsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardSettingsPopup.tsx
deleted file mode 100644
index e1eec1e876..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardSettingsPopup.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { useEffect, useState } from 'react';
-import { PropertiesSvg } from '$app/components/_shared/svg/PropertiesSvg';
-import { IPopupItem, PopupSelect } from '$app/components/_shared/PopupSelect';
-import { useTranslation } from 'react-i18next';
-import { GroupByFieldSvg } from '$app/components/_shared/svg/GroupByFieldSvg';
-
-export const BoardSettingsPopup = ({
-  hidePopup,
-  onFieldsClick,
-  onGroupClick,
-}: {
-  hidePopup: () => void;
-  onFieldsClick: () => void;
-  onGroupClick: () => void;
-}) => {
-  const [settingsItems, setSettingsItems] = useState<IPopupItem[]>([]);
-  const { t } = useTranslation();
-
-  useEffect(() => {
-    setSettingsItems([
-      {
-        icon: (
-          <i className={'h-5 w-5'}>
-            <PropertiesSvg></PropertiesSvg>
-          </i>
-        ),
-        title: t('grid.settings.properties'),
-        onClick: onFieldsClick,
-      },
-      {
-        icon: (
-          <i className={'h-5 w-5'}>
-            <GroupByFieldSvg></GroupByFieldSvg>
-          </i>
-        ),
-        title: t('grid.settings.group'),
-        onClick: onGroupClick,
-      },
-    ]);
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [t]);
-
-  return (
-    <PopupSelect
-      onOutsideClick={() => hidePopup()}
-      items={settingsItems}
-      className={'absolute left-full top-full z-10 text-xs'}
-    ></PopupSelect>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardTextCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardTextCell.tsx
deleted file mode 100644
index 613c797ca8..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardTextCell.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { useCell } from '../_shared/database-hooks/useCell';
-
-export const BoardTextCell = ({
-  cellIdentifier,
-  cellCache,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-}) => {
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-
-  return (
-    <div>
-      {((data as string | undefined) ?? '').split('\n').map((line, index) => (
-        <div key={index}>{line}</div>
-      ))}
-      &nbsp;
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.hooks.ts
deleted file mode 100644
index b9fd587734..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.hooks.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { useState } from 'react';
-
-export const useBoardToolbar = () => {
-  const [showSettings, setShowSettings] = useState(false);
-  const [showAllFields, setShowAllFields] = useState(false);
-  const [showGroupFields, setShowGroupFields] = useState(false);
-
-  const onSettingsClick = () => {
-    setShowSettings(!showSettings);
-  };
-
-  const onFieldsClick = () => {
-    setShowSettings(false);
-    setShowAllFields(true);
-  };
-
-  const onGroupClick = () => {
-    setShowSettings(false);
-    setShowGroupFields(true);
-  };
-
-  const hidePopup = () => {
-    setShowSettings(false);
-    setShowAllFields(false);
-    setShowGroupFields(false);
-  };
-
-  return {
-    showSettings,
-    onSettingsClick,
-    onFieldsClick,
-    onGroupClick,
-    hidePopup,
-    showAllFields,
-    showGroupFields,
-  };
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.tsx
deleted file mode 100644
index 7459f39857..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardToolbar.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { SettingsSvg } from '$app/components/_shared/svg/SettingsSvg';
-import { useBoardToolbar } from '$app/components/board/BoardToolbar.hooks';
-import { BoardSettingsPopup } from '$app/components/board/BoardSettingsPopup';
-import { BoardFieldsPopup } from '$app/components/board/BoardFieldsPopup';
-import { BoardGroupFieldsPopup } from '$app/components/board/BoardGroupFieldsPopup';
-
-export const BoardToolbar = ({ title }: { title: string }) => {
-  const { showSettings, showAllFields, showGroupFields, onSettingsClick, onFieldsClick, onGroupClick, hidePopup } =
-    useBoardToolbar();
-
-  return (
-    <div className={'relative flex items-center gap-2'}>
-      <div className={'text-xl font-semibold'}>{title}</div>
-      <button onClick={() => onSettingsClick()} className={'h-5 w-5'}>
-        <SettingsSvg></SettingsSvg>
-      </button>
-      {showSettings && (
-        <BoardSettingsPopup
-          hidePopup={hidePopup}
-          onFieldsClick={onFieldsClick}
-          onGroupClick={onGroupClick}
-        ></BoardSettingsPopup>
-      )}
-      {showAllFields && <BoardFieldsPopup hidePopup={hidePopup}></BoardFieldsPopup>}
-      {showGroupFields && <BoardGroupFieldsPopup hidePopup={hidePopup}></BoardGroupFieldsPopup>}
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardUrlCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardUrlCell.tsx
deleted file mode 100644
index 8c5188dca8..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardUrlCell.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc';
-import { CellCache } from '$app/stores/effects/database/cell/cell_cache';
-import { FieldController } from '$app/stores/effects/database/field/field_controller';
-import { useCell } from '$app/components/_shared/database-hooks/useCell';
-import { URLCellDataPB } from '@/services/backend';
-
-export const BoardUrlCell = ({
-  cellIdentifier,
-  cellCache,
-  fieldController,
-}: {
-  cellIdentifier: CellIdentifier;
-  cellCache: CellCache;
-  fieldController: FieldController;
-}) => {
-  const { data } = useCell(cellIdentifier, cellCache, fieldController);
-
-  return (
-    <>
-      <a className={'text-fill-hover hover:underline'} href={(data as URLCellDataPB)?.url ?? ''} target={'_blank'}>
-        {(data as URLCellDataPB)?.content ?? ''}&nbsp;
-      </a>
-    </>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.hooks.ts
index 36ab3a385a..1e83853530 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.hooks.ts
@@ -13,7 +13,7 @@ import {
   rowListeners,
   sortListeners,
   filterListeners,
-} from './application';
+} from '$app/application/database';
 
 export function useSelectDatabaseView({ viewId }: { viewId?: string }) {
   const key = 'v';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.tsx
index 416277c76f..4e59b16b2f 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/Database.tsx
@@ -1,18 +1,18 @@
 import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
 import { useViewId } from '$app/hooks/ViewId.hooks';
-import { databaseViewService } from './application';
+import { databaseViewService } from '$app/application/database';
 import { DatabaseTabBar } from './components';
 import { DatabaseLoader } from './DatabaseLoader';
 import { DatabaseView } from './DatabaseView';
 import { DatabaseCollection } from './components/database_settings';
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
 import SwipeableViews from 'react-swipeable-views';
 import { TabPanel } from '$app/components/database/components/tab_bar/ViewTabs';
 import DatabaseSettings from '$app/components/database/components/database_settings/DatabaseSettings';
 import { Portal } from '@mui/material';
 import { useTranslation } from 'react-i18next';
-import { ErrorCode } from '@/services/backend';
+import { ErrorCode, FolderNotification } from '@/services/backend';
 import ExpandRecordModal from '$app/components/database/components/edit_record/ExpandRecordModal';
+import { subscribeNotifications } from '$app/application/notification';
 
 interface Props {
   selectedViewId?: string;
@@ -44,15 +44,18 @@ export const Database = ({ selectedViewId, setSelectedViewId }: Props) => {
 
     onPageChanged();
 
-    const pageController = new PageController(viewId);
+    const unsubscribePromise = subscribeNotifications(
+      {
+        [FolderNotification.DidUpdateView]: () => {
+          onPageChanged();
+        },
+      },
+      {
+        id: viewId,
+      }
+    );
 
-    void pageController.subscribe({
-      onPageChanged,
-    });
-
-    return () => {
-      void pageController.unsubscribe();
-    };
+    return () => void unsubscribePromise.then((unsubscribe) => unsubscribe());
   }, [viewId]);
 
   const value = useMemo(() => {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.hooks.ts
index 74be8bea8c..76bba7b152 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.hooks.ts
@@ -1,7 +1,7 @@
 import { useCallback, useEffect, useState } from 'react';
 import { DatabaseNotification } from '@/services/backend';
 import { useNotification, useViewId } from '$app/hooks';
-import { cellService, Cell, Field } from '../../application';
+import { cellService, Cell, Field } from '$app/application/database';
 import { useDispatchCell, useSelectorCell } from '$app/components/database';
 
 export const useCell = (rowId: string, field: Field) => {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.tsx
index 67175131e1..a092a1d75a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/Cell.tsx
@@ -1,7 +1,7 @@
 import React, { FC, HTMLAttributes } from 'react';
 import { FieldType } from '@/services/backend';
 
-import { Cell as CellType, Field } from '../../application';
+import { Cell as CellType, Field } from '$app/application/database';
 import { useCell } from './Cell.hooks';
 import { TextCell } from './TextCell';
 import { SelectCell } from './SelectCell';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/CheckboxCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/CheckboxCell.tsx
index cff353e31a..f74f038e09 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/CheckboxCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/CheckboxCell.tsx
@@ -2,7 +2,7 @@ import React, { FC, useCallback } from 'react';
 import { ReactComponent as CheckboxCheckSvg } from '$app/assets/database/checkbox-check.svg';
 import { ReactComponent as CheckboxUncheckSvg } from '$app/assets/database/checkbox-uncheck.svg';
 import { useViewId } from '$app/hooks';
-import { cellService, CheckboxCell as CheckboxCellType, Field } from '../../application';
+import { cellService, CheckboxCell as CheckboxCellType, Field } from '$app/application/database';
 
 export const CheckboxCell: FC<{
   field: Field;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/ChecklistCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/ChecklistCell.tsx
index a72b16b376..ab591855ee 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/ChecklistCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/ChecklistCell.tsx
@@ -1,5 +1,5 @@
 import React, { useState, Suspense, useMemo } from 'react';
-import { ChecklistCell as ChecklistCellType, ChecklistField } from '$app/components/database/application';
+import { ChecklistCell as ChecklistCellType, ChecklistField } from '$app/application/database';
 import Typography from '@mui/material/Typography';
 import ChecklistCellActions from '$app/components/database/components/field_types/checklist/ChecklistCellActions';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/DateTimeCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/DateTimeCell.tsx
index 31f35afd5b..bf74fd44c5 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/DateTimeCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/DateTimeCell.tsx
@@ -1,5 +1,5 @@
 import React, { Suspense, useRef, useState, useMemo } from 'react';
-import { DateTimeCell as DateTimeCellType, DateTimeField } from '$app/components/database/application';
+import { DateTimeCell as DateTimeCellType, DateTimeField } from '$app/application/database';
 import DateTimeCellActions from '$app/components/database/components/field_types/date/DateTimeCellActions';
 
 interface Props {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/NumberCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/NumberCell.tsx
index af13b65d07..727e78de3f 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/NumberCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/NumberCell.tsx
@@ -1,5 +1,5 @@
 import React, { Suspense, useCallback, useMemo, useRef } from 'react';
-import { Field, NumberCell as NumberCellType } from '$app/components/database/application';
+import { Field, NumberCell as NumberCellType } from '$app/application/database';
 import { CellText } from '$app/components/database/_shared';
 import EditNumberCellInput from '$app/components/database/components/field_types/number/EditNumberCellInput';
 import { useInputCell } from '$app/components/database/components/cell/Cell.hooks';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/SelectCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/SelectCell.tsx
index 62bd30f7ab..5abe28cbfe 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/SelectCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/SelectCell.tsx
@@ -1,6 +1,6 @@
 import { FC, useCallback, useMemo, useState, Suspense, lazy } from 'react';
 import { MenuProps, Menu } from '@mui/material';
-import { SelectField, SelectCell as SelectCellType, SelectTypeOption } from '../../application';
+import { SelectField, SelectCell as SelectCellType, SelectTypeOption } from '$app/application/database';
 import { Tag } from '../field_types/select/Tag';
 import { useTypeOption } from '$app/components/database';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TextCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TextCell.tsx
index 7ad0bd0653..38927d744b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TextCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TextCell.tsx
@@ -1,5 +1,5 @@
 import { FC, FormEventHandler, Suspense, lazy, useCallback, useRef, useMemo } from 'react';
-import { TextCell as TextCellType } from '../../application';
+import { TextCell as TextCellType } from '$app/application/database';
 import { CellText } from '../../_shared';
 import { useInputCell } from '$app/components/database/components/cell/Cell.hooks';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TimestampCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TimestampCell.tsx
index f7aeec9f2c..5889a13915 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TimestampCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/TimestampCell.tsx
@@ -1,5 +1,5 @@
 import React from 'react';
-import { CreatedTimeField, LastEditedTimeField, TimeStampCell } from '$app/components/database/application';
+import { CreatedTimeField, LastEditedTimeField, TimeStampCell } from '$app/application/database';
 
 interface Props {
   field: LastEditedTimeField | CreatedTimeField;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/URLCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/URLCell.tsx
index d1c2c90db0..e07e81c1af 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/URLCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/cell/URLCell.tsx
@@ -1,6 +1,6 @@
 import React, { FormEventHandler, lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
 import { useInputCell } from '$app/components/database/components/cell/Cell.hooks';
-import { Field, UrlCell as URLCellType } from '$app/components/database/application';
+import { Field, UrlCell as URLCellType } from '$app/application/database';
 import { CellText } from '$app/components/database/_shared';
 
 const EditTextCellInput = lazy(() => import('$app/components/database/components/field_types/text/EditTextCellInput'));
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/Properties.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/Properties.tsx
index c150caa36c..a89b533bca 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/Properties.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/Properties.tsx
@@ -1,6 +1,6 @@
 import React, { useEffect, useState } from 'react';
 import { useDatabase } from '$app/components/database';
-import { Field as FieldType, fieldService } from '$app/components/database/application';
+import { Field as FieldType, fieldService } from '$app/application/database';
 import { Property } from '$app/components/database/components/property';
 import { FieldVisibility } from '@/services/backend';
 import { ReactComponent as EyeOpen } from '$app/assets/eye_open.svg';
@@ -41,7 +41,7 @@ function Properties({ onItemClick }: PropertiesProps) {
 
     setState(newProperties);
 
-    await fieldService.moveField(viewId, draggableId, newId ?? "");
+    await fieldService.moveField(viewId, draggableId, newId ?? '');
   };
 
   return (
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/SettingsMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/SettingsMenu.tsx
index 4dd2f2b3c3..2b740e6e0b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/SettingsMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/database_settings/SettingsMenu.tsx
@@ -2,9 +2,9 @@ import React, { useState } from 'react';
 import { Menu, MenuItem, MenuProps, Popover } from '@mui/material';
 import { useTranslation } from 'react-i18next';
 import Properties from '$app/components/database/components/database_settings/Properties';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import { FieldVisibility } from '@/services/backend';
-import { updateFieldSetting } from '$app/components/database/application/field/field_service';
+import { updateFieldSetting } from '$app/application/database/field/field_service';
 import { useViewId } from '$app/hooks';
 
 type SettingsMenuProps = MenuProps;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/EditRecord.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/EditRecord.tsx
index 3d60ad71b2..b14a3a9783 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/EditRecord.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/EditRecord.tsx
@@ -2,10 +2,10 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
 import RecordDocument from '$app/components/database/components/edit_record/RecordDocument';
 import RecordHeader from '$app/components/database/components/edit_record/RecordHeader';
 import { Page } from '$app_reducers/pages/slice';
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
 import { ErrorCode, ViewLayoutPB } from '@/services/backend';
 import { Log } from '$app/utils/log';
 import { useDatabase } from '$app/components/database';
+import { createOrphanPage, getPage } from '$app/application/folder/page.service';
 
 interface Props {
   rowId: string;
@@ -21,10 +21,9 @@ function EditRecord({ rowId }: Props) {
 
   const loadPage = useCallback(async () => {
     if (!id) return;
-    const controller = new PageController(id);
 
     try {
-      const page = await controller.getPage();
+      const page = await getPage(id);
 
       setPage(page);
     } catch (e) {
@@ -33,7 +32,8 @@ function EditRecord({ rowId }: Props) {
       // @ts-ignore
       if (e.code === ErrorCode.RecordNotFound) {
         try {
-          const page = await controller.createOrphanPage({
+          const page = await createOrphanPage({
+            view_id: id,
             name: '',
             layout: ViewLayoutPB.Document,
           });
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/ExpandRecordModal.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/ExpandRecordModal.tsx
index 362e616cf7..34d05d0988 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/ExpandRecordModal.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/ExpandRecordModal.tsx
@@ -34,7 +34,7 @@ function ExpandRecordModal({ open, onClose, rowId }: Props) {
         >
           <DetailsIcon />
         </IconButton>
-        <DialogContent className={'p-0'}>
+        <DialogContent className={'relative p-0'}>
           <EditRecord rowId={rowId} />
         </DialogContent>
       </Dialog>
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordActions.tsx
index 5d9f769aec..81fc0ed146 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordActions.tsx
@@ -3,7 +3,7 @@ import { Icon, Menu, MenuProps } from '@mui/material';
 import { ReactComponent as DelSvg } from '$app/assets/delete.svg';
 import { ReactComponent as CopySvg } from '$app/assets/copy.svg';
 import { useTranslation } from 'react-i18next';
-import { rowService } from '$app/components/database/application';
+import { rowService } from '$app/application/database';
 import { useViewId } from '$app/hooks';
 import MenuItem from '@mui/material/MenuItem';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordHeader.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordHeader.tsx
index 6210ed5f70..f3f1820a49 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordHeader.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordHeader.tsx
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
 import RecordTitle from '$app/components/database/components/edit_record/RecordTitle';
 import RecordProperties from '$app/components/database/components/edit_record/record_properties/RecordProperties';
 import { Divider } from '@mui/material';
-import { RowMeta } from '$app/components/database/application';
+import { RowMeta } from '$app/application/database';
 import { Page } from '$app_reducers/pages/slice';
 
 interface Props {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordTitle.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordTitle.tsx
index 8908b0de5e..c2f195aee2 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordTitle.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/RecordTitle.tsx
@@ -1,10 +1,10 @@
 import React, { useCallback, useMemo } from 'react';
 import { Page, PageIcon } from '$app_reducers/pages/slice';
-import ViewTitle from '$app/components/_shared/ViewTitle';
+import ViewTitle from '$app/components/_shared/view_title/ViewTitle';
 import { ViewIconTypePB } from '@/services/backend';
 import { useViewId } from '$app/hooks';
-import { updateRowMeta } from '$app/components/database/application/row/row_service';
-import { cellService, Field, RowMeta, TextCell } from '$app/components/database/application';
+import { updateRowMeta } from '$app/application/database/row/row_service';
+import { cellService, Field, RowMeta, TextCell } from '$app/application/database';
 import { useDatabase } from '$app/components/database';
 import { useCell } from '$app/components/database/components/cell/Cell.hooks';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/Property.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/Property.tsx
index 023194e811..279ee13f68 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/Property.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/Property.tsx
@@ -1,7 +1,7 @@
 import React, { HTMLAttributes } from 'react';
 import PropertyName from '$app/components/database/components/edit_record/record_properties/PropertyName';
 import PropertyValue from '$app/components/database/components/edit_record/record_properties/PropertyValue';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import { IconButton, Tooltip } from '@mui/material';
 import { ReactComponent as DragSvg } from '$app/assets/drag.svg';
 import { useTranslation } from 'react-i18next';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyList.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyList.tsx
index 0443545d49..138c7543fd 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyList.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyList.tsx
@@ -1,5 +1,5 @@
 import React, { HTMLAttributes, useState } from 'react';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import Property from '$app/components/database/components/edit_record/record_properties/Property';
 import { Draggable } from 'react-beautiful-dnd';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyName.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyName.tsx
index b2c2bb16de..e7de3f1fb0 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyName.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyName.tsx
@@ -1,6 +1,6 @@
 import React, { useRef } from 'react';
 import { Property } from '$app/components/database/components/property';
-import { Field as FieldType } from '$app/components/database/application';
+import { Field as FieldType } from '$app/application/database';
 
 interface Props {
   field: FieldType;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyValue.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyValue.tsx
index 90f8147f9f..4bb33e7f05 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyValue.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/PropertyValue.tsx
@@ -1,6 +1,6 @@
 import React, { useEffect, useRef, useState } from 'react';
 import { Cell } from '$app/components/database/components';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import { useTranslation } from 'react-i18next';
 
 function PropertyValue(props: { rowId: string; field: Field }) {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/RecordProperties.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/RecordProperties.tsx
index 3f9de43e44..16fc122615 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/RecordProperties.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/edit_record/record_properties/RecordProperties.tsx
@@ -1,5 +1,5 @@
 import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { Field, fieldService, RowMeta } from '$app/components/database/application';
+import { Field, fieldService, RowMeta } from '$app/application/database';
 import { useDatabase } from '$app/components/database';
 import { FieldVisibility } from '@/services/backend';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/AddNewOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/AddNewOption.tsx
index ff3c5db172..fc3f72e224 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/AddNewOption.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/AddNewOption.tsx
@@ -1,5 +1,5 @@
 import React, { useState } from 'react';
-import { updateChecklistCell } from '$app/components/database/application/cell/cell_service';
+import { updateChecklistCell } from '$app/application/database/cell/cell_service';
 import { useViewId } from '$app/hooks';
 import { ReactComponent as AddIcon } from '$app/assets/add.svg';
 import { IconButton } from '@mui/material';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistCellActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistCellActions.tsx
index ba63902dc6..4905765481 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistCellActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistCellActions.tsx
@@ -2,7 +2,7 @@ import React from 'react';
 import Popover, { PopoverProps } from '@mui/material/Popover';
 import { LinearProgressWithLabel } from '$app/components/database/components/field_types/checklist/LinearProgressWithLabel';
 import { Divider } from '@mui/material';
-import { ChecklistCell as ChecklistCellType } from '$app/components/database/application';
+import { ChecklistCell as ChecklistCellType } from '$app/application/database';
 import ChecklistItem from '$app/components/database/components/field_types/checklist/ChecklistItem';
 import AddNewOption from '$app/components/database/components/field_types/checklist/AddNewOption';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistItem.tsx
index 076dc854ea..9a33c8b9a3 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistItem.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/checklist/ChecklistItem.tsx
@@ -1,7 +1,7 @@
 import React, { useState } from 'react';
-import { SelectOption } from '$app/components/database/application';
+import { SelectOption } from '$app/application/database';
 import { Checkbox, IconButton } from '@mui/material';
-import { updateChecklistCell } from '$app/components/database/application/cell/cell_service';
+import { updateChecklistCell } from '$app/application/database/cell/cell_service';
 import { useViewId } from '$app/hooks';
 import { ReactComponent as DeleteIcon } from '$app/assets/delete.svg';
 import { ReactComponent as CheckboxCheckSvg } from '$app/assets/database/checkbox-check.svg';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeCellActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeCellActions.tsx
index 631ad8bb8c..f0c6a84250 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeCellActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeCellActions.tsx
@@ -1,9 +1,9 @@
 import React, { useCallback, useMemo } from 'react';
 import Popover, { PopoverProps } from '@mui/material/Popover';
-import { DateTimeCell, DateTimeField, DateTimeTypeOption } from '$app/components/database/application';
+import { DateTimeCell, DateTimeField, DateTimeTypeOption } from '$app/application/database';
 import { useViewId } from '$app/hooks';
 import { useTranslation } from 'react-i18next';
-import { updateDateCell } from '$app/components/database/application/cell/cell_service';
+import { updateDateCell } from '$app/application/database/cell/cell_service';
 import { Divider, MenuItem, MenuList } from '@mui/material';
 import dayjs from 'dayjs';
 import RangeSwitch from '$app/components/database/components/field_types/date/RangeSwitch';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFieldActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFieldActions.tsx
index 8225413a71..6c4b41a494 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFieldActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFieldActions.tsx
@@ -1,5 +1,5 @@
 import React from 'react';
-import { UndeterminedDateField } from '$app/components/database/application';
+import { UndeterminedDateField } from '$app/application/database';
 import DateTimeFormat from '$app/components/database/components/field_types/date/DateTimeFormat';
 import { Divider } from '@mui/material';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormat.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormat.tsx
index 7033077a00..0107997c24 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormat.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormat.tsx
@@ -1,7 +1,7 @@
 import React, { useCallback } from 'react';
 import DateFormat from '$app/components/database/components/field_types/date/DateFormat';
 import TimeFormat from '$app/components/database/components/field_types/date/TimeFormat';
-import { TimeStampTypeOption, UndeterminedDateField, updateTypeOption } from '$app/components/database/application';
+import { TimeStampTypeOption, UndeterminedDateField, updateTypeOption } from '$app/application/database';
 import { DateFormatPB, FieldType, TimeFormatPB } from '@/services/backend';
 import { useViewId } from '$app/hooks';
 import Typography from '@mui/material/Typography';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormatSelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormatSelect.tsx
index c65da97817..81ea28ed47 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormatSelect.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/date/DateTimeFormatSelect.tsx
@@ -1,7 +1,7 @@
 import React, { useState, useRef } from 'react';
 import { Menu, MenuItem } from '@mui/material';
 import { useTranslation } from 'react-i18next';
-import { DateTimeField } from '$app/components/database/application';
+import { DateTimeField } from '$app/application/database';
 import DateTimeFormat from '$app/components/database/components/field_types/date/DateTimeFormat';
 import { ReactComponent as MoreSvg } from '$app/assets/more.svg';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/number/NumberFieldActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/number/NumberFieldActions.tsx
index 7bc654918b..c91717093b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/number/NumberFieldActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/number/NumberFieldActions.tsx
@@ -1,5 +1,5 @@
 import React, { useCallback } from 'react';
-import { NumberField, NumberTypeOption, updateTypeOption } from '$app/components/database/application';
+import { NumberField, NumberTypeOption, updateTypeOption } from '$app/application/database';
 import { Divider } from '@mui/material';
 import { useTranslation } from 'react-i18next';
 import NumberFormatSelect from '$app/components/database/components/field_types/number/NumberFormatSelect';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/SelectOptionMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/SelectOptionMenu.tsx
index cdd14ca25e..7b31d203b4 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/SelectOptionMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/SelectOptionMenu.tsx
@@ -4,13 +4,13 @@ import { Divider, ListSubheader, MenuItem, MenuList, MenuProps, OutlinedInput }
 import { SelectOptionColorPB } from '@/services/backend';
 import { ReactComponent as DeleteSvg } from '$app/assets/delete.svg';
 import { ReactComponent as SelectCheckSvg } from '$app/assets/select-check.svg';
-import { SelectOption } from '../../../application';
+import { SelectOption } from '$app/application/database';
 import { SelectOptionColorMap, SelectOptionColorTextMap } from './constants';
 import Button from '@mui/material/Button';
 import {
   deleteSelectOption,
   insertOrUpdateSelectOption,
-} from '$app/components/database/application/field/select_option/select_option_service';
+} from '$app/application/database/field/select_option/select_option_service';
 import { useViewId } from '$app/hooks';
 import Popover from '@mui/material/Popover';
 
@@ -111,7 +111,7 @@ export const SelectOptionMenu: FC<SelectOptionMenuProps> = ({ fieldId, option, M
 
       <Divider />
       <MenuItem disabled>{t('grid.selectOption.colorPanelTitle')}</MenuItem>
-      <MenuList className={'max-h-[300px] overflow-y-auto overflow-x-hidden'}>
+      <MenuList className={'max-h-[300px] overflow-y-auto overflow-x-hidden px-2'}>
         {Colors.map((color) => (
           <MenuItem
             onClick={() => {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectCellActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectCellActions.tsx
index 357dceab12..fd658fbc5d 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectCellActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectCellActions.tsx
@@ -3,17 +3,12 @@ import { MenuItem } from '@mui/material';
 import { t } from 'i18next';
 import { CreateOption } from '$app/components/database/components/field_types/select/select_cell_actions/CreateOption';
 import { SelectOptionItem } from '$app/components/database/components/field_types/select/select_cell_actions/SelectOptionItem';
-import {
-  cellService,
-  SelectCell as SelectCellType,
-  SelectField,
-  SelectTypeOption,
-} from '$app/components/database/application';
+import { cellService, SelectCell as SelectCellType, SelectField, SelectTypeOption } from '$app/application/database';
 import { useViewId } from '$app/hooks';
 import {
   createSelectOption,
   insertOrUpdateSelectOption,
-} from '$app/components/database/application/field/select_option/select_option_service';
+} from '$app/application/database/field/select_option/select_option_service';
 import { FieldType } from '@/services/backend';
 import { useTypeOption } from '$app/components/database';
 import SearchInput from './SearchInput';
@@ -130,7 +125,7 @@ function SelectCellActions({
       {shouldCreateOption ? (
         <CreateOption label={newOptionName} onClick={handleNewTagClick} />
       ) : (
-        <div className={'max-h-[300px] overflow-y-auto overflow-x-hidden'}>
+        <div className={'max-h-[300px] overflow-y-auto overflow-x-hidden px-2'}>
           {filteredOptions.map((option) => (
             <MenuItem className={'px-2'} key={option.id} value={option.id}>
               <SelectOptionItem
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectOptionItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectOptionItem.tsx
index 3313d5e676..508d1e4aaa 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectOptionItem.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_cell_actions/SelectOptionItem.tsx
@@ -1,7 +1,7 @@
 import { FC, MouseEventHandler, useCallback, useRef, useState } from 'react';
 import { IconButton } from '@mui/material';
 import { ReactComponent as DetailsSvg } from '$app/assets/details.svg';
-import { SelectOption } from '../../../../application';
+import { SelectOption } from '$app/application/database';
 import { SelectOptionMenu } from '../SelectOptionMenu';
 import { Tag } from '../Tag';
 import { ReactComponent as SelectCheckSvg } from '$app/assets/select-check.svg';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/AddAnOption.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/AddAnOption.tsx
index 25a1e3eee0..b9caebd0c8 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/AddAnOption.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/AddAnOption.tsx
@@ -6,7 +6,7 @@ import { OutlinedInput } from '@mui/material';
 import {
   createSelectOption,
   insertOrUpdateSelectOption,
-} from '$app/components/database/application/field/select_option/select_option_service';
+} from '$app/application/database/field/select_option/select_option_service';
 import { useViewId } from '$app/hooks';
 
 function AddAnOption({ fieldId }: { fieldId: string }) {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Option.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Option.tsx
index 71693276c6..f0190b5c92 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Option.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Option.tsx
@@ -1,6 +1,6 @@
 import React, { useRef, useState } from 'react';
 import { ReactComponent as MoreIcon } from '$app/assets/more.svg';
-import { SelectOption } from '$app/components/database/application';
+import { SelectOption } from '$app/application/database';
 // import { ReactComponent as DragIcon } from '$app/assets/drag.svg';
 
 import { SelectOptionMenu } from '$app/components/database/components/field_types/select/SelectOptionMenu';
@@ -14,6 +14,7 @@ function Option({ option, fieldId }: { option: SelectOption; fieldId: string })
   return (
     <>
       <Button
+        size={'small'}
         onClick={() => setExpanded(!expanded)}
         color={'inherit'}
         // startIcon={<DragIcon />}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Options.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Options.tsx
index fea4b31475..f3701517c0 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Options.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/Options.tsx
@@ -1,5 +1,5 @@
 import React from 'react';
-import { SelectOption } from '$app/components/database/application';
+import { SelectOption } from '$app/application/database';
 import Option from './Option';
 
 interface Props {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/SelectFieldActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/SelectFieldActions.tsx
index 80e41f11fa..43e46848b3 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/SelectFieldActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/field_types/select/select_field_actions/SelectFieldActions.tsx
@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
 import { useTranslation } from 'react-i18next';
 import AddAnOption from '$app/components/database/components/field_types/select/select_field_actions/AddAnOption';
 import Options from '$app/components/database/components/field_types/select/select_field_actions/Options';
-import { SelectField, SelectTypeOption } from '$app/components/database/application';
+import { SelectField, SelectTypeOption } from '$app/application/database';
 import { Divider } from '@mui/material';
 import { useTypeOption } from '$app/components/database';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/Filter.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/Filter.tsx
index 615d03dc04..895f3cb39c 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/Filter.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/Filter.tsx
@@ -9,14 +9,14 @@ import {
   CheckboxFilterData,
   ChecklistFilterData,
   DateFilterData,
-} from '$app/components/database/application';
+} from '$app/application/database';
 import { Chip, Popover } from '@mui/material';
 import { Property } from '$app/components/database/components/property';
 import { ReactComponent as DropDownSvg } from '$app/assets/dropdown.svg';
 import TextFilter from './text_filter/TextFilter';
 import { FieldType } from '@/services/backend';
 import FilterActions from '$app/components/database/components/filter/FilterActions';
-import { updateFilter } from '$app/components/database/application/filter/filter_service';
+import { updateFilter } from '$app/application/database/filter/filter_service';
 import { useViewId } from '$app/hooks';
 import SelectFilter from './select_filter/SelectFilter';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterActions.tsx
index 865f9e1829..090102f34b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterActions.tsx
@@ -1,9 +1,9 @@
 import React, { useState } from 'react';
 import { IconButton, Menu, MenuItem } from '@mui/material';
 import { ReactComponent as MoreSvg } from '$app/assets/details.svg';
-import { Filter } from '$app/components/database/application';
+import { Filter } from '$app/application/database';
 import { useTranslation } from 'react-i18next';
-import { deleteFilter } from '$app/components/database/application/filter/filter_service';
+import { deleteFilter } from '$app/application/database/filter/filter_service';
 import { useViewId } from '$app/hooks';
 
 function FilterActions({ filter }: { filter: Filter }) {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterFieldsMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterFieldsMenu.tsx
index 092b8cff7b..1b6d87296b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterFieldsMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/FilterFieldsMenu.tsx
@@ -1,11 +1,11 @@
 import React, { MouseEvent, useCallback } from 'react';
 import { MenuProps } from '@mui/material';
 import PropertiesList from '$app/components/database/components/property/PropertiesList';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import { useViewId } from '$app/hooks';
 import { useTranslation } from 'react-i18next';
-import { insertFilter } from '$app/components/database/application/filter/filter_service';
-import { getDefaultFilter } from '$app/components/database/application/filter/filter_data';
+import { insertFilter } from '$app/application/database/filter/filter_service';
+import { getDefaultFilter } from '$app/application/database/filter/filter_data';
 import Popover from '@mui/material/Popover';
 
 function FilterFieldsMenu({
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/date_filter/DateFilter.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/date_filter/DateFilter.tsx
index dabcb42b19..b603df79e2 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/date_filter/DateFilter.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/date_filter/DateFilter.tsx
@@ -4,7 +4,7 @@ import {
   DateFilterData,
   DateTimeField,
   DateTimeTypeOption,
-} from '$app/components/database/application';
+} from '$app/application/database';
 import { DateFilterConditionPB } from '@/services/backend';
 import CustomCalendar from '$app/components/database/components/field_types/date/CustomCalendar';
 import DateTimeSet from '$app/components/database/components/field_types/date/DateTimeSet';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/select_filter/SelectFilter.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/select_filter/SelectFilter.tsx
index d15a296200..02ad8d6f25 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/select_filter/SelectFilter.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/select_filter/SelectFilter.tsx
@@ -4,7 +4,7 @@ import {
   SelectFilter as SelectFilterType,
   SelectFilterData,
   SelectTypeOption,
-} from '$app/components/database/application';
+} from '$app/application/database';
 import { MenuItem, MenuList } from '@mui/material';
 import { Tag } from '$app/components/database/components/field_types/select/Tag';
 import { ReactComponent as SelectCheckSvg } from '$app/assets/select-check.svg';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/text_filter/TextFilter.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/text_filter/TextFilter.tsx
index 85075d6ea6..ccb3e6dde5 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/text_filter/TextFilter.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/filter/text_filter/TextFilter.tsx
@@ -1,5 +1,5 @@
 import React, { useState } from 'react';
-import { TextFilter as TextFilterType, TextFilterData } from '$app/components/database/application';
+import { TextFilter as TextFilterType, TextFilterData } from '$app/application/database';
 import { TextField } from '@mui/material';
 import { useTranslation } from 'react-i18next';
 import { TextFilterConditionPB } from '@/services/backend';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/NewProperty.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/NewProperty.tsx
index ca501ca231..6ff76392b3 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/NewProperty.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/NewProperty.tsx
@@ -1,5 +1,5 @@
 import React, { useCallback } from 'react';
-import { fieldService } from '$app/components/database/application';
+import { fieldService } from '$app/application/database';
 import { FieldType } from '@/services/backend';
 import { useTranslation } from 'react-i18next';
 import Button from '@mui/material/Button';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertiesList.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertiesList.tsx
index 89a69141de..e47e7200f8 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertiesList.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertiesList.tsx
@@ -1,7 +1,7 @@
 import React, { useCallback, useMemo, useState } from 'react';
 import { OutlinedInput, MenuItem, MenuList } from '@mui/material';
 import { Property } from '$app/components/database/components/property/Property';
-import { Field as FieldType } from '../../application';
+import { Field as FieldType } from '$app/application/database';
 import { useDatabase } from '$app/components/database';
 
 interface FieldListProps {
@@ -42,7 +42,7 @@ function PropertiesList({ showSearch, onItemClick, searchPlaceholder }: FieldLis
     <div className={'pt-2'}>
       {searchInput}
       {emptyList}
-      <MenuList className={'max-h-[300px] overflow-y-auto overflow-x-hidden'}>
+      <MenuList className={'max-h-[300px] overflow-y-auto overflow-x-hidden px-2'}>
         {fieldsResult.map((field) => (
           <MenuItem
             className={'overflow-hidden text-ellipsis px-1'}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/Property.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/Property.tsx
index ea4de01e03..e3a93cd28f 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/Property.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/Property.tsx
@@ -1,5 +1,5 @@
 import { FC, useEffect, useRef, useState } from 'react';
-import { Field as FieldType } from '../../application';
+import { Field as FieldType } from '$app/application/database';
 import { ProppertyTypeSvg } from './property_type/ProppertyTypeSvg';
 import { PropertyMenu } from '$app/components/database/components/property/PropertyMenu';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyActions.tsx
index 9e447394a0..305676f64a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyActions.tsx
@@ -7,10 +7,10 @@ import { ReactComponent as DeleteSvg } from '$app/assets/delete.svg';
 import { ReactComponent as LeftSvg } from '$app/assets/left.svg';
 import { ReactComponent as RightSvg } from '$app/assets/right.svg';
 import { useViewId } from '$app/hooks';
-import { fieldService } from '$app/components/database/application';
+import { fieldService } from '$app/application/database';
 import { OrderObjectPositionTypePB, FieldVisibility } from '@/services/backend';
 import { MenuItem } from '@mui/material';
-import ConfirmDialog from '$app/components/_shared/app-dialog/ConfirmDialog';
+import DeleteConfirmDialog from '$app/components/_shared/delete_confirm_dialog/DeleteConfirmDialog';
 import { useTranslation } from 'react-i18next';
 
 export enum FieldAction {
@@ -83,7 +83,8 @@ function PropertyActions({ fieldId, onMenuItemClick, isPrimary, actions = defaul
         break;
       case FieldAction.InsertLeft:
       case FieldAction.InsertRight: {
-        const fieldPosition = action === FieldAction.InsertLeft ? OrderObjectPositionTypePB.Before : OrderObjectPositionTypePB.After;
+        const fieldPosition =
+          action === FieldAction.InsertLeft ? OrderObjectPositionTypePB.Before : OrderObjectPositionTypePB.After;
 
         const field = await fieldService.createField({
           viewId,
@@ -124,7 +125,7 @@ function PropertyActions({ fieldId, onMenuItemClick, isPrimary, actions = defaul
           </MenuItem>
         );
       })}
-      <ConfirmDialog
+      <DeleteConfirmDialog
         open={openConfirm}
         subtitle={''}
         title={t('grid.field.deleteFieldPromptMessage')}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyMenu.tsx
index 618a0d82c8..abd26a62ea 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyMenu.tsx
@@ -1,7 +1,7 @@
 import { Divider, MenuList } from '@mui/material';
 import { FC, useCallback } from 'react';
 import { useViewId } from '$app/hooks';
-import { Field, fieldService } from '../../application';
+import { Field, fieldService } from '$app/application/database';
 import PropertyTypeMenuExtension from '$app/components/database/components/property/property_type/PropertyTypeMenuExtension';
 import PropertyTypeSelect from '$app/components/database/components/property/property_type/PropertyTypeSelect';
 import { FieldType } from '@/services/backend';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyNameInput.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyNameInput.tsx
index 7d0d806fd7..31e7a26456 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyNameInput.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertyNameInput.tsx
@@ -1,6 +1,6 @@
 import React, { ChangeEventHandler, useCallback, useState } from 'react';
 import { useViewId } from '$app/hooks';
-import { fieldService } from '$app/components/database/application';
+import { fieldService } from '$app/application/database';
 import { Log } from '$app/utils/log';
 import TextField from '@mui/material/TextField';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertySelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertySelect.tsx
index 1a798d965b..5c4522904a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertySelect.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/PropertySelect.tsx
@@ -1,6 +1,6 @@
 import { MenuItem, Select, SelectChangeEvent, SelectProps } from '@mui/material';
 import { FC, useCallback } from 'react';
-import { Field as FieldType } from '../../application';
+import { Field as FieldType } from '$app/application/database';
 import { useDatabase } from '../../Database.hooks';
 import { Property } from './Property';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenu.tsx
index 33a279b6ed..f6bb705fc4 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenu.tsx
@@ -2,7 +2,7 @@ import { Divider, Menu, MenuItem, MenuProps } from '@mui/material';
 import { FC, useMemo } from 'react';
 import { FieldType } from '@/services/backend';
 import { PropertyTypeText, ProppertyTypeSvg } from '$app/components/database/components/property';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import { ReactComponent as SelectCheckSvg } from '$app/assets/select-check.svg';
 
 const FieldTypeGroup = [
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenuExtension.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenuExtension.tsx
index 2a5c488194..b45b670757 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenuExtension.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeMenuExtension.tsx
@@ -1,6 +1,6 @@
 import React, { useMemo } from 'react';
 import { FieldType } from '@/services/backend';
-import { DateTimeField, Field, NumberField, SelectField } from '$app/components/database/application';
+import { DateTimeField, Field, NumberField, SelectField } from '$app/application/database';
 import SelectFieldActions from '$app/components/database/components/field_types/select/select_field_actions/SelectFieldActions';
 import NumberFieldActions from '$app/components/database/components/field_types/number/NumberFieldActions';
 import DateTimeFieldActions from '$app/components/database/components/field_types/date/DateTimeFieldActions';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeSelect.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeSelect.tsx
index 8226b2aad5..27805c0035 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeSelect.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/property/property_type/PropertyTypeSelect.tsx
@@ -1,7 +1,7 @@
 import React, { useRef, useState } from 'react';
 import { ProppertyTypeSvg } from '$app/components/database/components/property/property_type/ProppertyTypeSvg';
 import { MenuItem } from '@mui/material';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import { ReactComponent as MoreSvg } from '$app/assets/more.svg';
 import { PropertyTypeMenu } from '$app/components/database/components/property/property_type/PropertyTypeMenu';
 import { FieldType } from '@/services/backend';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortFieldsMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortFieldsMenu.tsx
index ae9d801ff1..b0b80b6bb7 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortFieldsMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortFieldsMenu.tsx
@@ -1,7 +1,7 @@
 import React, { FC, MouseEvent, useCallback } from 'react';
 import { MenuProps } from '@mui/material';
 import PropertiesList from '$app/components/database/components/property/PropertiesList';
-import { Field, sortService } from '$app/components/database/application';
+import { Field, sortService } from '$app/application/database';
 import { SortConditionPB } from '@/services/backend';
 import { useTranslation } from 'react-i18next';
 import { useViewId } from '$app/hooks';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortItem.tsx
index f6e216f371..e042e9c9c5 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortItem.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortItem.tsx
@@ -1,7 +1,7 @@
 import { IconButton, SelectChangeEvent, Stack } from '@mui/material';
 import { FC, useCallback } from 'react';
 import { ReactComponent as CloseSvg } from '$app/assets/close.svg';
-import { Field, Sort, sortService } from '../../application';
+import { Field, Sort, sortService } from '$app/application/database';
 import { PropertySelect } from '../property';
 import { SortConditionSelect } from './SortConditionSelect';
 import { useViewId } from '@/appflowy_app/hooks';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortMenu.tsx
index 6e42830b5f..148d98f1cb 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/sort/SortMenu.tsx
@@ -1,7 +1,7 @@
 import { Menu, MenuProps } from '@mui/material';
 import { FC, MouseEventHandler, useCallback, useState } from 'react';
 import { useViewId } from '$app/hooks';
-import { sortService } from '../../application';
+import { sortService } from '$app/application/database';
 import { useDatabase } from '../../Database.hooks';
 import { SortItem } from './SortItem';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/AddViewBtn.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/AddViewBtn.tsx
index 6145a487f4..717bf1eb18 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/AddViewBtn.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/AddViewBtn.tsx
@@ -3,7 +3,7 @@ import { IconButton } from '@mui/material';
 import { ReactComponent as AddSvg } from '$app/assets/add.svg';
 import { useTranslation } from 'react-i18next';
 import { ViewLayoutPB } from '@/services/backend';
-import { createDatabaseView } from '$app/components/database/application/database_view/database_view_service';
+import { createDatabaseView } from '$app/application/database/database_view/database_view_service';
 
 function AddViewBtn({ pageId, onCreated }: { pageId: string; onCreated: (id: string) => void }) {
   const { t } = useTranslation();
@@ -18,9 +18,11 @@ function AddViewBtn({ pageId, onCreated }: { pageId: string; onCreated: (id: str
   };
 
   return (
-    <IconButton onClick={onClick} size='small'>
-      <AddSvg />
-    </IconButton>
+    <div className={'ml-1 flex items-center justify-center border-l border-line-divider px-1'}>
+      <IconButton className={'flex items-center justify-center'} onClick={onClick} size='small'>
+        <AddSvg />
+      </IconButton>
+    </div>
   );
 }
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/DatabaseTabBar.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/DatabaseTabBar.tsx
index 51ccdaaefa..86522b72aa 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/DatabaseTabBar.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/DatabaseTabBar.tsx
@@ -47,6 +47,15 @@ export const DatabaseTabBar: FC<DatabaseTabBarProps> = ({ pageId, childViewIds,
     }
   }, [selectedViewId, setSelectedViewId, views]);
 
+  const openMenu = (view: Page) => {
+    return (e: React.MouseEvent<HTMLElement>) => {
+      e.preventDefault();
+      e.stopPropagation();
+      setContextMenuView(view);
+      setContextMenuAnchorEl(e.currentTarget);
+    };
+  };
+
   return (
     <div className='-mb-px flex items-center px-16'>
       <div className='flex flex-1 items-center border-b border-line-divider'>
@@ -56,12 +65,8 @@ export const DatabaseTabBar: FC<DatabaseTabBarProps> = ({ pageId, childViewIds,
 
             return (
               <ViewTab
-                onContextMenu={(e) => {
-                  e.preventDefault();
-                  e.stopPropagation();
-                  setContextMenuView(view);
-                  setContextMenuAnchorEl(e.currentTarget);
-                }}
+                onContextMenu={openMenu(view)}
+                onDoubleClick={openMenu(view)}
                 key={view.id}
                 icon={<Icon />}
                 iconPosition='start'
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewActions.tsx
index 1495c43ed8..0d61e62544 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewActions.tsx
@@ -2,9 +2,9 @@ import React, { useState } from 'react';
 import { useTranslation } from 'react-i18next';
 import { ReactComponent as DeleteSvg } from '$app/assets/delete.svg';
 import { ReactComponent as EditSvg } from '$app/assets/edit.svg';
-import { deleteView, updateView } from '$app/components/database/application/database_view/database_view_service';
+import { deleteView, updateView } from '$app/application/database/database_view/database_view_service';
 import { MenuItem, MenuProps, Menu } from '@mui/material';
-import RenameDialog from '$app/components/layout/NestedPage/RenameDialog';
+import RenameDialog from '$app/components/layout/nested_page/RenameDialog';
 import { Page } from '$app_reducers/pages/slice';
 
 enum ViewAction {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewTabs.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewTabs.tsx
index ee866ff91b..a88edf7f2a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewTabs.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/components/tab_bar/ViewTabs.tsx
@@ -15,6 +15,7 @@ export const ViewTab = styled((props: TabProps) => <Tab disableRipple {...props}
   fontSize: '12px',
   lineHeight: '16px',
   minWidth: 'unset',
+  margin: '4px 0',
 
   '&.Mui-selected': {
     color: 'inherit',
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid/Grid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid.tsx
similarity index 67%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid/Grid.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid.tsx
index 154c0d0444..beb90c66dc 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid/Grid.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid.tsx
@@ -1,5 +1,5 @@
 import { FC } from 'react';
-import { GridTable, GridTableProps } from '../GridTable';
+import { GridTable, GridTableProps } from './grid_table';
 
 export const Grid: FC<GridTableProps> = (props) => {
   return <GridTable {...props} />;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid/index.ts
deleted file mode 100644
index 237cbef136..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/Grid/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './Grid';
\ No newline at end of file
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/index.ts
deleted file mode 100644
index 2b6d663ef5..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './GridCell';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/index.ts
deleted file mode 100644
index 69112da7e2..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './GridField';
\ No newline at end of file
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/index.ts
deleted file mode 100644
index 8551dd0ccc..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './GridTable';
\ No newline at end of file
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/constants.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/constants.ts
index 91f8b16f3c..eadfadaa89 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/constants.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/constants.ts
@@ -1,4 +1,4 @@
-import { Field, RowMeta } from '../application';
+import { Field, RowMeta } from '$app/application/database';
 
 export const GridCalculateCountHeight = 40;
 
@@ -65,7 +65,7 @@ export const rowMetasToRenderRow = (rowMetas: RowMeta[]): RenderRow[] => {
     })),
     {
       type: RenderRowType.NewRow,
-      data: { },
+      data: {},
     },
     {
       type: RenderRowType.CalculateRow,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCalculate/GridCalculate.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_calculate/GridCalculate.tsx
similarity index 87%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCalculate/GridCalculate.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_calculate/GridCalculate.tsx
index c6bcac90f9..da222e3330 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCalculate/GridCalculate.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_calculate/GridCalculate.tsx
@@ -1,6 +1,6 @@
 import React from 'react';
 import { useDatabaseVisibilityRows } from '$app/components/database';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import { DEFAULT_FIELD_WIDTH, GRID_ACTIONS_WIDTH } from '$app/components/database/grid/constants';
 
 interface Props {
@@ -9,7 +9,7 @@ interface Props {
   getContainerRef?: () => React.RefObject<HTMLDivElement>;
 }
 
-function GridCalculate({ field, index }: Props) {
+export function GridCalculate({ field, index }: Props) {
   const rowMetas = useDatabaseVisibilityRows();
   const count = rowMetas.length;
   const width = index === 0 ? GRID_ACTIONS_WIDTH : field.width ?? DEFAULT_FIELD_WIDTH;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCalculate/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_calculate/index.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCalculate/index.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_calculate/index.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/GridCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/GridCell.tsx
similarity index 82%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/GridCell.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/GridCell.tsx
index a1967de801..042ba1777d 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/GridCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/GridCell.tsx
@@ -1,10 +1,10 @@
 import React, { CSSProperties, memo } from 'react';
 import { GridColumn, RenderRow, RenderRowType } from '../constants';
-import GridNewRow from '$app/components/database/grid/GridNewRow/GridNewRow';
-import GridCalculate from '$app/components/database/grid/GridCalculate/GridCalculate';
+import GridNewRow from '$app/components/database/grid/grid_new_row/GridNewRow';
+import { GridCalculate } from '$app/components/database/grid/grid_calculate';
 import { areEqual } from 'react-window';
 import { Cell } from '$app/components/database/components';
-import PrimaryCell from '$app/components/database/grid/GridCell/PrimaryCell';
+import { PrimaryCell } from '$app/components/database/grid/grid_cell';
 
 const getRenderRowKey = (row: RenderRow) => {
   if (row.type === RenderRowType.Row) {
@@ -51,11 +51,7 @@ export const GridCell = memo(({ row, column, columnIndex, style, onEditRecord, g
     case RenderRowType.NewRow:
       return (
         <div style={style} className={'flex border-b border-line-divider'}>
-          <GridNewRow
-            getContainerRef={getContainerRef}
-            index={columnIndex}
-            groupId={row.data.groupId}
-          />
+          <GridNewRow getContainerRef={getContainerRef} index={columnIndex} groupId={row.data.groupId} />
         </div>
       );
     case RenderRowType.CalculateRow:
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/PrimaryCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/PrimaryCell.tsx
similarity index 95%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/PrimaryCell.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/PrimaryCell.tsx
index 1b2a7f1606..b9a734de7b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridCell/PrimaryCell.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/PrimaryCell.tsx
@@ -2,9 +2,9 @@ import React, { Suspense, useMemo, useRef } from 'react';
 import { ReactComponent as OpenIcon } from '$app/assets/open.svg';
 import { IconButton } from '@mui/material';
 
-import { useGridTableHoverState } from '$app/components/database/grid/GridRowActions/GridRowActions.hooks';
+import { useGridTableHoverState } from '$app/components/database/grid/grid_row_actions';
 
-function PrimaryCell({
+export function PrimaryCell({
   onEditRecord,
   icon,
   getContainerRef,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/index.ts
new file mode 100644
index 0000000000..949d5054bf
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_cell/index.ts
@@ -0,0 +1,2 @@
+export * from './GridCell';
+export * from './PrimaryCell';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridField.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridField.tsx
similarity index 94%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridField.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridField.tsx
index 691ab28a6f..d14df4f813 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridField.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridField.tsx
@@ -2,12 +2,11 @@ import { Button, Tooltip } from '@mui/material';
 import { DragEventHandler, FC, HTMLAttributes, memo, useCallback, useEffect, useMemo, useState } from 'react';
 import { useViewId } from '$app/hooks';
 import { DragItem, DropPosition, DragType, useDraggable, useDroppable, ScrollDirection } from '../../_shared';
-import { fieldService, Field } from '../../application';
+import { fieldService, Field } from '$app/application/database';
 import { Property } from '$app/components/database/components/property';
-import GridResizer from '$app/components/database/grid/GridField/GridResizer';
-import GridFieldMenu from '$app/components/database/grid/GridField/GridFieldMenu';
+import { GridResizer, GridFieldMenu } from '$app/components/database/grid/grid_field';
 import { areEqual } from 'react-window';
-import { useOpenMenu } from '$app/components/database/grid/GridStickyHeader/GridStickyHeader.hooks';
+import { useOpenMenu } from '$app/components/database/grid/grid_sticky_header/GridStickyHeader.hooks';
 import throttle from 'lodash-es/throttle';
 
 export interface GridFieldProps extends HTMLAttributes<HTMLDivElement> {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridFieldMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridFieldMenu.tsx
similarity index 90%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridFieldMenu.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridFieldMenu.tsx
index 1509c93e3b..ce351240e1 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridFieldMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridFieldMenu.tsx
@@ -1,6 +1,6 @@
 import React from 'react';
 import Popover, { PopoverProps } from '@mui/material/Popover';
-import { Field } from '$app/components/database/application';
+import { Field } from '$app/application/database';
 import PropertyNameInput from '$app/components/database/components/property/PropertyNameInput';
 import { MenuList, Portal } from '@mui/material';
 import PropertyActions, { FieldAction } from '$app/components/database/components/property/PropertyActions';
@@ -11,7 +11,7 @@ interface Props extends PopoverProps {
   onOpenMenu?: (fieldId: string) => void;
 }
 
-function GridFieldMenu({ field, onOpenPropertyMenu, onOpenMenu, ...props }: Props) {
+export function GridFieldMenu({ field, onOpenPropertyMenu, onOpenMenu, ...props }: Props) {
   return (
     <Portal>
       <Popover
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridNewField.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridNewField.tsx
similarity index 85%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridNewField.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridNewField.tsx
index 10611fc446..d0b739298a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridNewField.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridNewField.tsx
@@ -1,12 +1,12 @@
 import React, { useCallback } from 'react';
 import { useViewId } from '$app/hooks';
 import { useTranslation } from 'react-i18next';
-import { fieldService } from '$app/components/database/application';
+import { fieldService } from '$app/application/database';
 import { FieldType } from '@/services/backend';
 import Button from '@mui/material/Button';
 import { ReactComponent as AddSvg } from '$app/assets/add.svg';
 
-function GridNewField({ onInserted }: { onInserted?: (id: string) => void }) {
+export function GridNewField({ onInserted }: { onInserted?: (id: string) => void }) {
   const viewId = useViewId();
   const { t } = useTranslation();
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridResizer.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridResizer.tsx
similarity index 93%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridResizer.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridResizer.tsx
index bac219ee08..e673458318 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridField/GridResizer.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/GridResizer.tsx
@@ -1,5 +1,5 @@
 import React, { useCallback, useEffect, useRef, useState } from 'react';
-import { Field, fieldService } from '$app/components/database/application';
+import { Field, fieldService } from '$app/application/database';
 import { useViewId } from '$app/hooks';
 
 interface GridResizerProps {
@@ -9,7 +9,7 @@ interface GridResizerProps {
 
 const minWidth = 100;
 
-function GridResizer({ field, onWidthChange }: GridResizerProps) {
+export function GridResizer({ field, onWidthChange }: GridResizerProps) {
   const viewId = useViewId();
   const fieldId = field.id;
   const width = field.width || 0;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/index.ts
new file mode 100644
index 0000000000..384ee2af3b
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_field/index.ts
@@ -0,0 +1,4 @@
+export * from './GridField';
+export * from './GridFieldMenu';
+export * from './GridNewField';
+export * from './GridResizer';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridNewRow/GridNewRow.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_new_row/GridNewRow.tsx
similarity index 95%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridNewRow/GridNewRow.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_new_row/GridNewRow.tsx
index 23d490cf95..713430eb51 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridNewRow/GridNewRow.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_new_row/GridNewRow.tsx
@@ -1,5 +1,5 @@
 import React, { useCallback } from 'react';
-import { rowService } from '$app/components/database/application';
+import { rowService } from '$app/application/database';
 import { useViewId } from '$app/hooks';
 import { t } from 'i18next';
 import { ReactComponent as AddSvg } from '$app/assets/add.svg';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridOverlay/GridTableOverlay.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_overlay/GridTableOverlay.tsx
similarity index 77%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridOverlay/GridTableOverlay.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_overlay/GridTableOverlay.tsx
index 6c1ecc95df..3443535258 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridOverlay/GridTableOverlay.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_overlay/GridTableOverlay.tsx
@@ -1,8 +1,9 @@
 import React, { useEffect, useState } from 'react';
-import GridRowContextMenu from '$app/components/database/grid/GridRowActions/GridRowContextMenu';
-import GridRowActions from '$app/components/database/grid/GridRowActions/GridRowActions';
-
-import { useGridTableHoverState } from '$app/components/database/grid/GridRowActions/GridRowActions.hooks';
+import {
+  GridRowContextMenu,
+  GridRowActions,
+  useGridTableHoverState,
+} from '$app/components/database/grid/grid_row_actions';
 
 function GridTableOverlay({
   containerRef,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowActions.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowActions.hooks.ts
similarity index 98%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowActions.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowActions.hooks.ts
index d49ab6addc..9237bb3c03 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowActions.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowActions.hooks.ts
@@ -1,6 +1,6 @@
 import React, { useCallback, useEffect, useRef, useState } from 'react';
 import { useViewId } from '$app/hooks';
-import { rowService } from '$app/components/database/application';
+import { rowService } from '$app/application/database';
 import { autoScrollOnEdge, ScrollDirection } from '$app/components/database/_shared/dnd/utils';
 
 export function getCellsWithRowId(rowId: string, container: HTMLDivElement) {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowActions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowActions.tsx
similarity index 90%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowActions.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowActions.tsx
index 020bbc5387..2813c05f86 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowActions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowActions.tsx
@@ -3,13 +3,12 @@ import { IconButton, Tooltip } from '@mui/material';
 import { t } from 'i18next';
 import { ReactComponent as AddSvg } from '$app/assets/add.svg';
 import { GRID_ACTIONS_WIDTH } from '$app/components/database/grid/constants';
-import { rowService } from '$app/components/database/application';
+import { rowService } from '$app/application/database';
 import { useViewId } from '$app/hooks';
-import GridRowDragButton from '$app/components/database/grid/GridRowActions/GridRowDragButton';
-import GridRowMenu from '$app/components/database/grid/GridRowActions/GridRowMenu';
+import { GridRowDragButton, GridRowMenu } from '$app/components/database/grid/grid_row_actions';
 import { OrderObjectPositionTypePB } from '@/services/backend';
 
-function GridRowActions({
+export function GridRowActions({
   rowId,
   rowTop,
   containerRef,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowContextMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowContextMenu.tsx
similarity index 97%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowContextMenu.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowContextMenu.tsx
index 0734b345c1..5e5aeeb619 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowContextMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowContextMenu.tsx
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
 import GridRowMenu from './GridRowMenu';
 import { toggleProperty } from './GridRowActions.hooks';
 
-function GridRowContextMenu({
+export function GridRowContextMenu({
   containerRef,
   hoverRowId,
 }: {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowDragButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowDragButton.tsx
similarity index 96%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowDragButton.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowDragButton.tsx
index 1ebb018da9..6d271270a9 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowDragButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowDragButton.tsx
@@ -4,7 +4,7 @@ import { IconButton, Tooltip } from '@mui/material';
 import { ReactComponent as DragSvg } from '$app/assets/drag.svg';
 import { useTranslation } from 'react-i18next';
 
-function GridRowDragButton({
+export function GridRowDragButton({
   rowId,
   containerRef,
   onClick,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowMenu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowMenu.tsx
similarity index 95%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowMenu.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowMenu.tsx
index c8ab6bc7cf..3daa5041e3 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridRowActions/GridRowMenu.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/GridRowMenu.tsx
@@ -6,7 +6,7 @@ import { ReactComponent as CopySvg } from '$app/assets/copy.svg';
 import Popover, { PopoverProps } from '@mui/material/Popover';
 import { useViewId } from '$app/hooks';
 import { useTranslation } from 'react-i18next';
-import { rowService } from '$app/components/database/application';
+import { rowService } from '$app/application/database';
 import { Icon, MenuItem, MenuList } from '@mui/material';
 import { OrderObjectPositionTypePB } from '@/services/backend';
 
@@ -21,7 +21,7 @@ interface Props extends PopoverProps {
   rowId: string;
 }
 
-function GridRowMenu({ rowId, ...props }: Props) {
+export function GridRowMenu({ rowId, ...props }: Props) {
   const viewId = useViewId();
 
   const { t } = useTranslation();
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/index.ts
new file mode 100644
index 0000000000..fb50b6248c
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_row_actions/index.ts
@@ -0,0 +1,5 @@
+export * from './GridRowActions.hooks';
+export * from './GridRowActions';
+export * from './GridRowContextMenu';
+export * from './GridRowDragButton';
+export * from './GridRowMenu';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridStickyHeader/GridStickyHeader.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_sticky_header/GridStickyHeader.hooks.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridStickyHeader/GridStickyHeader.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_sticky_header/GridStickyHeader.hooks.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridStickyHeader/GridStickyHeader.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_sticky_header/GridStickyHeader.tsx
similarity index 91%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridStickyHeader/GridStickyHeader.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_sticky_header/GridStickyHeader.tsx
index 2b67a4fe6f..333edf89ba 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridStickyHeader/GridStickyHeader.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_sticky_header/GridStickyHeader.tsx
@@ -1,11 +1,11 @@
 import React, { useCallback, useState } from 'react';
 import { GridChildComponentProps, VariableSizeGrid as Grid } from 'react-window';
 import AutoSizer from 'react-virtualized-auto-sizer';
-import { useGridColumn } from '$app/components/database/grid/GridTable/GridTable.hooks';
-import { GridField } from '$app/components/database/grid/GridField';
+import { useGridColumn } from '$app/components/database/grid/grid_table';
+import { GridField } from 'src/appflowy_app/components/database/grid/grid_field';
 import NewProperty from '$app/components/database/components/property/NewProperty';
 import { GridColumn, GridColumnType } from '$app/components/database/grid/constants';
-import { OpenMenuContext } from '$app/components/database/grid/GridStickyHeader/GridStickyHeader.hooks';
+import { OpenMenuContext } from '$app/components/database/grid/grid_sticky_header/GridStickyHeader.hooks';
 
 const GridStickyHeader = React.forwardRef<
   Grid<HTMLDivElement> | null,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/GridTable.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/GridTable.hooks.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/GridTable.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/GridTable.hooks.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/GridTable.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/GridTable.tsx
similarity index 91%
rename from frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/GridTable.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/GridTable.tsx
index c0bede08ee..3dee0941a9 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/GridTable/GridTable.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/GridTable.tsx
@@ -1,14 +1,14 @@
 import React, { FC, useCallback, useMemo, useRef } from 'react';
-import { RowMeta } from '../../application';
+import { RowMeta } from '$app/application/database';
 import { useDatabaseVisibilityFields, useDatabaseVisibilityRows } from '../../Database.hooks';
 import { fieldsToColumns, GridColumn, RenderRow, RenderRowType, rowMetasToRenderRow } from '../constants';
 import { CircularProgress } from '@mui/material';
 import { GridChildComponentProps, GridOnScrollProps, VariableSizeGrid as Grid } from 'react-window';
 import AutoSizer from 'react-virtualized-auto-sizer';
-import { GridCell } from '$app/components/database/grid/GridCell';
-import { useGridColumn, useGridRow } from '$app/components/database/grid/GridTable/GridTable.hooks';
-import GridStickyHeader from '$app/components/database/grid/GridStickyHeader/GridStickyHeader';
-import GridTableOverlay from '$app/components/database/grid/GridOverlay/GridTableOverlay';
+import { GridCell } from 'src/appflowy_app/components/database/grid/grid_cell';
+import { useGridColumn, useGridRow } from './GridTable.hooks';
+import GridStickyHeader from '$app/components/database/grid/grid_sticky_header/GridStickyHeader';
+import GridTableOverlay from '$app/components/database/grid/grid_overlay/GridTableOverlay';
 import ReactDOM from 'react-dom';
 
 export interface GridTableProps {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/index.ts
new file mode 100644
index 0000000000..dfdb9b7949
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/grid_table/index.ts
@@ -0,0 +1,2 @@
+export * from './GridTable';
+export * from './GridTable.hooks';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/index.ts
index 9296c1d2fa..762542e7cb 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/index.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/database/grid/index.ts
@@ -1 +1 @@
-export { Grid } from './Grid';
\ No newline at end of file
+export * from './Grid';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/document/document_header/DocumentHeader.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/document/document_header/DocumentHeader.tsx
index 87deb9e147..611aecc84a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/document/document_header/DocumentHeader.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/document/document_header/DocumentHeader.tsx
@@ -1,27 +1,19 @@
 import React, { memo, useCallback } from 'react';
 import { Page, PageIcon } from '$app_reducers/pages/slice';
-import { useAppDispatch } from '$app/stores/store';
-import ViewTitle from '$app/components/_shared/ViewTitle';
-import { updatePageIcon } from '$app_reducers/pages/async_actions';
+import ViewTitle from '$app/components/_shared/view_title/ViewTitle';
+import { updatePageIcon } from '$app/application/folder/page.service';
 
 interface DocumentHeaderProps {
   page: Page;
 }
 
 export function DocumentHeader({ page }: DocumentHeaderProps) {
-  const dispatch = useAppDispatch();
-
   const pageId = page.id;
   const onUpdateIcon = useCallback(
-    (icon: PageIcon) => {
-      void dispatch(
-        updatePageIcon({
-          id: pageId,
-          icon: icon.value ? icon : undefined,
-        })
-      );
+    async (icon: PageIcon) => {
+      await updatePageIcon(pageId, icon.value ? icon : undefined);
     },
-    [dispatch, pageId]
+    [pageId]
   );
 
   if (!page) return null;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/Editor.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/editor/Editor.tsx
index caed46c256..1d6be5c293 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/Editor.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/Editor.tsx
@@ -7,10 +7,12 @@ import { EditorIdProvider } from '$app/components/editor/Editor.hooks';
 
 export function Editor(props: EditorProps) {
   return (
-    <EditorIdProvider value={props.id}>
-      <CollaborativeEditor {...props} />
-      <Toaster />
-    </EditorIdProvider>
+    <div className={'appflowy-editor relative'}>
+      <EditorIdProvider value={props.id}>
+        <CollaborativeEditor {...props} />
+        <Toaster />
+      </EditorIdProvider>
+    </div>
   );
 }
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/_shared/PlaceholderContent.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/_shared/PlaceholderContent.tsx
index 1d4d225a02..9c8e163b45 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/_shared/PlaceholderContent.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/_shared/PlaceholderContent.tsx
@@ -1,4 +1,4 @@
-import React, { CSSProperties, useMemo } from 'react';
+import React, { CSSProperties, useEffect, useMemo, useState } from 'react';
 import { ReactEditor, useSelected, useSlateStatic } from 'slate-react';
 import { Editor, Element, Range } from 'slate';
 import { EditorNodeType, HeadingNode } from '$app/application/document/document.types';
@@ -8,7 +8,7 @@ function PlaceholderContent({ node, ...attributes }: { node: Element; className?
   const { t } = useTranslation();
   const editor = useSlateStatic();
   const selected = useSelected() && !!editor.selection && Range.isCollapsed(editor.selection);
-
+  const [isComposing, setIsComposing] = useState(false);
   const block = useMemo(() => {
     const path = ReactEditor.findPath(editor, node);
     const match = Editor.above(editor, {
@@ -88,6 +88,31 @@ function PlaceholderContent({ node, ...attributes }: { node: Element; className?
     }
   }, [block?.type, t, unSelectedPlaceholder]);
 
+  useEffect(() => {
+    if (!selected) return;
+
+    const handleCompositionStart = () => {
+      setIsComposing(true);
+    };
+
+    const handleCompositionEnd = () => {
+      setIsComposing(false);
+    };
+
+    const editorDom = ReactEditor.toDOMNode(editor, editor);
+
+    editorDom.addEventListener('compositionstart', handleCompositionStart);
+    editorDom.addEventListener('compositionend', handleCompositionEnd);
+    return () => {
+      editorDom.removeEventListener('compositionstart', handleCompositionStart);
+      editorDom.removeEventListener('compositionend', handleCompositionEnd);
+    };
+  }, [editor, selected]);
+
+  if (isComposing) {
+    return null;
+  }
+
   return (
     <span contentEditable={false} {...attributes} className={className}>
       {selected ? selectedPlaceholder : unSelectedPlaceholder}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/callout/CalloutIcon.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/callout/CalloutIcon.tsx
index 3c32e988a1..5a57e57888 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/callout/CalloutIcon.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/callout/CalloutIcon.tsx
@@ -1,7 +1,7 @@
 import React, { useCallback, useRef, useState } from 'react';
 import { IconButton } from '@mui/material';
 import { CalloutNode } from '$app/application/document/document.types';
-import EmojiPicker from '$app/components/_shared/EmojiPicker';
+import EmojiPicker from '$app/components/_shared/emoji_picker/EmojiPicker';
 import Popover from '@mui/material/Popover';
 import { PopoverCommonProps } from '$app/components/editor/components/tools/popover';
 import { useSlateStatic } from 'slate-react';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/database/utils.ts b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/database/utils.ts
index c56092f175..032502b415 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/database/utils.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/database/utils.ts
@@ -1,11 +1,11 @@
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
 import { ViewLayoutPB } from '@/services/backend';
+import { createPage } from '$app/application/folder/page.service';
 
 export async function createGrid(pageId: string) {
-  const pageController = new PageController(pageId);
-  const newViewId = await pageController.createPage({
+  const newViewId = await createPage({
     layout: ViewLayoutPB.Grid,
     name: '',
+    parent_view_id: pageId,
   });
 
   return newViewId;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/math_equation/MathEquation.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/math_equation/MathEquation.tsx
index f09c9d1052..db13ed49ed 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/math_equation/MathEquation.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/blocks/math_equation/MathEquation.tsx
@@ -1,6 +1,6 @@
 import { forwardRef, memo, useState } from 'react';
 import { EditorElementProps, MathEquationNode } from '$app/application/document/document.types';
-import KatexMath from '$app/components/_shared/KatexMath';
+import KatexMath from '$app/components/_shared/katex_math/KatexMath';
 import { useTranslation } from 'react-i18next';
 import { FunctionsOutlined } from '@mui/icons-material';
 import EditPopover from '$app/components/editor/components/blocks/math_equation/EditPopover';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/editor/shortcuts/shortcuts.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/editor/shortcuts/shortcuts.hooks.ts
index f48affad4b..c9894b5e8d 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/editor/shortcuts/shortcuts.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/editor/shortcuts/shortcuts.hooks.ts
@@ -1,6 +1,6 @@
 import { ReactEditor } from 'slate-react';
 import { useCallback, KeyboardEvent } from 'react';
-import { EditorMarkFormat, EditorNodeType } from '$app/application/document/document.types';
+import { EditorMarkFormat, EditorNodeType, TodoListNode } from '$app/application/document/document.types';
 import isHotkey from 'is-hotkey';
 
 import { getBlock } from '$app/components/editor/plugins/utils';
@@ -95,6 +95,12 @@ export function useShortcuts(editor: ReactEditor) {
 
         return;
       }
+
+      if (isHotkey('mod+Enter', e) && node && node.type === EditorNodeType.TodoListBlock) {
+        e.preventDefault();
+        CustomEditor.toggleTodo(editor, node as TodoListNode);
+        return;
+      }
     },
     [editor]
   );
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/inline_formula/FormulaLeaf.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/inline_formula/FormulaLeaf.tsx
index f0f5b1a616..5899630867 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/inline_formula/FormulaLeaf.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/inline_formula/FormulaLeaf.tsx
@@ -1,5 +1,5 @@
 import React from 'react';
-import KatexMath from '$app/components/_shared/KatexMath';
+import KatexMath from '$app/components/_shared/katex_math/KatexMath';
 
 function FormulaLeaf({ formula, children }: { formula: string; children: React.ReactNode }) {
   return (
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/mention/MentionLeaf.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/mention/MentionLeaf.tsx
index c8db92c2e1..adf22a53a0 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/mention/MentionLeaf.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/editor/components/inline_nodes/mention/MentionLeaf.tsx
@@ -1,10 +1,10 @@
 import React, { useCallback, useEffect, useState } from 'react';
 import { Mention, MentionPage } from '$app/application/document/document.types';
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
 import { ReactComponent as DocumentSvg } from '$app/assets/document.svg';
 import { useTranslation } from 'react-i18next';
 import { useNavigate } from 'react-router-dom';
 import { pageTypeMap } from '$app_reducers/pages/slice';
+import { getPage } from '$app/application/folder/page.service';
 
 export function MentionLeaf({ children, mention }: { mention: Mention; children: React.ReactNode }) {
   const { t } = useTranslation();
@@ -12,7 +12,7 @@ export function MentionLeaf({ children, mention }: { mention: Mention; children:
   const navigate = useNavigate();
   const loadPage = useCallback(async () => {
     if (!mention.page) return;
-    const page = await new PageController(mention.page).getPage();
+    const page = await getPage(mention.page);
 
     setPage(page);
   }, [mention.page]);
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Layout.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Layout.tsx
index b41096f6c1..d912c4bf6b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Layout.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Layout.tsx
@@ -1,6 +1,6 @@
 import React, { ReactNode, useEffect } from 'react';
-import SideBar from '$app/components/layout/SideBar';
-import TopBar from '$app/components/layout/TopBar';
+import SideBar from '$app/components/layout/side_bar/SideBar';
+import TopBar from '$app/components/layout/top_bar/TopBar';
 import { useAppSelector } from '$app/stores/store';
 import { FooterPanel } from '$app/components/layout/FooterPanel';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/Workspace.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/Workspace.hooks.ts
deleted file mode 100644
index e04bd734a0..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/Workspace.hooks.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import { useCallback, useEffect, useMemo } from 'react';
-import { WorkspaceController } from '$app/stores/effects/workspace/workspace_controller';
-import { useAppDispatch, useAppSelector } from '$app/stores/store';
-import { workspaceActions, WorkspaceItem } from '$app_reducers/workspace/slice';
-import { WorkspaceManagerController } from '$app/stores/effects/workspace/workspace_manager_controller';
-import { Page, pagesActions } from '$app_reducers/pages/slice';
-
-export function useLoadWorkspaces() {
-  const dispatch = useAppDispatch();
-  const { workspaces, currentWorkspace } = useAppSelector((state) => state.workspace);
-
-  const onWorkspacesChanged = useCallback(
-    (data: { workspaces: WorkspaceItem[]; currentWorkspace: WorkspaceItem }) => {
-      dispatch(workspaceActions.onWorkspacesChanged(data));
-    },
-    [dispatch]
-  );
-
-  const controller = useMemo(() => {
-    return new WorkspaceManagerController();
-  }, []);
-
-  const initializeWorkspaces = useCallback(async () => {
-    const workspaces = await controller.getWorkspaces();
-    const currentWorkspace = await controller.getCurrentWorkspace();
-
-    dispatch(
-      workspaceActions.initWorkspaces({
-        workspaces,
-        currentWorkspace,
-      })
-    );
-  }, [controller, dispatch]);
-
-  const subscribeToWorkspaces = useCallback(async () => {
-    await controller.subscribe({
-      onWorkspacesChanged,
-    });
-  }, [controller, onWorkspacesChanged]);
-
-  useEffect(() => {
-    void (async () => {
-      await initializeWorkspaces();
-      await subscribeToWorkspaces();
-    })();
-
-    return () => {
-      void controller.dispose();
-    };
-  }, [controller, initializeWorkspaces, subscribeToWorkspaces]);
-
-  return {
-    workspaces,
-    currentWorkspace,
-  };
-}
-
-export function useLoadWorkspace(workspace: WorkspaceItem) {
-  const { id } = workspace;
-  const dispatch = useAppDispatch();
-
-  const controller = useMemo(() => {
-    return new WorkspaceController(id);
-  }, [id]);
-
-  const openWorkspace = useCallback(async () => {
-    await controller.open();
-  }, [controller]);
-
-  const deleteWorkspace = useCallback(async () => {
-    await controller.delete();
-  }, [controller]);
-
-  const onChildPagesChanged = useCallback(
-    (childPages: Page[]) => {
-      dispatch(
-        pagesActions.addChildPages({
-          id,
-          childPages,
-        })
-      );
-    },
-    [dispatch, id]
-  );
-
-  const initializeWorkspace = useCallback(async () => {
-    const childPages = await controller.getChildPages();
-
-    dispatch(
-      pagesActions.addChildPages({
-        id,
-        childPages,
-      })
-    );
-  }, [controller, dispatch, id]);
-
-  const subscribeToWorkspace = useCallback(async () => {
-    await controller.subscribe({
-      onChildPagesChanged,
-    });
-  }, [controller, onChildPagesChanged]);
-
-  useEffect(() => {
-    void (async () => {
-      await initializeWorkspace();
-      await subscribeToWorkspace();
-    })();
-
-    return () => {
-      void controller.dispose();
-    };
-  }, [controller, initializeWorkspace, subscribeToWorkspace]);
-
-  return {
-    openWorkspace,
-    controller,
-    deleteWorkspace,
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Breadcrumb/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/BreadCrumb.tsx
similarity index 93%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/Breadcrumb/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/BreadCrumb.tsx
index 0b7a688e38..5ef81d2e17 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Breadcrumb/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/BreadCrumb.tsx
@@ -1,5 +1,5 @@
 import React, { useCallback, useMemo } from 'react';
-import { useLoadExpandedPages } from '$app/components/layout/Breadcrumb/Breadcrumb.hooks';
+import { useLoadExpandedPages } from '$app/components/layout/bread_crumb/Breadcrumb.hooks';
 import Breadcrumbs from '@mui/material/Breadcrumbs';
 import Link from '@mui/material/Link';
 import Typography from '@mui/material/Typography';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Breadcrumb/Breadcrumb.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/Breadcrumb.hooks.ts
similarity index 91%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/Breadcrumb/Breadcrumb.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/Breadcrumb.hooks.ts
index 82d7854a3a..ed10c5b7b9 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Breadcrumb/Breadcrumb.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/Breadcrumb.hooks.ts
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
 import { useParams, useLocation } from 'react-router-dom';
 import { Page } from '$app_reducers/pages/slice';
 import { useTranslation } from 'react-i18next';
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
+import { getPage } from '$app/application/folder/page.service';
 
 export function useLoadExpandedPages() {
   const { t } = useTranslation();
@@ -26,11 +26,10 @@ export function useLoadExpandedPages() {
   const loadPagePath = useCallback(
     async (pageId: string) => {
       let page = pageMap[pageId];
-      const controller = new PageController(pageId);
 
       if (!page) {
         try {
-          page = await controller.getPage();
+          page = await getPage(pageId);
         } catch (e) {
           // do nothing
         }
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/CollapseMenuButton/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/collapse_menu_button/CollapseMenuButton.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/CollapseMenuButton/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/collapse_menu_button/CollapseMenuButton.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/AddButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/AddButton.tsx
similarity index 79%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/AddButton.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/AddButton.tsx
index 80c4bfed07..266775515c 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/AddButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/AddButton.tsx
@@ -1,11 +1,10 @@
 import React, { useMemo } from 'react';
-import ButtonPopoverList from '$app/components/_shared/ButtonPopoverList';
+import ButtonPopoverList from '$app/components/_shared/button_menu/ButtonMenu';
 import { IconButton } from '@mui/material';
 import { ReactComponent as AddSvg } from '$app/assets/add.svg';
 import { useTranslation } from 'react-i18next';
 import { ReactComponent as DocumentSvg } from '$app/assets/document.svg';
 import { ReactComponent as GridSvg } from '$app/assets/grid.svg';
-import { ReactComponent as BoardSvg } from '$app/assets/board.svg';
 import { ViewLayoutPB } from '@/services/backend';
 
 function AddButton({ isVisible, onAddPage }: { isVisible: boolean; onAddPage: (layout: ViewLayoutPB) => void }) {
@@ -36,18 +35,6 @@ function AddButton({ isVisible, onAddPage }: { isVisible: boolean; onAddPage: (l
           onAddPage(ViewLayoutPB.Grid);
         },
       },
-      {
-        key: 'add-board',
-        label: t('board.menuName'),
-        icon: (
-          <div className={'h-5 w-5'}>
-            <BoardSvg />
-          </div>
-        ),
-        onClick: () => {
-          onAddPage(ViewLayoutPB.Board);
-        },
-      },
     ],
     [onAddPage, t]
   );
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/DeleteDialog.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/DeleteDialog.tsx
similarity index 86%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/DeleteDialog.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/DeleteDialog.tsx
index 85697b4bdf..83ed658ac1 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/DeleteDialog.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/DeleteDialog.tsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import { useTranslation } from 'react-i18next';
 import { ViewLayoutPB } from '@/services/backend';
-import ConfirmDialog from '$app/components/_shared/app-dialog/ConfirmDialog';
+import DeleteConfirmDialog from '$app/components/_shared/delete_confirm_dialog/DeleteConfirmDialog';
 
 function DeleteDialog({
   layout,
@@ -24,7 +24,7 @@ function DeleteDialog({
   }[layout];
 
   return (
-    <ConfirmDialog
+    <DeleteConfirmDialog
       open={open}
       title={t('views.deleteContentTitle', {
         pageType,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/MoreButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/MoreButton.tsx
similarity index 94%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/MoreButton.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/MoreButton.tsx
index c12d1eea36..92bb254bd3 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/MoreButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/MoreButton.tsx
@@ -1,7 +1,7 @@
 import React, { useMemo, useState } from 'react';
 import { useTranslation } from 'react-i18next';
 import { IconButton } from '@mui/material';
-import ButtonPopoverList from '../../_shared/ButtonPopoverList';
+import ButtonPopoverList from '$app/components/_shared/button_menu/ButtonMenu';
 
 import { ReactComponent as DetailsSvg } from '$app/assets/details.svg';
 import { ReactComponent as EditSvg } from '$app/assets/edit.svg';
@@ -10,7 +10,7 @@ import { ReactComponent as TrashSvg } from '$app/assets/delete.svg';
 
 import RenameDialog from './RenameDialog';
 import { Page } from '$app_reducers/pages/slice';
-import DeleteDialog from '$app/components/layout/NestedPage/DeleteDialog';
+import DeleteDialog from '$app/components/layout/nested_page/DeleteDialog';
 
 function MoreButton({
   isVisible,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/NestedPage.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPage.hooks.ts
similarity index 66%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/NestedPage.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPage.hooks.ts
index f754fa8416..1081fc2cd1 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/NestedPage.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPage.hooks.ts
@@ -1,10 +1,11 @@
-import { useCallback, useEffect, useMemo } from 'react';
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
-import { Page, pagesActions, pageTypeMap } from '$app_reducers/pages/slice';
+import { useCallback, useEffect } from 'react';
+import { Page, pagesActions, pageTypeMap, parserViewPBToPage } from '$app_reducers/pages/slice';
 import { useAppDispatch, useAppSelector } from '$app/stores/store';
-import { ViewLayoutPB } from '@/services/backend';
+import { FolderNotification, ViewLayoutPB } from '@/services/backend';
 import { useNavigate, useParams } from 'react-router-dom';
 import { updatePageName } from '$app_reducers/pages/async_actions';
+import { createPage, deletePage, duplicatePage, getChildPages } from '$app/application/folder/page.service';
+import { subscribeNotifications } from '$app/application/notification';
 
 export function useLoadChildPages(pageId: string) {
   const dispatch = useAppDispatch();
@@ -18,26 +19,16 @@ export function useLoadChildPages(pageId: string) {
     }
   }, [dispatch, pageId, collapsed]);
 
-  const controller = useMemo(() => {
-    return new PageController(pageId);
-  }, [pageId]);
-
   const onPageChanged = useCallback(
-    (page: Page, children: Page[]) => {
+    (page: Page) => {
       dispatch(pagesActions.onPageChanged(page));
-      dispatch(
-        pagesActions.addChildPages({
-          id: page.id,
-          childPages: children,
-        })
-      );
     },
     [dispatch]
   );
 
   const loadPageChildren = useCallback(
     async (pageId: string) => {
-      const childPages = await controller.getChildPages();
+      const childPages = await getChildPages(pageId);
 
       dispatch(
         pagesActions.addChildPages({
@@ -46,7 +37,7 @@ export function useLoadChildPages(pageId: string) {
         })
       );
     },
-    [controller, dispatch]
+    [dispatch]
   );
 
   useEffect(() => {
@@ -54,13 +45,24 @@ export function useLoadChildPages(pageId: string) {
   }, [loadPageChildren, pageId]);
 
   useEffect(() => {
-    void controller.subscribe({
-      onPageChanged,
-    });
-    return () => {
-      void controller.dispose();
-    };
-  }, [controller, onPageChanged]);
+    const unsubscribePromise = subscribeNotifications(
+      {
+        [FolderNotification.DidUpdateView]: async (payload) => {
+          const page = parserViewPBToPage(payload);
+
+          onPageChanged(page);
+        },
+        [FolderNotification.DidUpdateChildViews]: async () => {
+          void loadPageChildren(pageId);
+        },
+      },
+      {
+        id: pageId,
+      }
+    );
+
+    return () => void unsubscribePromise.then((unsubscribe) => unsubscribe());
+  }, [pageId, onPageChanged, loadPageChildren]);
 
   return {
     toggleCollapsed,
@@ -73,9 +75,6 @@ export function usePageActions(pageId: string) {
   const page = useAppSelector((state) => state.pages.pageMap[pageId]);
   const dispatch = useAppDispatch();
   const navigate = useNavigate();
-  const controller = useMemo(() => {
-    return new PageController(pageId);
-  }, [pageId]);
 
   const onPageClick = useCallback(() => {
     const pageType = pageTypeMap[page.layout];
@@ -85,9 +84,10 @@ export function usePageActions(pageId: string) {
 
   const onAddPage = useCallback(
     async (layout: ViewLayoutPB) => {
-      const newViewId = await controller.createPage({
+      const newViewId = await createPage({
         layout,
         name: '',
+        parent_view_id: pageId,
       });
 
       dispatch(pagesActions.expandPage(pageId));
@@ -95,16 +95,16 @@ export function usePageActions(pageId: string) {
 
       navigate(`/page/${pageType}/${newViewId}`);
     },
-    [controller, dispatch, navigate, pageId]
+    [dispatch, navigate, pageId]
   );
 
   const onDeletePage = useCallback(async () => {
-    await controller.deletePage();
-  }, [controller]);
+    await deletePage(pageId);
+  }, [pageId]);
 
   const onDuplicatePage = useCallback(async () => {
-    await controller.duplicatePage();
-  }, [controller]);
+    await duplicatePage(pageId);
+  }, [pageId]);
 
   const onRenamePage = useCallback(
     async (name: string) => {
@@ -113,12 +113,6 @@ export function usePageActions(pageId: string) {
     [dispatch, pageId]
   );
 
-  useEffect(() => {
-    return () => {
-      void controller.dispose();
-    };
-  }, [controller]);
-
   return {
     onAddPage,
     onPageClick,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPage.tsx
similarity index 93%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPage.tsx
index dc7906d63c..54e283e878 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPage.tsx
@@ -1,9 +1,9 @@
 import React, { useCallback, useMemo } from 'react';
 import Collapse from '@mui/material/Collapse';
 import { TransitionGroup } from 'react-transition-group';
-import NestedPageTitle from '$app/components/layout/NestedPage/NestedPageTitle';
-import { useLoadChildPages, usePageActions } from '$app/components/layout/NestedPage/NestedPage.hooks';
-import { useDrag } from '$app/components/_shared/drag-block';
+import NestedPageTitle from '$app/components/layout/nested_page/NestedPageTitle';
+import { useLoadChildPages, usePageActions } from '$app/components/layout/nested_page/NestedPage.hooks';
+import { useDrag } from 'src/appflowy_app/components/_shared/drag_block';
 import { useAppDispatch } from '$app/stores/store';
 import { movePageThunk } from '$app_reducers/pages/async_actions';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/NestedPageTitle.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPageTitle.tsx
similarity index 96%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/NestedPageTitle.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPageTitle.tsx
index 98de2e167d..5b33d8a157 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/NestedPageTitle.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/NestedPageTitle.tsx
@@ -4,7 +4,7 @@ import { useAppSelector } from '$app/stores/store';
 import AddButton from './AddButton';
 import MoreButton from './MoreButton';
 import { ViewLayoutPB } from '@/services/backend';
-import { useSelectedPage } from '$app/components/layout/NestedPage/NestedPage.hooks';
+import { useSelectedPage } from '$app/components/layout/nested_page/NestedPage.hooks';
 import { useTranslation } from 'react-i18next';
 
 function NestedPageTitle({
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/RenameDialog.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/RenameDialog.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/NestedPage/RenameDialog.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/nested_page/RenameDialog.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Share/Share.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/share/Share.hooks.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/Share/Share.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/share/Share.hooks.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Share/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/share/Share.tsx
similarity index 85%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/Share/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/share/Share.tsx
index eb97cc96b0..1a10cb08e6 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Share/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/share/Share.tsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import { useTranslation } from 'react-i18next';
 import Button from '@mui/material/Button';
-import { useShareConfig } from '$app/components/layout/Share/Share.hooks';
+import { useShareConfig } from '$app/components/layout/share/Share.hooks';
 
 function ShareButton() {
   const { showShareButton } = useShareConfig();
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/Resizer.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/Resizer.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/Resizer.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/Resizer.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/SideBar.tsx
similarity index 81%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/SideBar.tsx
index 4b525da21d..cfde67bde6 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/SideBar.tsx
@@ -3,10 +3,10 @@ import { useAppSelector } from '$app/stores/store';
 import { ThemeMode } from '$app/stores/reducers/current-user/slice';
 import { AppflowyLogoDark } from '$app/components/_shared/svg/AppflowyLogoDark';
 import { AppflowyLogoLight } from '$app/components/_shared/svg/AppflowyLogoLight';
-import CollapseMenuButton from '$app/components/layout/CollapseMenuButton';
-import Resizer from '$app/components/layout/SideBar/Resizer';
-import UserInfo from '$app/components/layout/SideBar/UserInfo';
-import WorkspaceManager from '$app/components/layout/WorkspaceManager';
+import CollapseMenuButton from '$app/components/layout/collapse_menu_button/CollapseMenuButton';
+import Resizer from '$app/components/layout/side_bar/Resizer';
+import UserInfo from '$app/components/layout/side_bar/UserInfo';
+import WorkspaceManager from '$app/components/layout/workspace_manager/WorkspaceManager';
 
 function SideBar() {
   const { isCollapsed, width, isResizing } = useAppSelector((state) => state.sidebar);
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/UserInfo.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/UserInfo.tsx
similarity index 95%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/UserInfo.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/UserInfo.tsx
index a4aaca150a..bde742f57a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/SideBar/UserInfo.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/UserInfo.tsx
@@ -3,7 +3,7 @@ import { useAppSelector } from '$app/stores/store';
 import { Avatar } from '@mui/material';
 import PersonOutline from '@mui/icons-material/PersonOutline';
 import ArrowDropDown from '@mui/icons-material/ArrowDropDown';
-import UserSetting from '../UserSetting';
+import UserSetting from '../user_setting/UserSetting';
 
 function UserInfo() {
   const currentUser = useAppSelector((state) => state.currentUser);
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/FontSizeConfig.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/FontSizeConfig.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/FontSizeConfig.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/FontSizeConfig.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreButton.tsx
similarity index 85%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreButton.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreButton.tsx
index ca104218ab..1ffae1eb85 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreButton.tsx
@@ -3,8 +3,8 @@ import { useTranslation } from 'react-i18next';
 import { Drawer, IconButton } from '@mui/material';
 import { Details2Svg } from '$app/components/_shared/svg/Details2Svg';
 import Tooltip from '@mui/material/Tooltip';
-import MoreOptions from '$app/components/layout/TopBar/MoreOptions';
-import { useMoreOptionsConfig } from '$app/components/layout/TopBar/MoreOptions.hooks';
+import MoreOptions from '$app/components/layout/top_bar/MoreOptions';
+import { useMoreOptionsConfig } from '$app/components/layout/top_bar/MoreOptions.hooks';
 
 function MoreButton() {
   const { t } = useTranslation();
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreOptions.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreOptions.hooks.ts
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreOptions.hooks.ts
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreOptions.hooks.ts
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreOptions.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreOptions.tsx
similarity index 59%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreOptions.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreOptions.tsx
index 28f2b46759..7f77259212 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/MoreOptions.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/MoreOptions.tsx
@@ -1,6 +1,6 @@
 import React from 'react';
-import FontSizeConfig from '$app/components/layout/TopBar/FontSizeConfig';
-import { useMoreOptionsConfig } from '$app/components/layout/TopBar/MoreOptions.hooks';
+import FontSizeConfig from '$app/components/layout/top_bar/FontSizeConfig';
+import { useMoreOptionsConfig } from '$app/components/layout/top_bar/MoreOptions.hooks';
 
 function MoreOptions() {
   const { showStyleOptions } = useMoreOptionsConfig();
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/TopBar.tsx
similarity index 72%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/TopBar.tsx
index d3d99a2fd5..178c596f6b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/TopBar/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/TopBar.tsx
@@ -1,9 +1,9 @@
 import React from 'react';
-import CollapseMenuButton from '$app/components/layout/CollapseMenuButton';
+import CollapseMenuButton from '$app/components/layout/collapse_menu_button/CollapseMenuButton';
 import { useAppSelector } from '$app/stores/store';
-import Breadcrumb from '$app/components/layout/Breadcrumb';
-import ShareButton from '$app/components/layout/Share';
-import MoreButton from '$app/components/layout/TopBar/MoreButton';
+import Breadcrumb from '$app/components/layout/bread_crumb/BreadCrumb';
+import ShareButton from '$app/components/layout/share/Share';
+import MoreButton from '$app/components/layout/top_bar/MoreButton';
 
 function TopBar() {
   const sidebarIsCollapsed = useAppSelector((state) => state.sidebar.isCollapsed);
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/AppearanceSetting.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/AppearanceSetting.tsx
similarity index 82%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/AppearanceSetting.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/AppearanceSetting.tsx
index cf69f1c426..e2d0367a51 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/AppearanceSetting.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/AppearanceSetting.tsx
@@ -36,24 +36,6 @@ function AppearanceSetting({
     [t]
   );
 
-  const themeOptions = useMemo(
-    () => [
-      {
-        value: Theme.Default,
-        content: 'Default',
-      },
-      {
-        value: Theme.Dandelion,
-        content: 'Dandelion',
-      },
-      {
-        value: Theme.Lavender,
-        content: 'Lavender',
-      },
-    ],
-    []
-  );
-
   const renderSelect = useCallback(
     (
       items: {
@@ -107,16 +89,6 @@ function AppearanceSetting({
             });
           },
         },
-        {
-          options: themeOptions,
-          label: t('settings.appearance.theme'),
-          value: theme,
-          onChange: (newValue) => {
-            onChange({
-              theme: newValue as Theme,
-            });
-          },
-        },
       ])}
     </div>
   );
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/LanguageSetting.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/LanguageSetting.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/LanguageSetting.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/LanguageSetting.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/Menu.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/Menu.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/Menu.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/Menu.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/SettingPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/SettingPanel.tsx
similarity index 100%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/SettingPanel.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/SettingPanel.tsx
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/UserSetting.tsx
similarity index 74%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/UserSetting.tsx
index 256f4e96ac..7fd52de56a 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/UserSetting/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/user_setting/UserSetting.tsx
@@ -8,9 +8,9 @@ import UserSettingPanel from './SettingPanel';
 import { Theme, UserSetting } from '$app/stores/reducers/current-user/slice';
 import { useAppDispatch, useAppSelector } from '$app/stores/store';
 import { currentUserActions } from '$app_reducers/current-user/slice';
-import { useUserSettingControllerContext } from '$app/components/_shared/app-hooks/useUserSettingControllerContext';
 import { ThemeModePB } from '@/services/backend';
 import { useTranslation } from 'react-i18next';
+import { UserService } from '$app/application/user/user.service';
 
 const SlideTransition = React.forwardRef((props: SlideProps, ref) => {
   return <Slide {...props} direction='up' ref={ref} />;
@@ -19,7 +19,6 @@ const SlideTransition = React.forwardRef((props: SlideProps, ref) => {
 function UserSettings({ open, onClose }: { open: boolean; onClose: () => void }) {
   const userSettingState = useAppSelector((state) => state.currentUser.userSetting);
   const dispatch = useAppDispatch();
-  const userSettingController = useUserSettingControllerContext();
   const { t } = useTranslation();
   const [selected, setSelected] = useState<MenuItem>(MenuItem.Appearance);
   const handleChange = useCallback(
@@ -27,20 +26,18 @@ function UserSettings({ open, onClose }: { open: boolean; onClose: () => void })
       const newSetting = { ...userSettingState, ...setting };
 
       dispatch(currentUserActions.setUserSetting(newSetting));
-      if (userSettingController) {
-        const language = newSetting.language || 'en';
+      const language = newSetting.language || 'en';
 
-        void userSettingController.setAppearanceSetting({
-          theme: newSetting.theme || Theme.Default,
-          theme_mode: newSetting.themeMode || ThemeModePB.Light,
-          locale: {
-            language_code: language.split('-')[0],
-            country_code: language.split('-')[1],
-          },
-        });
-      }
+      void UserService.setAppearanceSetting({
+        theme: newSetting.theme || Theme.Default,
+        theme_mode: newSetting.themeMode || ThemeModePB.Light,
+        locale: {
+          language_code: language.split('-')[0],
+          country_code: language.split('-')[1],
+        },
+      });
     },
-    [dispatch, userSettingController, userSettingState]
+    [dispatch, userSettingState]
   );
 
   return (
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/MoreButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/MoreButton.tsx
similarity index 94%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/MoreButton.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/MoreButton.tsx
index e22818eeb2..efdd8d1144 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/MoreButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/MoreButton.tsx
@@ -5,7 +5,7 @@ import MoreIcon from '@mui/icons-material/MoreHoriz';
 import SettingsIcon from '@mui/icons-material/Settings';
 import { useTranslation } from 'react-i18next';
 import { DeleteOutline } from '@mui/icons-material';
-import ButtonPopoverList from '$app/components/_shared/ButtonPopoverList';
+import ButtonPopoverList from '$app/components/_shared/button_menu/ButtonMenu';
 
 function MoreButton({
   workspace,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/NestedPages.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/NestedPages.tsx
similarity index 86%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/NestedPages.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/NestedPages.tsx
index dea679c0f6..80d61440b7 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/NestedPages.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/NestedPages.tsx
@@ -1,6 +1,6 @@
 import React from 'react';
 import { useAppSelector } from '$app/stores/store';
-import NestedPage from '$app/components/layout/NestedPage';
+import NestedPage from '$app/components/layout/nested_page/NestedPage';
 
 function WorkspaceNestedPages({ workspaceId }: { workspaceId: string }) {
   const pageIds = useAppSelector((state) => {
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/NewPageButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/NewPageButton.tsx
similarity index 72%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/NewPageButton.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/NewPageButton.tsx
index ad405024a1..f82cb2208e 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/NewPageButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/NewPageButton.tsx
@@ -1,26 +1,19 @@
-import React, { useEffect, useMemo } from 'react';
+import React from 'react';
 import AddSvg from '$app/components/_shared/svg/AddSvg';
 import { useTranslation } from 'react-i18next';
-import { WorkspaceController } from '$app/stores/effects/workspace/workspace_controller';
 import { ViewLayoutPB } from '@/services/backend';
 import { useNavigate } from 'react-router-dom';
+import { createCurrentWorkspaceChildView } from '$app/application/folder/workspace.service';
 
 function NewPageButton({ workspaceId }: { workspaceId: string }) {
   const { t } = useTranslation();
-  const controller = useMemo(() => new WorkspaceController(workspaceId), [workspaceId]);
   const navigate = useNavigate();
 
-  useEffect(() => {
-    return () => {
-      void controller.dispose();
-    };
-  }, [controller]);
-
   return (
     <div className={'flex h-[60px] w-full items-center border-t border-line-divider px-6 py-5'}>
       <button
         onClick={async () => {
-          const { id } = await controller.createView({
+          const { id } = await createCurrentWorkspaceChildView({
             name: '',
             layout: ViewLayoutPB.Document,
             parent_view_id: workspaceId,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/TrashButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/TrashButton.tsx
similarity index 83%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/TrashButton.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/TrashButton.tsx
index 11d085fb53..944c23df01 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/TrashButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/TrashButton.tsx
@@ -2,8 +2,8 @@ import React, { useCallback } from 'react';
 import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
 import { useTranslation } from 'react-i18next';
 import { useLocation, useNavigate } from 'react-router-dom';
-import { useDrag } from '$app/components/_shared/drag-block';
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
+import { useDrag } from 'src/appflowy_app/components/_shared/drag_block';
+import { deletePage } from '$app/application/folder/page.service';
 
 function TrashButton() {
   const { t } = useTranslation();
@@ -16,9 +16,7 @@ function TrashButton() {
   const selected = currentPathType === 'trash';
 
   const onEnd = useCallback((result: { dragId: string; position: 'before' | 'after' | 'inside' }) => {
-    const controller = new PageController(result.dragId);
-
-    void controller.deletePage();
+    void deletePage(result.dragId);
   }, []);
 
   const { onDrop, onDragOver, onDragLeave, isDraggingOver } = useDrag({
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.hooks.ts
new file mode 100644
index 0000000000..2b5ac678e8
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.hooks.ts
@@ -0,0 +1,97 @@
+import { useCallback, useEffect } from 'react';
+import { useAppDispatch, useAppSelector } from '$app/stores/store';
+import { workspaceActions, WorkspaceItem } from '$app_reducers/workspace/slice';
+import { Page, pagesActions, parserViewPBToPage } from '$app_reducers/pages/slice';
+import { subscribeNotifications } from '$app/application/notification';
+import { FolderNotification } from '@/services/backend';
+import * as workspaceService from '$app/application/folder/workspace.service';
+
+export function useLoadWorkspaces() {
+  const dispatch = useAppDispatch();
+  const { workspaces, currentWorkspace } = useAppSelector((state) => state.workspace);
+
+  const initializeWorkspaces = useCallback(async () => {
+    const workspaces = await workspaceService.getWorkspaces();
+    const currentWorkspace = await workspaceService.getCurrentWorkspace();
+
+    dispatch(
+      workspaceActions.initWorkspaces({
+        workspaces,
+        currentWorkspace,
+      })
+    );
+  }, [dispatch]);
+
+  useEffect(() => {
+    void (async () => {
+      await initializeWorkspaces();
+    })();
+  }, [initializeWorkspaces]);
+
+  return {
+    workspaces,
+    currentWorkspace,
+  };
+}
+
+export function useLoadWorkspace(workspace: WorkspaceItem) {
+  const { id } = workspace;
+  const dispatch = useAppDispatch();
+
+  const openWorkspace = useCallback(async () => {
+    await workspaceService.openWorkspace(id);
+  }, [id]);
+
+  const deleteWorkspace = useCallback(async () => {
+    await workspaceService.deleteWorkspace(id);
+  }, [id]);
+
+  const onChildPagesChanged = useCallback(
+    (childPages: Page[]) => {
+      dispatch(
+        pagesActions.addChildPages({
+          id,
+          childPages,
+        })
+      );
+    },
+    [dispatch, id]
+  );
+
+  const initializeWorkspace = useCallback(async () => {
+    const childPages = await workspaceService.getWorkspaceChildViews(id);
+
+    dispatch(
+      pagesActions.addChildPages({
+        id,
+        childPages,
+      })
+    );
+  }, [dispatch, id]);
+
+  useEffect(() => {
+    void (async () => {
+      await initializeWorkspace();
+    })();
+  }, [initializeWorkspace]);
+
+  useEffect(() => {
+    const unsubscribePromise = subscribeNotifications(
+      {
+        [FolderNotification.DidUpdateWorkspaceViews]: async (changeset) => {
+          const res = changeset.items;
+
+          onChildPagesChanged(res.map(parserViewPBToPage));
+        },
+      },
+      { id }
+    );
+
+    return () => void unsubscribePromise.then((unsubscribe) => unsubscribe());
+  }, [id, onChildPagesChanged]);
+
+  return {
+    openWorkspace,
+    deleteWorkspace,
+  };
+}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/Workspace.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.tsx
similarity index 74%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/Workspace.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.tsx
index 97453c4ccc..db9ce8f4b1 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/Workspace.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.tsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import { WorkspaceItem } from '$app_reducers/workspace/slice';
-import NestedViews from '$app/components/layout/WorkspaceManager/NestedPages';
-import { useLoadWorkspace } from '$app/components/layout/WorkspaceManager/Workspace.hooks';
+import NestedViews from '$app/components/layout/workspace_manager/NestedPages';
+import { useLoadWorkspace } from '$app/components/layout/workspace_manager/Workspace.hooks';
 
 function Workspace({ workspace, opened }: { workspace: WorkspaceItem; opened: boolean }) {
   useLoadWorkspace(workspace);
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/index.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/WorkspaceManager.tsx
similarity index 75%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/index.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/WorkspaceManager.tsx
index 945c3d2d40..a7a90e785f 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/index.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/WorkspaceManager.tsx
@@ -1,8 +1,8 @@
 import React from 'react';
-import NewPageButton from '$app/components/layout/WorkspaceManager/NewPageButton';
-import { useLoadWorkspaces } from '$app/components/layout/WorkspaceManager/Workspace.hooks';
+import NewPageButton from '$app/components/layout/workspace_manager/NewPageButton';
+import { useLoadWorkspaces } from '$app/components/layout/workspace_manager/Workspace.hooks';
 import Workspace from './Workspace';
-import TrashButton from '$app/components/layout/WorkspaceManager/TrashButton';
+import TrashButton from '$app/components/layout/workspace_manager/TrashButton';
 
 function WorkspaceManager() {
   const { workspaces, currentWorkspace } = useLoadWorkspaces();
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/WorkspaceTitle.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/WorkspaceTitle.tsx
similarity index 92%
rename from frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/WorkspaceTitle.tsx
rename to frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/WorkspaceTitle.tsx
index 9a256035fe..4c9f8988a6 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/WorkspaceManager/WorkspaceTitle.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/WorkspaceTitle.tsx
@@ -1,5 +1,5 @@
 import React, { useState } from 'react';
-import MoreButton from '$app/components/layout/WorkspaceManager/MoreButton';
+import MoreButton from '$app/components/layout/workspace_manager/MoreButton';
 import MenuItem from '@mui/material/MenuItem';
 import { WorkspaceItem } from '$app_reducers/workspace/slice';
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/AllIcons.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/AllIcons.tsx
deleted file mode 100644
index 3f3acfbb35..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/AllIcons.tsx
+++ /dev/null
@@ -1,204 +0,0 @@
-import AddSvg from '$app/components/_shared/svg/AddSvg';
-import { ArrowLeftSvg } from '$app/components/_shared/svg/ArrowLeftSvg';
-import { ArrowRightSvg } from '$app/components/_shared/svg/ArrowRightSvg';
-import { BoardSvg } from '$app/components/_shared/svg/BoardSvg';
-import { CheckboxSvg } from '$app/components/_shared/svg/CheckboxSvg';
-import { ChecklistTypeSvg } from '$app/components/_shared/svg/ChecklistTypeSvg';
-import { CheckmarkSvg } from '$app/components/_shared/svg/CheckmarkSvg';
-import { ClockSvg } from '$app/components/_shared/svg/ClockSvg';
-import { CloseSvg } from '$app/components/_shared/svg/CloseSvg';
-import { CopySvg } from '$app/components/_shared/svg/CopySvg';
-import { DateTypeSvg } from '$app/components/_shared/svg/DateTypeSvg';
-import { Details2Svg } from '$app/components/_shared/svg/Details2Svg';
-import { DocumentSvg } from '$app/components/_shared/svg/DocumentSvg';
-import { DropDownShowSvg } from '$app/components/_shared/svg/DropDownShowSvg';
-import { EarthSvg } from '$app/components/_shared/svg/EarthSvg';
-import { EditorCheckSvg } from '$app/components/_shared/svg/EditorCheckSvg';
-import { EditorUncheckSvg } from '$app/components/_shared/svg/EditorUncheckSvg';
-import { EditSvg } from '$app/components/_shared/svg/EditSvg';
-import { EyeClosedSvg } from '$app/components/_shared/svg/EyeClosedSvg';
-import { EyeOpenSvg } from '$app/components/_shared/svg/EyeOpenSvg';
-import { FilterSvg } from '$app/components/_shared/svg/FilterSvg';
-import { GridSvg } from '$app/components/_shared/svg/GridSvg';
-import { GroupByFieldSvg } from '$app/components/_shared/svg/GroupByFieldSvg';
-import { HideMenuSvg } from '$app/components/_shared/svg/HideMenuSvg';
-import { InformationSvg } from '$app/components/_shared/svg/InformationSvg';
-import { LogoutSvg } from '$app/components/_shared/svg/LogoutSvg';
-import { MoreSvg } from '$app/components/_shared/svg/MoreSvg';
-import { MultiSelectTypeSvg } from '$app/components/_shared/svg/MultiSelectTypeSvg';
-import { NumberTypeSvg } from '$app/components/_shared/svg/NumberTypeSvg';
-import { PropertiesSvg } from '$app/components/_shared/svg/PropertiesSvg';
-import { SearchSvg } from '$app/components/_shared/svg/SearchSvg';
-import { ShowMenuSvg } from '$app/components/_shared/svg/ShowMenuSvg';
-import { SingleSelectTypeSvg } from '$app/components/_shared/svg/SingleSelectTypeSvg';
-import { SkipLeftSvg } from '$app/components/_shared/svg/SkipLeftSvg';
-import { SkipRightSvg } from '$app/components/_shared/svg/SkipRightSvg';
-import { SortSvg } from '$app/components/_shared/svg/SortSvg';
-import { TextTypeSvg } from '$app/components/_shared/svg/TextTypeSvg';
-import { TrashSvg } from '$app/components/_shared/svg/TrashSvg';
-import { UrlTypeSvg } from '$app/components/_shared/svg/UrlTypeSvg';
-import { DragElementSvg } from '$app/components/_shared/svg/DragElementSvg';
-import { ImageSvg } from '$app/components/_shared/svg/ImageSvg';
-import { DragSvg } from '$app/components/_shared/svg/DragSvg';
-import { FullView } from '$app/components/_shared/svg/FullView';
-import { GroupBySvg } from '$app/components/_shared/svg/GroupBySvg';
-import { SettingsSvg } from '$app/components/_shared/svg/SettingsSvg';
-import { ShareSvg } from '$app/components/_shared/svg/ShareSvg';
-import { SortAscSvg } from '$app/components/_shared/svg/SortAscSvg';
-import { SortDescSvg } from '$app/components/_shared/svg/SortDescSvg';
-
-export const AllIcons = () => {
-  return (
-    <div className={'p-8'}>
-      <h1 className={'mb-12 text-2xl'}>Icons</h1>
-      <div className={'mb-8'}>
-        <div className={'flex flex-wrap items-center gap-8'}>
-          <i className={'h-5 w-5'} title={'AddSvg'}>
-            <AddSvg></AddSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'ArrowLeftSvg'}>
-            <ArrowLeftSvg></ArrowLeftSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'ArrowRightSvg'}>
-            <ArrowRightSvg></ArrowRightSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'BoardSvg'}>
-            <BoardSvg></BoardSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'CheckboxSvg'}>
-            <CheckboxSvg></CheckboxSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'ChecklistTypeSvg'}>
-            <ChecklistTypeSvg></ChecklistTypeSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'CheckmarkSvg'}>
-            <CheckmarkSvg></CheckmarkSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'ClockSvg'}>
-            <ClockSvg></ClockSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'CloseSvg'}>
-            <CloseSvg></CloseSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'CopySvg'}>
-            <CopySvg></CopySvg>
-          </i>
-          <i className={'h-5 w-5'} title={'DateTypeSvg'}>
-            <DateTypeSvg></DateTypeSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'Details2Svg'}>
-            <Details2Svg></Details2Svg>
-          </i>
-          <i className={'h-5 w-5'} title={'DocumentSvg'}>
-            <DocumentSvg></DocumentSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'DragElementSvg'}>
-            <DragElementSvg></DragElementSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'DragSvg'}>
-            <DragSvg></DragSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'DropDownShowSvg'}>
-            <DropDownShowSvg></DropDownShowSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'EarthSvg'}>
-            <EarthSvg></EarthSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'EditorCheckSvg'}>
-            <EditorCheckSvg></EditorCheckSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'EditorUncheckSvg'}>
-            <EditorUncheckSvg></EditorUncheckSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'EditSvg'}>
-            <EditSvg></EditSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'EyeClosedSvg'}>
-            <EyeClosedSvg></EyeClosedSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'EyeOpenSvg'}>
-            <EyeOpenSvg></EyeOpenSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'FilterSvg'}>
-            <FilterSvg></FilterSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'FullView'}>
-            <FullView></FullView>
-          </i>
-          <i className={'h-5 w-5'} title={'GridSvg'}>
-            <GridSvg></GridSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'GroupByFieldSvg'}>
-            <GroupByFieldSvg></GroupByFieldSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'GroupBySvg'}>
-            <GroupBySvg></GroupBySvg>
-          </i>
-          <i className={'h-5 w-5'} title={'HideMenuSvg'}>
-            <HideMenuSvg></HideMenuSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'ImageSvg'}>
-            <ImageSvg></ImageSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'InformationSvg'}>
-            <InformationSvg></InformationSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'LogoutSvg'}>
-            <LogoutSvg></LogoutSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'MoreSvg'}>
-            <MoreSvg></MoreSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'MultiSelectTypeSvg'}>
-            <MultiSelectTypeSvg></MultiSelectTypeSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'NumberTypeSvg'}>
-            <NumberTypeSvg></NumberTypeSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'PropertiesSvg'}>
-            <PropertiesSvg></PropertiesSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SearchSvg'}>
-            <SearchSvg></SearchSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SettingsSvg'}>
-            <SettingsSvg></SettingsSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'ShareSvg'}>
-            <ShareSvg></ShareSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'ShowMenuSvg'}>
-            <ShowMenuSvg></ShowMenuSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SingleSelectTypeSvg'}>
-            <SingleSelectTypeSvg></SingleSelectTypeSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SkipLeftSvg'}>
-            <SkipLeftSvg></SkipLeftSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SkipRightSvg'}>
-            <SkipRightSvg></SkipRightSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SortAscSvg'}>
-            <SortAscSvg></SortAscSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SortDescSvg'}>
-            <SortDescSvg></SortDescSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'SortSvg'}>
-            <SortSvg></SortSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'TextTypeSvg'}>
-            <TextTypeSvg></TextTypeSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'TrashSvg'}>
-            <TrashSvg></TrashSvg>
-          </i>
-          <i className={'h-5 w-5'} title={'UrlTypeSvg'}>
-            <UrlTypeSvg></UrlTypeSvg>
-          </i>
-        </div>
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/ColorPalette.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/ColorPalette.tsx
deleted file mode 100644
index 1a8e5dee95..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/ColorPalette.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-export const ColorPalette = () => {
-  return (
-    <div className={'p-8'}>
-      <h1 className={'mb-4 text-2xl'}>Colors</h1>
-      <h2 className={'mb-4'}>Main</h2>
-      <div className={'mb-8 flex flex-wrap items-center'}>
-        <div title={'fill-hover'} className={'m-2 h-[100px] w-[100px] bg-fill-default'}></div>
-        <div title={'main-hovered'} className={'m-2 h-[100px] w-[100px] bg-fill-list-hover'}></div>
-        <div title={'fill-list-hover'} className={'m-2 h-[100px] w-[100px] bg-fill-list-hover'}></div>
-        <div title={'main-selector'} className={'m-2 h-[100px] w-[100px] bg-fill-selector'}></div>
-        <div title={'main-alert'} className={'m-2 h-[100px] w-[100px] bg-function-info'}></div>
-        <div title={'main-warning'} className={'m-2 h-[100px] w-[100px] bg-function-warning'}></div>
-        <div title={'main-success'} className={'m-2 h-[100px] w-[100px] bg-function-success'}></div>
-      </div>
-      <h2 className={'mb-4'}>Tint</h2>
-      <div className={'mb-8 flex flex-wrap items-center text-text-title'}>
-        <div title={'tint-1'} className={'m-2 h-[100px] w-[100px] bg-tint-pink'}></div>
-        <div title={'tint-2'} className={'m-2 h-[100px] w-[100px] bg-tint-purple'}></div>
-        <div title={'tint-3'} className={'m-2 h-[100px] w-[100px] bg-tint-red'}></div>
-        <div title={'tint-4'} className={'m-2 h-[100px] w-[100px] bg-tint-green'}></div>
-        <div title={'tint-5'} className={'m-2 h-[100px] w-[100px] bg-tint-blue'}></div>
-        <div title={'tint-6'} className={'m-2 h-[100px] w-[100px] bg-tint-yellow'}></div>
-        <div title={'tint-7'} className={'m-2 h-[100px] w-[100px] bg-tint-aqua'}></div>
-        <div title={'tint-8'} className={'m-2 h-[100px] w-[100px] bg-tint-lime'}></div>
-        <div title={'tint-9'} className={'m-2 h-[100px] w-[100px] bg-tint-pink'}></div>
-      </div>
-      <h2 className={'mb-4'}>Shades</h2>
-      <div className={'mb-8 flex flex-wrap items-center'}>
-        <div title={'shade-1'} className={'bg-shade-1 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'shade-2'} className={'bg-shade-2 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'shade-3'} className={'bg-shade-3 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'shade-4'} className={'bg-shade-4 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'shade-5'} className={'bg-shade-5 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'line-divider'} className={'m-2 h-[100px] w-[100px] bg-line-divider'}></div>
-      </div>
-      <h2 className={'mb-4'}>Surface</h2>
-      <div className={'mb-8 flex flex-wrap items-center'}>
-        <div title={'surface-1'} className={'bg-surface-1 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'surface-2'} className={'bg-surface-2 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'surface-3'} className={'bg-surface-3 m-2 h-[100px] w-[100px]'}></div>
-        <div title={'surface-4'} className={'bg-surface-4 m-2 h-[100px] w-[100px]'}></div>
-      </div>
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts
deleted file mode 100644
index 4060051597..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-import { FieldType, SingleSelectTypeOptionPB, ViewLayoutPB, ViewPB, WorkspaceSettingPB } from '@/services/backend';
-import { DatabaseController } from '$app/stores/effects/database/database_controller';
-import { RowInfo } from '$app/stores/effects/database/row/row_cache';
-import { RowController } from '$app/stores/effects/database/row/row_controller';
-import {
-  CellControllerBuilder,
-  CheckboxCellController,
-  DateCellController,
-  SelectOptionCellController,
-  TextCellController,
-  URLCellController,
-} from '$app/stores/effects/database/cell/controller_builder';
-import { None, Option, Some } from 'ts-results';
-import { DatabaseBackendService } from '$app/stores/effects/database/database_bd_svc';
-import { FieldInfo } from '$app/stores/effects/database/field/field_controller';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { makeSingleSelectTypeOptionContext } from '$app/stores/effects/database/field/type_option/type_option_context';
-import { SelectOptionBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { WorkspaceController } from '$app/stores/effects/workspace/workspace_controller';
-import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder';
-
-// Create a database page for specific layout type
-// Do not use it production code. Just for testing
-export async function createTestDatabaseView(layout: ViewLayoutPB): Promise<ViewPB> {
-  const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspaceSetting().then((result) =>
-    result.unwrap()
-  );
-  const wsSvc = new WorkspaceController(workspaceSetting.workspace_id);
-
-  return await wsSvc.createView({ name: 'New Grid', layout });
-}
-
-export async function openTestDatabase(viewId: string): Promise<DatabaseController> {
-  return new DatabaseController(viewId);
-}
-
-export async function assertTextCell(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController,
-  expectedContent: string
-) {
-  const cellController = await makeTextCellController(fieldId, rowInfo, databaseController).then((result) =>
-    result.unwrap()
-  );
-
-  cellController.subscribeChanged({
-    onCellChanged: (value) => {
-      const cellContent = value.unwrap();
-
-      if (cellContent !== expectedContent) {
-        throw Error('Text cell content is not match');
-      }
-    },
-  });
-  await cellController.getCellData();
-}
-
-export async function editTextCell(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController,
-  content: string
-) {
-  const cellController = await makeTextCellController(fieldId, rowInfo, databaseController).then((result) =>
-    result.unwrap()
-  );
-
-  await cellController.saveCellData(content);
-}
-
-export async function makeTextCellController(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController
-): Promise<Option<TextCellController>> {
-  const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.RichText, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  return Some(builder.build() as TextCellController);
-}
-
-export async function makeSingleSelectCellController(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController
-): Promise<Option<SelectOptionCellController>> {
-  const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.SingleSelect, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  return Some(builder.build() as SelectOptionCellController);
-}
-
-export async function makeMultiSelectCellController(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController
-): Promise<Option<SelectOptionCellController>> {
-  const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.MultiSelect, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  return Some(builder.build() as SelectOptionCellController);
-}
-
-export async function makeDateCellController(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController
-): Promise<Option<DateCellController>> {
-  const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.DateTime, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  return Some(builder.build() as DateCellController);
-}
-
-export async function makeCheckboxCellController(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController
-): Promise<Option<CheckboxCellController>> {
-  const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.Checkbox, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  return Some(builder.build() as CheckboxCellController);
-}
-
-export async function makeURLCellController(
-  fieldId: string,
-  rowInfo: RowInfo,
-  databaseController: DatabaseController
-): Promise<Option<URLCellController>> {
-  const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.DateTime, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  return Some(builder.build() as URLCellController);
-}
-
-export async function makeCellControllerBuilder(
-  fieldId: string,
-  rowInfo: RowInfo,
-  _fieldType: FieldType,
-  databaseController: DatabaseController
-): Promise<Option<CellControllerBuilder>> {
-  const rowCache = databaseController.databaseViewCache.getRowCache();
-  const cellCache = rowCache.getCellCache();
-  const fieldController = databaseController.fieldController;
-  const rowController = new RowController(rowInfo, fieldController, rowCache);
-  const cellByFieldId = await rowController.loadCells();
-
-  for (const cellIdentifier of cellByFieldId.values()) {
-    const builder = new CellControllerBuilder(cellIdentifier, cellCache, fieldController);
-
-    if (cellIdentifier.fieldId === fieldId) {
-      return Some(builder);
-    }
-  }
-
-  return None;
-}
-
-export function findFirstFieldInfoWithFieldType(rowInfo: RowInfo, fieldType: FieldType) {
-  const fieldInfo = rowInfo.fieldInfos.find((element) => element.field.field_type === fieldType);
-
-  if (fieldInfo === undefined) {
-    return None;
-  } else {
-    return Some(fieldInfo);
-  }
-}
-
-export async function assertFieldName(controller: TypeOptionController, expected: string) {
-  const fieldInfo = controller.getFieldInfo();
-
-  if (fieldInfo.field.name !== expected) {
-    throw Error('Expect field name:' + expected + 'but receive:' + fieldInfo.field.name);
-  }
-}
-
-export async function assertNumberOfFields(viewId: string, expected: number) {
-  const svc = new DatabaseBackendService(viewId);
-  const databasePB = await svc.openDatabase().then((result) => result.unwrap());
-
-  if (databasePB.fields.length !== expected) {
-    throw Error('Expect number of fields:' + expected + 'but receive:' + databasePB.fields.length);
-  }
-}
-
-export async function assertNumberOfRows(viewId: string, expected: number) {
-  const svc = new DatabaseBackendService(viewId);
-  const databasePB = await svc.openDatabase().then((result) => result.unwrap());
-
-  if (databasePB.rows.length !== expected) {
-    throw Error('Expect number of rows:' + expected + 'but receive:' + databasePB.rows.length);
-  }
-}
-
-export async function assertNumberOfRowsInGroup(viewId: string, groupId: string, expected: number) {
-  const svc = new DatabaseBackendService(viewId);
-
-  await svc.openDatabase();
-
-  const group = await svc.getGroup(groupId).then((result) => result.unwrap());
-
-  if (group.rows.length !== expected) {
-    throw Error('Expect number of rows in group:' + expected + 'but receive:' + group.rows.length);
-  }
-}
-
-export async function createSingleSelectOptions(viewId: string, fieldInfo: FieldInfo, optionNames: string[]) {
-  assert(fieldInfo.field.field_type === FieldType.SingleSelect, 'Only work on single select');
-  const typeOptionController = new TypeOptionController(viewId, Some(fieldInfo));
-  const singleSelectTypeOptionContext = makeSingleSelectTypeOptionContext(typeOptionController);
-  const singleSelectTypeOptionPB: SingleSelectTypeOptionPB = singleSelectTypeOptionContext.getTypeOption();
-
-  const backendSvc = new SelectOptionBackendService(viewId, fieldInfo.field.id);
-
-  for (const optionName of optionNames) {
-    const option = await backendSvc.createOption({ name: optionName }).then((result) => result.unwrap());
-
-    singleSelectTypeOptionPB.options.splice(0, 0, option);
-  }
-
-  await singleSelectTypeOptionContext.setTypeOption(singleSelectTypeOptionPB);
-  return singleSelectTypeOptionContext;
-}
-
-export function assert(condition: boolean, msg?: string) {
-  if (!condition) {
-    throw Error(msg);
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts
deleted file mode 100644
index 895e28eee7..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { ViewLayoutPB, WorkspaceSettingPB } from '@/services/backend';
-import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller';
-import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder';
-
-export async function createTestDocument() {
-  const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspaceSetting().then((result) =>
-    result.unwrap()
-  );
-  const appService = new WorkspaceController(workspaceSetting.workspace_id);
-  const result = await appService.createView({ name: 'New Document', layout: ViewLayoutPB.Document });
-
-  return result;
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestAPI.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestAPI.tsx
deleted file mode 100644
index 46c41a65e9..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestAPI.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import React from 'react';
-import {
-  RunAllGridTests,
-  TestCreateGrid,
-  TestCreateNewField,
-  TestCreateRow,
-  TestCreateSelectOptionInCell,
-  TestDeleteField,
-  TestDeleteRow,
-  TestEditCell,
-  TestEditCheckboxCell,
-  TestEditDateCell,
-  TestEditDateFormat,
-  TestEditField,
-  TestEditNumberFormat,
-  TestEditTextCell,
-  TestEditURLCell,
-  TestGetSingleSelectFieldData,
-  TestMoveField,
-  TestSwitchFromMultiSelectToText,
-  TestSwitchFromSingleSelectToNumber,
-} from './TestGrid';
-import {
-  TestCreateKanbanBoard,
-  TestCreateKanbanBoardColumn,
-  TestCreateKanbanBoardRowInNoStatusGroup,
-  TestAllKanbanTests,
-  TestMoveKanbanBoardColumn,
-  TestMoveKanbanBoardRow,
-} from './TestGroup';
-import { TestCreateViews } from '$app/components/tests/TestFolder';
-
-export const TestAPI = () => {
-  return (
-    <React.Fragment>
-      <ul className='m-6, space-y-2'>
-        {/*<tests></tests>*/}
-        <RunAllGridTests></RunAllGridTests>
-        <TestCreateGrid></TestCreateGrid>
-        <TestCreateRow></TestCreateRow>
-        <TestDeleteRow></TestDeleteRow>
-        <TestEditCell></TestEditCell>
-        <TestEditTextCell></TestEditTextCell>
-        <TestEditURLCell></TestEditURLCell>
-        <TestEditDateCell></TestEditDateCell>
-        <TestEditCheckboxCell></TestEditCheckboxCell>
-        <TestCreateSelectOptionInCell></TestCreateSelectOptionInCell>
-        <TestGetSingleSelectFieldData></TestGetSingleSelectFieldData>
-        <TestEditField></TestEditField>
-        <TestMoveField></TestMoveField>
-        <TestCreateNewField></TestCreateNewField>
-        <TestDeleteField></TestDeleteField>
-        <TestEditDateFormat></TestEditDateFormat>
-        <TestEditNumberFormat></TestEditNumberFormat>
-        <TestSwitchFromSingleSelectToNumber></TestSwitchFromSingleSelectToNumber>
-        <TestSwitchFromMultiSelectToText></TestSwitchFromMultiSelectToText>
-        {/*kanban board */}
-        <TestAllKanbanTests></TestAllKanbanTests>
-        <TestCreateKanbanBoard></TestCreateKanbanBoard>
-        <TestCreateKanbanBoardRowInNoStatusGroup></TestCreateKanbanBoardRowInNoStatusGroup>
-        <TestMoveKanbanBoardRow></TestMoveKanbanBoardRow>
-        <TestMoveKanbanBoardColumn></TestMoveKanbanBoardColumn>
-        <TestCreateKanbanBoardColumn></TestCreateKanbanBoardColumn>
-        {/*Folders*/}
-        <TestCreateViews></TestCreateViews>
-      </ul>
-    </React.Fragment>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestFolder.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestFolder.tsx
deleted file mode 100644
index 6e24aae8a1..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestFolder.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from 'react';
-import { UserBackendService } from '$app/stores/effects/user/user_bd_svc';
-import { useAppSelector } from '$app/stores/store';
-import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller';
-import { ViewLayoutPB, ViewPB } from '@/services/backend';
-
-const testCreateFolder = async (userId?: number) => {
-  if (!userId) {
-    console.log('user is not logged in');
-    return;
-  }
-
-  console.log('test create views');
-  const userBackendService: UserBackendService = new UserBackendService(userId);
-  const workspaces = await userBackendService.getWorkspaces();
-
-  if (workspaces.ok) {
-    console.log('workspaces: ', workspaces.val.toObject());
-  }
-
-  const currentWorkspaceSetting = await userBackendService.getCurrentWorkspaceSetting();
-  const workspaceService = new WorkspaceController(currentWorkspaceSetting.workspace_id);
-  const rootViews: ViewPB[] = [];
-
-  for (let i = 1; i <= 3; i++) {
-    const result = await workspaceService.createView({
-      name: `test board ${i}`,
-      desc: 'test description',
-      layout: ViewLayoutPB.Board,
-    });
-
-    rootViews.push(result);
-  }
-
-  for (let i = 1; i <= 3; i++) {
-    await workspaceService.createView({
-      name: `test board 1 ${i}`,
-      desc: 'test description',
-      layout: ViewLayoutPB.Board,
-      parent_view_id: rootViews[0].id,
-    });
-  }
-
-  const allApps = await workspaceService.getChildPages();
-
-  console.log(allApps);
-};
-
-export const TestCreateViews = () => {
-  const currentUser = useAppSelector((state) => state.currentUser);
-
-  return TestButton('Test create views', testCreateFolder, currentUser.id);
-};
-
-const TestButton = (title: string, onClick: (userId?: number) => void, userId?: number) => {
-  return (
-    <React.Fragment>
-      <div>
-        <button className='rounded-md bg-pink-200 p-4' type='button' onClick={() => onClick(userId)}>
-          {title}
-        </button>
-      </div>
-    </React.Fragment>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestFonts.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestFonts.tsx
deleted file mode 100644
index 04e4c566a6..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestFonts.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { ChangeEvent, useState } from 'react';
-
-const TestFonts = () => {
-  const [sampleText, setSampleText] = useState('Sample Text');
-
-  const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
-    setSampleText(e.target.value);
-  };
-
-  return (
-    <div className={'flex h-full w-full flex-col items-center justify-center'}>
-      <div className={'py-2'}>
-        <input className={'rounded border border-gray-500 px-2 py-1'} value={sampleText} onChange={onInputChange} />
-      </div>
-      <div className={'flex flex-1 flex-col items-center justify-center overflow-auto text-2xl'}>
-        <div className={'mb-4 font-thin'}>{sampleText} 100 Thin</div>
-        <div className={'mb-4 font-extralight'}>{sampleText} 200 Extra Light</div>
-        <div className={'mb-4 font-light'}>{sampleText} 300 Light</div>
-        <div className={'mb-4 font-normal'}>{sampleText} 400 Regular</div>
-        <div className={'mb-4 font-medium'}>{sampleText} 500 Medium</div>
-        <div className={'mb-4 font-semibold'}>{sampleText} 600 Semi Bold</div>
-        <div className={'mb-4 font-bold'}>{sampleText} 700 Bold</div>
-        <div className={'mb-4 font-extrabold'}>{sampleText} 800 Extra Bold</div>
-        <div className={'mb-4 font-black'}>{sampleText} 900 Black</div>
-      </div>
-    </div>
-  );
-};
-
-export default TestFonts;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx
deleted file mode 100644
index 9aaaaf1453..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx
+++ /dev/null
@@ -1,608 +0,0 @@
-import React from 'react';
-import {
-  DateFormatPB,
-  FieldType,
-  NumberFormatPB,
-  NumberTypeOptionPB,
-  SelectOptionCellDataPB,
-  TimeFormatPB,
-  ViewLayoutPB,
-} from '@/services/backend';
-import { Log } from '$app/utils/log';
-import {
-  assert,
-  assertFieldName,
-  assertNumberOfFields,
-  assertNumberOfRows,
-  assertTextCell,
-  createSingleSelectOptions,
-  createTestDatabaseView,
-  editTextCell,
-  findFirstFieldInfoWithFieldType,
-  makeCheckboxCellController,
-  makeDateCellController,
-  makeMultiSelectCellController,
-  makeSingleSelectCellController,
-  makeTextCellController,
-  makeURLCellController,
-  openTestDatabase,
-} from './DatabaseTestHelper';
-import { SelectOptionCellBackendService } from '$app/stores/effects/database/cell/select_option_bd_svc';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { None, Some } from 'ts-results';
-import {
-  makeDateTypeOptionContext,
-  makeNumberTypeOptionContext,
-} from '$app/stores/effects/database/field/type_option/type_option_context';
-import { CalendarData } from '$app/stores/effects/database/cell/controller_builder';
-
-export const RunAllGridTests = () => {
-  async function run() {
-    await createBuildInGrid();
-    await testEditGridCell();
-    await testCreateRow();
-    await testDeleteRow();
-    await testCreateOptionInCell();
-    await testGetSingleSelectFieldData();
-    await testSwitchFromSingleSelectToNumber();
-    await testSwitchFromMultiSelectToRichText();
-    await testEditField();
-    await testCreateNewField();
-    await testDeleteField();
-  }
-
-  return (
-    <React.Fragment>
-      <div>
-        <button className='rounded-md bg-red-400 p-4' type='button' onClick={() => run()}>
-          Run all grid tests
-        </button>
-      </div>
-    </React.Fragment>
-  );
-};
-
-async function createBuildInGrid() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  databaseController.subscribe({
-    onViewChanged: (databasePB) => {
-      Log.debug('Did receive database:' + databasePB);
-    },
-    // onRowsChanged: async (rows) => {
-    //   if (rows.length !== 3) {
-    //     throw Error('Expected number of rows is 3, but receive ' + rows.length);
-    //   }
-    // },
-    onFieldsChanged: (fields) => {
-      if (fields.length !== 3) {
-        throw Error('Expected number of fields is 3, but receive ' + fields.length);
-      }
-    },
-  });
-  await databaseController.open().then((result) => result.unwrap());
-  await databaseController.dispose();
-}
-
-async function testEditGridCell() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) {
-    const cellContent = index.toString();
-    const fieldInfo = findFirstFieldInfoWithFieldType(row, FieldType.RichText).unwrap();
-
-    await editTextCell(fieldInfo.field.id, row, databaseController, cellContent);
-    await assertTextCell(fieldInfo.field.id, row, databaseController, cellContent);
-  }
-}
-
-async function testEditTextCell() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  const row = databaseController.databaseViewCache.rowInfos[0];
-  const textField = findFirstFieldInfoWithFieldType(row, FieldType.RichText).unwrap();
-  const textCellController = await makeTextCellController(textField.field.id, row, databaseController).then((result) =>
-    result.unwrap()
-  );
-
-  textCellController.subscribeChanged({
-    onCellChanged: (content) => {
-      Log.info('Receive text:', content);
-    },
-  });
-
-  await textCellController.saveCellData('hello react');
-  await new Promise((resolve) => setTimeout(resolve, 200));
-  await databaseController.dispose();
-}
-
-async function testEditURLCell() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  const typeOptionController = new TypeOptionController(view.id, None, FieldType.URL);
-
-  await typeOptionController.initialize();
-
-  const row = databaseController.databaseViewCache.rowInfos[0];
-  const urlCellController = await makeURLCellController(typeOptionController.fieldId, row, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  urlCellController.subscribeChanged({
-    onCellChanged: (content) => {
-      const pb = content.unwrap();
-
-      Log.info('Receive url data:', pb.url, pb.content);
-    },
-  });
-
-  await urlCellController.saveCellData('hello react');
-  await new Promise((resolve) => setTimeout(resolve, 200));
-
-  await urlCellController.saveCellData('appflowy.io');
-  await new Promise((resolve) => setTimeout(resolve, 200));
-}
-
-async function testEditDateCell() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  const typeOptionController = new TypeOptionController(view.id, None, FieldType.DateTime);
-
-  await typeOptionController.initialize();
-
-  const row = databaseController.databaseViewCache.rowInfos[0];
-  const dateCellController = await makeDateCellController(typeOptionController.fieldId, row, databaseController).then(
-    (result) => result.unwrap()
-  );
-
-  dateCellController.subscribeChanged({
-    onCellChanged: (content) => {
-      const pb = content.unwrap();
-
-      Log.info('Receive date data:', pb.date, pb.time);
-    },
-  });
-
-  const date = new CalendarData(new Date(), true, '13:00');
-
-  await dateCellController.saveCellData(date);
-  await new Promise((resolve) => setTimeout(resolve, 200));
-}
-
-async function testEditDateFormatPB() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Create date field
-  const typeOptionController = new TypeOptionController(view.id, None, FieldType.DateTime);
-
-  await typeOptionController.initialize();
-
-  // update date type option
-  const dateTypeOptionContext = makeDateTypeOptionContext(typeOptionController);
-  const typeOption = dateTypeOptionContext.getTypeOption();
-
-  assert(typeOption.date_format === DateFormatPB.Friendly, 'Date format not match');
-  assert(typeOption.time_format === TimeFormatPB.TwentyFourHour, 'Time format not match');
-  typeOption.date_format = DateFormatPB.Local;
-  typeOption.time_format = TimeFormatPB.TwelveHour;
-  await dateTypeOptionContext.setTypeOption(typeOption);
-
-  const typeOption2 = dateTypeOptionContext.getTypeOption();
-
-  assert(typeOption2.date_format === DateFormatPB.Local, 'Date format not match');
-  assert(typeOption2.time_format === TimeFormatPB.TwelveHour, 'Time format not match');
-
-  await new Promise((resolve) => setTimeout(resolve, 200));
-}
-
-async function testEditNumberFormatPB() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Create date field
-  const typeOptionController = new TypeOptionController(view.id, None, FieldType.Number);
-
-  await typeOptionController.initialize();
-
-  // update date type option
-  const dateTypeOptionContext = makeNumberTypeOptionContext(typeOptionController);
-  const typeOption = dateTypeOptionContext.getTypeOption();
-
-  typeOption.format = NumberFormatPB.EUR;
-  typeOption.name = 'Money';
-  await dateTypeOptionContext.setTypeOption(typeOption);
-
-  const typeOption2 = dateTypeOptionContext.getTypeOption();
-
-  Log.info(typeOption2);
-  await new Promise((resolve) => setTimeout(resolve, 200));
-}
-
-async function testCheckboxCell() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  const typeOptionController = new TypeOptionController(view.id, None, FieldType.Checkbox);
-
-  await typeOptionController.initialize();
-
-  const row = databaseController.databaseViewCache.rowInfos[0];
-  const checkboxCellController = await makeCheckboxCellController(
-    typeOptionController.fieldId,
-    row,
-    databaseController
-  ).then((result) => result.unwrap());
-
-  checkboxCellController.subscribeChanged({
-    onCellChanged: (content) => {
-      const pb = content.unwrap();
-
-      Log.info('Receive checkbox data:', pb);
-    },
-  });
-
-  await checkboxCellController.saveCellData('true');
-  await new Promise((resolve) => setTimeout(resolve, 200));
-}
-
-async function testCreateRow() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-  await assertNumberOfRows(view.id, 3);
-
-  // Create a row from a DatabaseController
-  await databaseController.createRow();
-  await assertNumberOfRows(view.id, 4);
-  await databaseController.dispose();
-}
-
-async function testDeleteRow() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  const rows = databaseController.databaseViewCache.rowInfos;
-
-  await databaseController.deleteRow(rows[0].row.id);
-  await assertNumberOfRows(view.id, 2);
-
-  // Wait the databaseViewCache get the change notification and
-  // update the rows.
-  await new Promise((resolve) => setTimeout(resolve, 200));
-  if (databaseController.databaseViewCache.rowInfos.length !== 2) {
-    throw Error('The number of rows is not match');
-  }
-
-  await databaseController.dispose();
-}
-
-async function testCreateOptionInCell() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-  for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) {
-    if (index === 0) {
-      const fieldInfo = findFirstFieldInfoWithFieldType(row, FieldType.SingleSelect).unwrap();
-      const cellController = await makeSingleSelectCellController(fieldInfo.field.id, row, databaseController).then(
-        (result) => result.unwrap()
-      );
-
-      // eslint-disable-next-line @typescript-eslint/await-thenable
-      await cellController.subscribeChanged({
-        onCellChanged: (value) => {
-          if (value.some) {
-            const option: SelectOptionCellDataPB = value.unwrap();
-
-            console.log(option);
-          }
-        },
-      });
-      const backendSvc = new SelectOptionCellBackendService(cellController.cellIdentifier);
-
-      await backendSvc.createOption({ name: 'option' + index });
-      await cellController.dispose();
-    }
-  }
-
-  await databaseController.dispose();
-}
-
-async function testMoveField() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-  const ids = databaseController.fieldController.fieldInfos.map((value) => value.field.id);
-
-  Log.info('Receive fields data:', ids);
-
-  databaseController.subscribe({
-    onFieldsChanged: (values) => {
-      const new_ids = values.map((value) => value.field.id);
-
-      Log.info('Receive fields data:', new_ids);
-    },
-  });
-
-  const fieldInfos = [...databaseController.fieldController.fieldInfos];
-  const fromFieldId = fieldInfos[0].field.id;
-  const toFieldId = fieldInfos[1].field.id;
-
-  await databaseController.moveField({ fromFieldId: fromFieldId, toFieldId: toFieldId });
-  await new Promise((resolve) => setTimeout(resolve, 200));
-  assert(databaseController.fieldController.fieldInfos[1].field.id === fromFieldId);
-}
-
-async function testGetSingleSelectFieldData() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Find the single select column
-  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-  const singleSelect = databaseController.fieldController.fieldInfos.find(
-    (fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect
-  )!;
-
-  // Create options
-  const singleSelectTypeOptionContext = await createSingleSelectOptions(view.id, singleSelect, [
-    'Task 1',
-    'Task 2',
-    'Task 3',
-  ]);
-
-  // Read options
-  const options = singleSelectTypeOptionContext.getTypeOption();
-
-  console.log(options);
-
-  await databaseController.dispose();
-}
-
-async function testSwitchFromSingleSelectToNumber() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Find the single select column
-  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-  const singleSelect = databaseController.fieldController.fieldInfos.find(
-    (fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect
-  )!;
-  const typeOptionController = new TypeOptionController(view.id, Some(singleSelect));
-
-  await typeOptionController.switchToField(FieldType.Number);
-
-  // Check the number type option
-  const numberTypeOptionContext = makeNumberTypeOptionContext(typeOptionController);
-  const numberTypeOption: NumberTypeOptionPB = numberTypeOptionContext
-    .getTypeOption();
-  const format: NumberFormatPB = numberTypeOption.format;
-
-  if (format !== NumberFormatPB.Num) {
-    throw Error('The default format should be number');
-  }
-
-  await databaseController.dispose();
-}
-
-async function testSwitchFromMultiSelectToRichText() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Create multi-select field
-  const typeOptionController = new TypeOptionController(view.id, None, FieldType.MultiSelect);
-
-  await typeOptionController.initialize();
-
-  // Insert options to first row
-  const row = databaseController.databaseViewCache.rowInfos[0];
-  const multiSelectField = typeOptionController.getFieldInfo();
-  // const multiSelectField = findFirstFieldInfoWithFieldType(row, FieldType.MultiSelect).unwrap();
-  const selectOptionCellController = await makeMultiSelectCellController(
-    multiSelectField.field.id,
-    row,
-    databaseController
-  ).then((result) => result.unwrap());
-  const backendSvc = new SelectOptionCellBackendService(selectOptionCellController.cellIdentifier);
-
-  await backendSvc.createOption({ name: 'A' });
-  await backendSvc.createOption({ name: 'B' });
-  await backendSvc.createOption({ name: 'C' });
-
-  const selectOptionCellData = await selectOptionCellController.getCellData().then((result) => result.unwrap());
-
-  if (selectOptionCellData.options.length !== 3) {
-    throw Error('The options should equal to 3');
-  }
-
-  if (selectOptionCellData.select_options.length !== 3) {
-    throw Error('The selected options should equal to 3');
-  }
-
-  await selectOptionCellController.dispose();
-
-  // Switch to RichText field type
-  await typeOptionController.switchToField(FieldType.RichText);
-  if (typeOptionController.fieldType !== FieldType.RichText) {
-    throw Error('The field type should be text');
-  }
-
-  const textCellController = await makeTextCellController(multiSelectField.field.id, row, databaseController).then(
-    (result) => result.unwrap()
-  );
-  const cellContent = await textCellController.getCellData();
-
-  if (cellContent.unwrap() !== 'A,B,C') {
-    throw Error('The cell content should be A,B,C, but receive: ' + cellContent.unwrap());
-  }
-
-  await databaseController.dispose();
-}
-
-async function testEditField() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-  const fieldInfos = databaseController.fieldController.fieldInfos;
-
-  // Modify the name of the field
-  const firstFieldInfo = fieldInfos[0];
-  const controller = new TypeOptionController(view.id, Some(firstFieldInfo));
-
-  await controller.initialize();
-  const newName = 'hello world';
-
-  await controller.setFieldName(newName);
-
-  await new Promise((resolve) => setTimeout(resolve, 200));
-  await assertFieldName(controller, newName);
-  await databaseController.dispose();
-}
-
-async function testCreateNewField() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-  await assertNumberOfFields(view.id, 3);
-
-  // Modify the name of the field
-  const controller = new TypeOptionController(view.id, None);
-
-  await controller.initialize();
-  await assertNumberOfFields(view.id, 4);
-  await databaseController.dispose();
-}
-
-async function testDeleteField() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Grid);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Modify the name of the field.
-  // The fieldInfos[0] is the primary field by default, we can't delete it.
-  // So let choose the second fieldInfo.
-  const fieldInfo = databaseController.fieldController.fieldInfos[1];
-  const controller = new TypeOptionController(view.id, Some(fieldInfo));
-
-  await controller.initialize();
-  await assertNumberOfFields(view.id, 3);
-  await controller.deleteField();
-  await assertNumberOfFields(view.id, 2);
-  await databaseController.dispose();
-}
-
-export const TestCreateGrid = () => {
-  return TestButton('Test create build-in grid', createBuildInGrid);
-};
-
-export const TestEditCell = () => {
-  return TestButton('Test editing cell', testEditGridCell);
-};
-
-export const TestEditTextCell = () => {
-  return TestButton('Test editing text cell', testEditTextCell);
-};
-
-export const TestEditURLCell = () => {
-  return TestButton('Test editing URL cell', testEditURLCell);
-};
-
-export const TestEditDateCell = () => {
-  return TestButton('Test editing date cell', testEditDateCell);
-};
-
-export const TestEditDateFormat = () => {
-  return TestButton('Test editing date format', testEditDateFormatPB);
-};
-
-export const TestEditNumberFormat = () => {
-  return TestButton('Test editing number format', testEditNumberFormatPB);
-};
-
-export const TestEditCheckboxCell = () => {
-  return TestButton('Test editing checkbox cell', testCheckboxCell);
-};
-
-export const TestCreateRow = () => {
-  return TestButton('Test create row', testCreateRow);
-};
-
-export const TestDeleteRow = () => {
-  return TestButton('Test delete row', testDeleteRow);
-};
-
-export const TestCreateSelectOptionInCell = () => {
-  return TestButton('Test create a select option in cell', testCreateOptionInCell);
-};
-
-export const TestGetSingleSelectFieldData = () => {
-  return TestButton('Test get single-select column data', testGetSingleSelectFieldData);
-};
-
-export const TestSwitchFromSingleSelectToNumber = () => {
-  return TestButton('Test switch from single-select to number column', testSwitchFromSingleSelectToNumber);
-};
-
-export const TestSwitchFromMultiSelectToText = () => {
-  return TestButton('Test switch from multi-select to text column', testSwitchFromMultiSelectToRichText);
-};
-
-export const TestMoveField = () => {
-  return TestButton('Test move field', testMoveField);
-};
-
-export const TestEditField = () => {
-  return TestButton('Test edit the column name', testEditField);
-};
-
-export const TestCreateNewField = () => {
-  return TestButton('Test create a new column', testCreateNewField);
-};
-
-export const TestDeleteField = () => {
-  return TestButton('Test delete a new column', testDeleteField);
-};
-
-export const TestButton = (title: string, onClick: () => void) => {
-  return (
-    <React.Fragment>
-      <div>
-        <button className='rounded-md bg-blue-400 p-4' type='button' onClick={() => onClick()}>
-          {title}
-        </button>
-      </div>
-    </React.Fragment>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGroup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGroup.tsx
deleted file mode 100644
index c161eeeeb1..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGroup.tsx
+++ /dev/null
@@ -1,191 +0,0 @@
-import {
-  assert,
-  assertNumberOfRowsInGroup,
-  createSingleSelectOptions,
-  createTestDatabaseView,
-  openTestDatabase,
-} from './DatabaseTestHelper';
-import { FieldType, ViewLayoutPB } from '../../../services/backend';
-import React from 'react';
-
-export const TestAllKanbanTests = () => {
-  async function run() {
-    await createBuildInBoard();
-    await createKanbanBoardRow();
-    await moveKanbanBoardRow();
-    await createKanbanBoardColumn();
-    await createColumnInBoard();
-  }
-
-  return (
-    <React.Fragment>
-      <div>
-        <button className='rounded-md bg-red-400 p-4' type='button' onClick={() => run()}>
-          Run all kanban board tests
-        </button>
-      </div>
-    </React.Fragment>
-  );
-};
-
-async function createBuildInBoard() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Board);
-  const databaseController = await openTestDatabase(view.id);
-
-  databaseController.subscribe({
-    onGroupByField: (groups) => {
-      console.log(groups);
-      if (groups.length !== 4) {
-        throw Error('The build-in board should have 4 groups');
-      }
-
-      assert(groups[0].rows.length === 0, 'The no status group should have 0 rows');
-      assert(groups[1].rows.length === 3, 'The first group should have 3 rows');
-      assert(groups[2].rows.length === 0, 'The second group should have 0 rows');
-      assert(groups[3].rows.length === 0, 'The third group should have 0 rows');
-    },
-  });
-  await databaseController.open().then((result) => result.unwrap());
-  await databaseController.dispose();
-}
-
-async function createKanbanBoardRow() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Board);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Create row in no status group
-  const noStatusGroup = databaseController.groups.getValue()[0];
-
-  await noStatusGroup.createRow().then((result) => result.unwrap());
-  await assertNumberOfRowsInGroup(view.id, noStatusGroup.groupId, 1);
-
-  await databaseController.dispose();
-}
-
-async function moveKanbanBoardRow() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Board);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Create row in no status group
-  const firstGroup = databaseController.groups.getValue()[1];
-  const secondGroup = databaseController.groups.getValue()[2];
-
-  // subscribe the group changes
-  firstGroup.subscribe({
-    onRemoveRow: (groupId, deleteRowId) => {
-      console.log(groupId + 'did remove:' + deleteRowId);
-    },
-    onInsertRow: (groupId, rowPB) => {
-      console.log(groupId + 'did insert:' + rowPB.id);
-    },
-    onUpdateRow: (groupId, rowPB) => {
-      console.log(groupId + 'did update:' + rowPB.id);
-    },
-    onCreateRow: (groupId, rowPB) => {
-      console.log(groupId + 'did create:' + rowPB.id);
-    },
-  });
-
-  secondGroup.subscribe({
-    onRemoveRow: (groupId, deleteRowId) => {
-      console.log(groupId + 'did remove:' + deleteRowId);
-    },
-    onInsertRow: (groupId, rowPB) => {
-      console.log(groupId + 'did insert:' + rowPB.id);
-    },
-    onUpdateRow: (groupId, rowPB) => {
-      console.log(groupId + 'did update:' + rowPB.id);
-    },
-    onCreateRow: (groupId, rowPB) => {
-      console.log(groupId + 'did create:' + rowPB.id);
-    },
-  });
-
-  const row = firstGroup.rowAtIndex(0).unwrap();
-
-  await databaseController.moveGroupRow(row.id, secondGroup.groupId);
-
-  assert(firstGroup.rows.length === 2);
-  await assertNumberOfRowsInGroup(view.id, firstGroup.groupId, 2);
-
-  assert(secondGroup.rows.length === 1);
-  await assertNumberOfRowsInGroup(view.id, secondGroup.groupId, 1);
-
-  await databaseController.dispose();
-}
-
-async function createKanbanBoardColumn() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Board);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // Create row in no status group
-  const firstGroup = databaseController.groups.getValue()[1];
-  const secondGroup = databaseController.groups.getValue()[2];
-
-  await databaseController.moveGroup(firstGroup.groupId, secondGroup.groupId);
-
-  assert(databaseController.groups.getValue()[1].groupId === secondGroup.groupId);
-  assert(databaseController.groups.getValue()[2].groupId === firstGroup.groupId);
-  await databaseController.dispose();
-}
-
-async function createColumnInBoard() {
-  const view = await createTestDatabaseView(ViewLayoutPB.Board);
-  const databaseController = await openTestDatabase(view.id);
-
-  await databaseController.open().then((result) => result.unwrap());
-
-  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-  const singleSelect = databaseController.fieldController.fieldInfos.find(
-    (fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect
-  )!;
-
-  // Create a option which will cause creating a new group
-  const name = 'New column';
-
-  await createSingleSelectOptions(view.id, singleSelect, [name]);
-
-  // Wait the backend posting the notification to update the groups
-  await new Promise((resolve) => setTimeout(resolve, 200));
-  assert(databaseController.groups.value.length === 5, 'expect number of groups is 5');
-  assert(databaseController.groups.value[4].name === name, 'expect the last group name is ' + name);
-  await databaseController.dispose();
-}
-
-export const TestCreateKanbanBoard = () => {
-  return TestButton('Test create build-in board', createBuildInBoard);
-};
-
-export const TestCreateKanbanBoardRowInNoStatusGroup = () => {
-  return TestButton('Test create row in build-in kanban board', createKanbanBoardRow);
-};
-
-export const TestMoveKanbanBoardRow = () => {
-  return TestButton('Test move row in build-in kanban board', moveKanbanBoardRow);
-};
-
-export const TestMoveKanbanBoardColumn = () => {
-  return TestButton('Test move column in build-in kanban board', createKanbanBoardColumn);
-};
-
-export const TestCreateKanbanBoardColumn = () => {
-  return TestButton('Test create column in build-in kanban board', createColumnInBoard);
-};
-
-export const TestButton = (title: string, onClick: () => void) => {
-  return (
-    <React.Fragment>
-      <div>
-        <button className='rounded-md bg-yellow-200 p-4' type='button' onClick={() => onClick()}>
-          {title}
-        </button>
-      </div>
-    </React.Fragment>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.hooks.ts
index 9948a2b189..e98a846da0 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.hooks.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.hooks.ts
@@ -1,41 +1,35 @@
-import { useCallback, useEffect, useMemo, useState } from 'react';
-import { TrashController } from '$app/stores/effects/workspace/trash/controller';
+import { useCallback, useEffect, useState } from 'react';
 import { useAppDispatch, useAppSelector } from '@/appflowy_app/stores/store';
 import { trashActions, trashPBToTrash } from '$app_reducers/trash/slice';
+import { subscribeNotifications } from '$app/application/notification';
+import { FolderNotification } from '@/services/backend';
+import { deleteTrashItem, getTrash, putback, deleteAll, restoreAll } from '$app/application/folder/trash.service';
 
 export function useLoadTrash() {
   const trash = useAppSelector((state) => state.trash.list);
   const dispatch = useAppDispatch();
-  const controller = useMemo(() => {
-    return new TrashController();
-  }, []);
 
   const initializeTrash = useCallback(async () => {
-    const trash = await controller.getTrash();
+    const trash = await getTrash();
 
     dispatch(trashActions.initTrash(trash.map(trashPBToTrash)));
-  }, [controller, dispatch]);
+  }, [dispatch]);
 
-  const subscribeToTrash = useCallback(async () => {
-    await controller.subscribe({
-      onTrashChanged: (trash) => {
-        dispatch(trashActions.onTrashChanged(trash.map(trashPBToTrash)));
+  useEffect(() => {
+    void initializeTrash();
+  }, [initializeTrash]);
+
+  useEffect(() => {
+    const unsubscribePromise = subscribeNotifications({
+      [FolderNotification.DidUpdateTrash]: async (changeset) => {
+        dispatch(trashActions.onTrashChanged(changeset.items.map(trashPBToTrash)));
       },
     });
-  }, [controller, dispatch]);
 
-  useEffect(() => {
-    void (async () => {
-      await initializeTrash();
-      await subscribeToTrash();
-    })();
-  }, [initializeTrash, subscribeToTrash]);
-
-  useEffect(() => {
     return () => {
-      void controller.dispose();
+      void unsubscribePromise.then((fn) => fn());
     };
-  }, [controller]);
+  }, [dispatch]);
 
   return {
     trash,
@@ -46,16 +40,6 @@ export function useTrashActions() {
   const [restoreAllDialogOpen, setRestoreAllDialogOpen] = useState(false);
   const [deleteAllDialogOpen, setDeleteAllDialogOpen] = useState(false);
 
-  const controller = useMemo(() => {
-    return new TrashController();
-  }, []);
-
-  useEffect(() => {
-    return () => {
-      void controller.dispose();
-    };
-  }, [controller]);
-
   const onClickRestoreAll = () => {
     setRestoreAllDialogOpen(true);
   };
@@ -70,18 +54,10 @@ export function useTrashActions() {
   };
 
   return {
-    onPutback: async (id: string) => {
-      await controller.putback(id);
-    },
-    onDelete: async (ids: string[]) => {
-      await controller.delete(ids);
-    },
-    onDeleteAll: async () => {
-      await controller.deleteAll();
-    },
-    onRestoreAll: async () => {
-      await controller.restoreAll();
-    },
+    onPutback: putback,
+    onDelete: deleteTrashItem,
+    onDeleteAll: deleteAll,
+    onRestoreAll: restoreAll,
     onClickRestoreAll,
     onClickDeleteAll,
     restoreAllDialogOpen,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.tsx
index 6387437162..6f0a0f94f6 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/trash/Trash.tsx
@@ -5,7 +5,7 @@ import { DeleteOutline, RestoreOutlined } from '@mui/icons-material';
 import { useLoadTrash, useTrashActions } from '$app/components/trash/Trash.hooks';
 import { Divider, List } from '@mui/material';
 import TrashItem from '$app/components/trash/TrashItem';
-import ConfirmDialog from '$app/components/_shared/app-dialog/ConfirmDialog';
+import DeleteConfirmDialog from '$app/components/_shared/delete_confirm_dialog/DeleteConfirmDialog';
 
 function Trash() {
   const { t } = useTranslation();
@@ -57,14 +57,14 @@ function Trash() {
           />
         ))}
       </List>
-      <ConfirmDialog
+      <DeleteConfirmDialog
         open={restoreAllDialogOpen}
         title={t('trash.confirmRestoreAll.title')}
         subtitle={t('trash.confirmRestoreAll.caption')}
         onOk={onRestoreAll}
         onClose={closeDialog}
       />
-      <ConfirmDialog
+      <DeleteConfirmDialog
         open={deleteAllDialogOpen}
         title={t('trash.confirmDeleteAll.title')}
         subtitle={t('trash.confirmDeleteAll.caption')}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/index.ts
deleted file mode 100644
index 7c5757b01c..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './user_listener';
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/parser.ts b/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/parser.ts
deleted file mode 100644
index 866d910e83..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/parser.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { FlowyError, UserNotification } from '@/services/backend';
-import { NotificationParser, OnNotificationError } from '@/services/backend/notifications';
-import { Result } from 'ts-results';
-
-declare type UserNotificationCallback = (ty: UserNotification, payload: Result<Uint8Array, FlowyError>) => void;
-
-export class UserNotificationParser extends NotificationParser<UserNotification> {
-  constructor(params: { id?: string; callback: UserNotificationCallback; onError?: OnNotificationError }) {
-    super(
-      params.callback,
-      (ty) => {
-        const notification = UserNotification[ty];
-
-        if (isUserNotification(notification)) {
-          return UserNotification[notification];
-        } else {
-          return UserNotification.Unknown;
-        }
-      },
-      params.id
-    );
-  }
-}
-
-const isUserNotification = (notification: string): notification is keyof typeof UserNotification => {
-  return Object.values(UserNotification).indexOf(notification) !== -1;
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/user_listener.ts b/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/user_listener.ts
deleted file mode 100644
index 112ee9b6a2..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/user_listener.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { FlowyError, UserNotification, UserProfilePB } from '@/services/backend';
-import { AFNotificationObserver, OnNotificationError } from '@/services/backend/notifications';
-import { UserNotificationParser } from './parser';
-import { Ok, Result } from 'ts-results';
-
-declare type OnUserProfileUpdate = (result: Result<UserProfilePB, FlowyError>) => void;
-
-export class UserNotificationListener extends AFNotificationObserver<UserNotification> {
-  onProfileUpdate?: OnUserProfileUpdate;
-
-  constructor(params: { userId?: string; onProfileUpdate?: OnUserProfileUpdate; onError?: OnNotificationError }) {
-    const parser = new UserNotificationParser({
-      callback: (notification, result) => {
-        switch (notification) {
-          case UserNotification.DidUpdateUserProfile:
-            if (result.ok) {
-              this.onProfileUpdate?.(Ok(UserProfilePB.deserializeBinary(result.val)));
-            } else {
-              this.onProfileUpdate?.(result);
-            }
-
-            break;
-          default:
-            break;
-        }
-      },
-      id: params.userId,
-      onError: params.onError,
-    });
-
-    super(parser);
-    this.onProfileUpdate = params.onProfileUpdate;
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/user/presentation/index.ts b/frontend/appflowy_tauri/src/appflowy_app/components/user/presentation/index.ts
deleted file mode 100644
index cb0ff5c3b5..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/components/user/presentation/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export {};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_bd_svc.ts
deleted file mode 100644
index 30ec4e5812..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_bd_svc.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { DatabaseEventGetCell, DatabaseEventUpdateCell } from '@/services/backend/events/flowy-database2';
-import { CellChangesetPB, CellIdPB, FieldType } from '@/services/backend';
-
-class CellIdentifier {
-  constructor(
-    public readonly viewId: string,
-    public readonly rowId: string,
-    public readonly fieldId: string,
-    public readonly fieldType: FieldType
-  ) {}
-}
-
-class CellBackendService {
-  static updateCell = async (cellId: CellIdentifier, data: string) => {
-    const payload = CellChangesetPB.fromObject({
-      view_id: cellId.viewId,
-      field_id: cellId.fieldId,
-      row_id: cellId.rowId,
-      cell_changeset: data,
-    });
-
-    return DatabaseEventUpdateCell(payload);
-  };
-
-  getCell = async (cellId: CellIdentifier) => {
-    const payload = CellIdPB.fromObject({
-      view_id: cellId.viewId,
-      field_id: cellId.fieldId,
-      row_id: cellId.rowId,
-    });
-
-    return DatabaseEventGetCell(payload);
-  };
-}
-
-export { CellBackendService, CellIdentifier };
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts
deleted file mode 100644
index d81415660c..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { None, Option, Some } from 'ts-results';
-
-export class CellCacheKey {
-  constructor(public readonly fieldId: string, public readonly rowId: string) {}
-}
-
-type CellDataByRowId = Map<string, any>;
-
-export class CellCache {
-  private cellDataByFieldId = new Map<string, CellDataByRowId>();
-
-  constructor(public readonly databaseId: string) {}
-
-  remove = (key: CellCacheKey) => {
-    const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId);
-
-    if (cellDataByRowId !== undefined) {
-      cellDataByRowId.delete(key.rowId);
-    }
-  };
-
-  removeWithFieldId = (fieldId: string) => {
-    this.cellDataByFieldId.delete(fieldId);
-  };
-
-  insert = (key: CellCacheKey, value: any) => {
-    const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId);
-
-    if (cellDataByRowId === undefined) {
-      const map = new Map();
-
-      map.set(key.rowId, value);
-      this.cellDataByFieldId.set(key.fieldId, map);
-    } else {
-      cellDataByRowId.set(key.rowId, value);
-    }
-  };
-
-  get<T>(key: CellCacheKey): Option<T> {
-    const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId);
-
-    if (cellDataByRowId === undefined) {
-      return None;
-    } else {
-      const value = cellDataByRowId.get(key.rowId);
-
-      if (typeof value === typeof undefined) {
-        return None;
-      }
-
-      // if (value satisfies T) {
-      //   return Some(value as T);
-      // }
-      return Some(value);
-    }
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts
deleted file mode 100644
index 2f1c164313..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts
+++ /dev/null
@@ -1,139 +0,0 @@
-import { CellIdentifier } from './cell_bd_svc';
-import { CellCache, CellCacheKey } from './cell_cache';
-import { CellDataLoader } from './data_parser';
-import { CellDataPersistence } from './data_persistence';
-import { FieldBackendService } from '../field/field_bd_svc';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { CellObserver } from './cell_observer';
-import { Log } from '$app/utils/log';
-import { None, Option, Some } from 'ts-results';
-import { DatabaseFieldObserver } from '../field/field_observer';
-
-type Callbacks<T> = { onCellChanged: (value: Option<T>) => void; onFieldChanged?: () => void };
-
-export class CellController<T, D> {
-  private fieldBackendService: FieldBackendService;
-  private cellDataNotifier: CellDataNotifier<T>;
-  private cellObserver: CellObserver;
-  private readonly cacheKey: CellCacheKey;
-  private readonly fieldNotifier: DatabaseFieldObserver;
-  private subscribeCallbacks?: Callbacks<T>;
-
-  constructor(
-    public readonly cellIdentifier: CellIdentifier,
-    private readonly cellCache: CellCache,
-    private readonly cellDataLoader: CellDataLoader<T>,
-    private readonly cellDataPersistence: CellDataPersistence<D>
-  ) {
-    this.fieldBackendService = new FieldBackendService(cellIdentifier.viewId, cellIdentifier.fieldId);
-    this.cacheKey = new CellCacheKey(cellIdentifier.fieldId, cellIdentifier.rowId);
-    this.cellDataNotifier = new CellDataNotifier(cellCache.get<T>(this.cacheKey));
-    this.cellObserver = new CellObserver(cellIdentifier.rowId, cellIdentifier.fieldId);
-    this.fieldNotifier = new DatabaseFieldObserver(cellIdentifier.fieldId);
-
-    void this.cellObserver.subscribe({
-      /// 1.Listen on user edit event and load the new cell data if needed.
-      /// For example:
-      ///  user input: 12
-      ///  cell display: $12
-      onCellChanged: async () => {
-        this.cellCache.remove(this.cacheKey);
-        try {
-          await this._loadCellData();
-        } catch (e) {
-          Log.error(e);
-        }
-      },
-    });
-
-    /// 2.Listen on the field event and load the cell data if needed.
-    void this.fieldNotifier.subscribe({
-      onFieldChanged: async () => {
-        /// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed
-        /// For example:
-        ///   ï¿¥12 -> $12
-        if (this.cellDataLoader.reloadOnFieldChanged) {
-          await this._loadCellData();
-        }
-
-        this.subscribeCallbacks?.onFieldChanged?.();
-      },
-    });
-  }
-
-  subscribeChanged = (callbacks: Callbacks<T>) => {
-    this.subscribeCallbacks = callbacks;
-    this.cellDataNotifier.observer?.subscribe((cellData) => {
-      if (cellData !== null) {
-        callbacks.onCellChanged(Some(cellData));
-      }
-    });
-  };
-
-  saveCellData = async (data: D) => {
-    const result = await this.cellDataPersistence.save(data);
-
-    if (result.err) {
-      Log.error(result.val);
-    }
-  };
-
-  /// Return the cell data immediately if it exists in the cache
-  /// Otherwise, it will load the cell data from the backend. The
-  /// subscribers of the [onCellChanged] will get noticed
-  getCellData = async (): Promise<Option<T>> => {
-    const cellData = this.cellCache.get<T>(this.cacheKey);
-
-    if (cellData.none) {
-      await this._loadCellData();
-      return this.cellCache.get<T>(this.cacheKey);
-    }
-
-    return cellData;
-  };
-
-  private _loadCellData = async () => {
-    const result = await this.cellDataLoader.loadData();
-
-    if (result.ok) {
-      const cellData = result.val;
-
-      if (cellData.some) {
-        this.cellCache.insert(this.cacheKey, cellData.val);
-        this.cellDataNotifier.cellData = cellData;
-      }
-    } else {
-      this.cellCache.remove(this.cacheKey);
-      this.cellDataNotifier.cellData = None;
-    }
-  };
-
-  dispose = async () => {
-    await this.cellObserver.unsubscribe();
-    await this.fieldNotifier.unsubscribe();
-    this.cellDataNotifier.unsubscribe();
-  };
-}
-
-class CellDataNotifier<T> extends ChangeNotifier<T> {
-  _cellData: Option<T>;
-
-  constructor(cellData: Option<T>) {
-    super();
-    this._cellData = cellData;
-  }
-
-  set cellData(data: Option<T>) {
-    if (this._cellData !== data) {
-      this._cellData = data;
-
-      if (this._cellData.some) {
-        this.notify(this._cellData.val);
-      }
-    }
-  }
-
-  get cellData(): Option<T> {
-    return this._cellData;
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts
deleted file mode 100644
index 0cd5ae35c2..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Ok, Result } from 'ts-results';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { DatabaseNotificationObserver } from '../notifications/observer';
-import { DatabaseNotification, FlowyError } from '@/services/backend';
-import { Subscription } from 'rxjs';
-
-export type CellChangedCallback = (value: Result<void, FlowyError>) => void;
-
-export class CellObserver {
-  private notifier?: ChangeNotifier<Result<void, FlowyError>>;
-  private listener?: DatabaseNotificationObserver;
-  private subscription?: Subscription;
-
-  constructor(public readonly rowId: string, public readonly fieldId: string) {}
-
-  subscribe = async (callbacks: { onCellChanged: CellChangedCallback }) => {
-    this.notifier = new ChangeNotifier();
-    this.subscription = this.notifier?.observer?.subscribe(callbacks.onCellChanged);
-    this.listener = new DatabaseNotificationObserver({
-      // The rowId combine with fieldId can identifier the cell.
-      // This format rowId:fieldId is also defined in the backend,
-      // so don't change this.
-      id: this.rowId + ':' + this.fieldId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case DatabaseNotification.DidUpdateCell:
-            if (result.ok) {
-              this.notifier?.notify(Ok.EMPTY);
-            } else {
-              this.notifier?.notify(result);
-            }
-
-            return;
-          default:
-            break;
-        }
-      },
-    });
-    await this.listener.start();
-  };
-
-  unsubscribe = async () => {
-    this.subscription?.unsubscribe();
-    await this.listener?.stop();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts
deleted file mode 100644
index bc1d5744e0..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import { DateCellDataPB, FieldType, SelectOptionCellDataPB, URLCellDataPB } from '@/services/backend';
-import { CellIdentifier } from './cell_bd_svc';
-import { CellController } from './cell_controller';
-import {
-  CellDataLoader,
-  DateCellDataParser,
-  SelectOptionCellDataParser,
-  StringCellDataParser,
-  URLCellDataParser,
-} from './data_parser';
-import { CellCache } from './cell_cache';
-import { FieldController } from '../field/field_controller';
-import { DateCellDataPersistence, TextCellDataPersistence } from './data_persistence';
-
-export type TextCellController = CellController<string, string>;
-
-export type CheckboxCellController = CellController<string, string>;
-
-export type NumberCellController = CellController<string, string>;
-
-export type SelectOptionCellController = CellController<SelectOptionCellDataPB, string>;
-
-export type DateCellController = CellController<DateCellDataPB, CalendarData>;
-
-export class CalendarData {
-  constructor(public readonly date: Date, public readonly includeTime: boolean, public readonly time?: string) {}
-}
-
-export type URLCellController = CellController<URLCellDataPB, string>;
-
-export class CellControllerBuilder {
-  constructor(
-    public readonly cellIdentifier: CellIdentifier,
-    public readonly cellCache: CellCache,
-    public readonly fieldController: FieldController
-  ) {}
-
-  ///
-  build = () => {
-    switch (this.cellIdentifier.fieldType) {
-      case FieldType.Checkbox:
-        return this.makeCheckboxCellController();
-      case FieldType.RichText:
-        return this.makeTextCellController();
-      case FieldType.Number:
-        return this.makeNumberCellController();
-      case FieldType.DateTime:
-      case FieldType.LastEditedTime:
-      case FieldType.CreatedTime:
-        return this.makeDateCellController();
-      case FieldType.URL:
-        return this.makeURLCellController();
-      case FieldType.SingleSelect:
-      case FieldType.MultiSelect:
-      case FieldType.Checklist:
-        return this.makeSelectOptionCellController();
-    }
-  };
-
-  makeSelectOptionCellController = (): SelectOptionCellController => {
-    const loader = new CellDataLoader(this.cellIdentifier, new SelectOptionCellDataParser(), true);
-    const persistence = new TextCellDataPersistence(this.cellIdentifier);
-
-    return new CellController<SelectOptionCellDataPB, string>(this.cellIdentifier, this.cellCache, loader, persistence);
-  };
-
-  makeURLCellController = (): URLCellController => {
-    const loader = new CellDataLoader(this.cellIdentifier, new URLCellDataParser());
-    const persistence = new TextCellDataPersistence(this.cellIdentifier);
-
-    return new CellController<URLCellDataPB, string>(this.cellIdentifier, this.cellCache, loader, persistence);
-  };
-
-  makeDateCellController = (): DateCellController => {
-    const loader = new CellDataLoader(this.cellIdentifier, new DateCellDataParser(), true);
-    const persistence = new DateCellDataPersistence(this.cellIdentifier);
-
-    return new CellController<DateCellDataPB, CalendarData>(this.cellIdentifier, this.cellCache, loader, persistence);
-  };
-
-  makeNumberCellController = (): NumberCellController => {
-    const loader = new CellDataLoader(this.cellIdentifier, new StringCellDataParser(), true);
-    const persistence = new TextCellDataPersistence(this.cellIdentifier);
-
-    return new CellController<string, string>(this.cellIdentifier, this.cellCache, loader, persistence);
-  };
-
-  makeTextCellController = (): TextCellController => {
-    const loader = new CellDataLoader(this.cellIdentifier, new StringCellDataParser());
-    const persistence = new TextCellDataPersistence(this.cellIdentifier);
-
-    return new CellController<string, string>(this.cellIdentifier, this.cellCache, loader, persistence);
-  };
-
-  makeCheckboxCellController = (): CheckboxCellController => {
-    const loader = new CellDataLoader(this.cellIdentifier, new StringCellDataParser());
-    const persistence = new TextCellDataPersistence(this.cellIdentifier);
-
-    return new CellController<string, string>(this.cellIdentifier, this.cellCache, loader, persistence);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts
deleted file mode 100644
index 80afed8f9f..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { CellBackendService, CellIdentifier } from './cell_bd_svc';
-import { SelectOptionCellDataPB, URLCellDataPB, DateCellDataPB } from '@/services/backend';
-import { Err, None, Ok, Option, Some } from 'ts-results';
-import { Log } from '$app/utils/log';
-
-abstract class CellDataParser<T> {
-  abstract parserData(data: Uint8Array): Option<T>;
-}
-
-class CellDataLoader<T> {
-  private service = new CellBackendService();
-
-  constructor(
-    readonly cellId: CellIdentifier,
-    readonly parser: CellDataParser<T>,
-    public readonly reloadOnFieldChanged: boolean = false
-  ) {}
-
-  loadData = async () => {
-    const result = await this.service.getCell(this.cellId);
-
-    if (result.ok) {
-      return Ok(this.parser.parserData(result.val.data));
-    } else {
-      Log.error(result.err);
-      return Err(result.err);
-    }
-  };
-}
-
-export const utf8Decoder = new TextDecoder('utf-8');
-export const utf8Encoder = new TextEncoder();
-
-class StringCellDataParser extends CellDataParser<string> {
-  parserData(data: Uint8Array): Option<string> {
-    return Some(utf8Decoder.decode(data));
-  }
-}
-
-class DateCellDataParser extends CellDataParser<DateCellDataPB> {
-  parserData(data: Uint8Array): Option<DateCellDataPB> {
-    return Some(DateCellDataPB.deserializeBinary(data));
-  }
-}
-
-class SelectOptionCellDataParser extends CellDataParser<SelectOptionCellDataPB> {
-  parserData(data: Uint8Array): Option<SelectOptionCellDataPB> {
-    if (data.length === 0) {
-      return None;
-    }
-
-    return Some(SelectOptionCellDataPB.deserializeBinary(data));
-  }
-}
-
-class URLCellDataParser extends CellDataParser<URLCellDataPB> {
-  parserData(data: Uint8Array): Option<URLCellDataPB> {
-    if (data.length === 0) {
-      return None;
-    }
-
-    return Some(URLCellDataPB.deserializeBinary(data));
-  }
-}
-
-export {
-  StringCellDataParser,
-  DateCellDataParser,
-  SelectOptionCellDataParser,
-  URLCellDataParser,
-  CellDataLoader,
-  CellDataParser,
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts
deleted file mode 100644
index ea8e9e2953..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { Result } from 'ts-results';
-import { CellBackendService, CellIdentifier } from './cell_bd_svc';
-import { CalendarData } from './controller_builder';
-import { DateChangesetPB, FlowyError, CellIdPB } from '@/services/backend';
-import { DatabaseEventUpdateDateCell } from '@/services/backend/events/flowy-database2';
-
-export abstract class CellDataPersistence<D> {
-  abstract save(data: D): Promise<Result<void, FlowyError>>;
-}
-
-export class TextCellDataPersistence extends CellDataPersistence<string> {
-  constructor(public readonly cellId: CellIdentifier) {
-    super();
-  }
-
-  save(data: string): Promise<Result<void, FlowyError>> {
-    return CellBackendService.updateCell(this.cellId, data);
-  }
-}
-
-export class DateCellDataPersistence extends CellDataPersistence<CalendarData> {
-  constructor(public readonly cellIdentifier: CellIdentifier) {
-    super();
-  }
-
-  save(data: CalendarData): Promise<Result<void, FlowyError>> {
-    const payload = DateChangesetPB.fromObject({ cell_id: _makeCellId(this.cellIdentifier) });
-
-    payload.date = (data.date.getTime() / 1000) | 0;
-    if (data.time !== undefined) {
-      payload.time = data.time;
-    }
-
-    payload.include_time = data.includeTime;
-    return DatabaseEventUpdateDateCell(payload);
-  }
-}
-
-function _makeCellId(cellIdentifier: CellIdentifier): CellIdPB {
-  return CellIdPB.fromObject({
-    view_id: cellIdentifier.viewId,
-    field_id: cellIdentifier.fieldId,
-    row_id: cellIdentifier.rowId,
-  });
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts
deleted file mode 100644
index 5e3e86fadc..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import { CellIdentifier } from './cell_bd_svc';
-import {
-  CellIdPB,
-  CreateSelectOptionPayloadPB,
-  RepeatedSelectOptionPayload,
-  SelectOptionCellChangesetPB,
-  SelectOptionPB,
-} from '@/services/backend';
-import {
-  DatabaseEventCreateSelectOption,
-  DatabaseEventDeleteSelectOption,
-  DatabaseEventGetSelectOptionCellData,
-  DatabaseEventInsertOrUpdateSelectOption,
-  DatabaseEventUpdateSelectOptionCell,
-} from '@/services/backend/events/flowy-database2';
-
-export class SelectOptionBackendService {
-  constructor(public readonly viewId: string, public readonly fieldId: string) {}
-
-  createOption = async (params: { name: string }) => {
-    const payload = CreateSelectOptionPayloadPB.fromObject({
-      option_name: params.name,
-      view_id: this.viewId,
-      field_id: this.fieldId,
-    });
-
-    return DatabaseEventCreateSelectOption(payload);
-  };
-}
-
-export class SelectOptionCellBackendService {
-  constructor(public readonly cellIdentifier: CellIdentifier) {}
-
-  // Creates a new option and insert this option to the cell
-  createOption = async (params: { name: string; isSelect?: boolean }) => {
-    const payload = CreateSelectOptionPayloadPB.fromObject({
-      option_name: params.name,
-      view_id: this.cellIdentifier.viewId,
-      field_id: this.cellIdentifier.fieldId,
-    });
-
-    const result = await DatabaseEventCreateSelectOption(payload);
-
-    if (result.ok) {
-      return await this._insertOption(result.val, params.isSelect || true);
-    } else {
-      return result;
-    }
-  };
-
-  private _insertOption = (option: SelectOptionPB, _: boolean) => {
-    const payload = RepeatedSelectOptionPayload.fromObject({
-      view_id: this.cellIdentifier.viewId,
-      field_id: this.cellIdentifier.fieldId,
-      items: [option],
-    });
-
-    return DatabaseEventInsertOrUpdateSelectOption(payload);
-  };
-
-  updateOption = async (option: SelectOptionPB) => {
-    const payload = RepeatedSelectOptionPayload.fromObject({
-      view_id: this.cellIdentifier.viewId,
-      field_id: this.cellIdentifier.fieldId,
-      items: [option],
-    });
-
-    return DatabaseEventInsertOrUpdateSelectOption(payload);
-  };
-
-  deleteOption = (options: SelectOptionPB[]) => {
-    const payload = RepeatedSelectOptionPayload.fromObject({
-      view_id: this.cellIdentifier.viewId,
-      field_id: this.cellIdentifier.fieldId,
-      row_id: this.cellIdentifier.rowId,
-    });
-
-    payload.items.push(...options);
-    return DatabaseEventDeleteSelectOption(payload);
-  };
-
-  getOptionCellData = () => {
-    return DatabaseEventGetSelectOptionCellData(this._cellIdentifier());
-  };
-
-  selectOption = (optionIds: string[]) => {
-    const payload = SelectOptionCellChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
-
-    payload.insert_option_ids.push(...optionIds);
-    return DatabaseEventUpdateSelectOptionCell(payload);
-  };
-
-  unselectOption = (optionIds: string[]) => {
-    const payload = SelectOptionCellChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
-
-    payload.delete_option_ids.push(...optionIds);
-    return DatabaseEventUpdateSelectOptionCell(payload);
-  };
-
-  private _cellIdentifier = () => {
-    return CellIdPB.fromObject({
-      view_id: this.cellIdentifier.viewId,
-      field_id: this.cellIdentifier.fieldId,
-      row_id: this.cellIdentifier.rowId,
-    });
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts
deleted file mode 100644
index 33ece15fb8..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-import {
-  DatabaseEventCreateRow,
-  DatabaseEventDeleteRow,
-  DatabaseEventDuplicateRow,
-  DatabaseEventGetDatabase,
-  DatabaseEventGetDatabaseSetting,
-  DatabaseEventGetFields,
-  DatabaseEventGetGroup,
-  DatabaseEventGetGroups,
-  DatabaseEventMoveField,
-  DatabaseEventMoveGroup,
-  DatabaseEventMoveGroupRow,
-  DatabaseEventMoveRow,
-  DatabaseEventUpdateField,
-  DatabaseGroupIdPB,
-  FieldChangesetPB,
-  MoveFieldPayloadPB,
-  MoveGroupPayloadPB,
-  MoveGroupRowPayloadPB,
-  MoveRowPayloadPB,
-  RowIdPB,
-  DuplicateFieldPayloadPB,
-  DatabaseEventDuplicateField,
-} from '@/services/backend/events/flowy-database2';
-import {
-  GetFieldPayloadPB,
-  RepeatedFieldIdPB,
-  FieldIdPB,
-  DatabaseViewIdPB,
-  CreateRowPayloadPB,
-  ViewIdPB,
-  OrderObjectPositionTypePB,
-} from '@/services/backend';
-import { FolderEventCloseView } from '@/services/backend/events/flowy-folder';
-import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller';
-import { None } from 'ts-results';
-
-/// A service that wraps the backend service
-export class DatabaseBackendService {
-  viewId: string;
-
-  constructor(viewId: string) {
-    this.viewId = viewId;
-  }
-
-  /// Open a database
-  openDatabase = async () => {
-    const payload = DatabaseViewIdPB.fromObject({
-      value: this.viewId,
-    });
-
-    return DatabaseEventGetDatabase(payload);
-  };
-
-  /// Close a database
-  closeDatabase = async () => {
-    const payload = ViewIdPB.fromObject({ value: this.viewId });
-
-    return FolderEventCloseView(payload);
-  };
-
-  /// Create a row in database
-  /// 1.The row will be the last row in database if the params is undefined
-  /// 2.The row will be placed after the passed-in rowId
-  /// 3.The row will be moved to the group with groupId. Currently, grouping is
-  /// only support in kanban board.
-  createRow = async (params?: { groupId?: string; position?: OrderObjectPositionTypePB; rowId?: string }) => {
-    const payload = CreateRowPayloadPB.fromObject({
-      view_id: this.viewId,
-      row_position: {
-        position: params?.position,
-        object_id: params?.rowId,
-      },
-      group_id: params?.groupId,
-    });
-
-    return DatabaseEventCreateRow(payload);
-  };
-
-  duplicateRow = async (rowId: string) => {
-    const payload = RowIdPB.fromObject({ view_id: this.viewId, row_id: rowId });
-
-    return DatabaseEventDuplicateRow(payload);
-  };
-
-  deleteRow = async (rowId: string) => {
-    const payload = RowIdPB.fromObject({ view_id: this.viewId, row_id: rowId });
-
-    return DatabaseEventDeleteRow(payload);
-  };
-
-  moveRow = async (fromRowId: string, toRowId: string) => {
-    const payload = MoveRowPayloadPB.fromObject({ view_id: this.viewId, from_row_id: fromRowId, to_row_id: toRowId });
-
-    return DatabaseEventMoveRow(payload);
-  };
-
-  /// Move the row from one group to another group
-  /// [toRowId] is used to locate the moving row location.
-  moveGroupRow = (fromRowId: string, toGroupId: string, toRowId?: string) => {
-    const payload = MoveGroupRowPayloadPB.fromObject({
-      view_id: this.viewId,
-      from_row_id: fromRowId,
-      to_group_id: toGroupId,
-    });
-
-    if (toRowId !== undefined) {
-      payload.to_row_id = toRowId;
-    }
-
-    return DatabaseEventMoveGroupRow(payload);
-  };
-
-  moveGroup = (fromGroupId: string, toGroupId: string) => {
-    const payload = MoveGroupPayloadPB.fromObject({
-      view_id: this.viewId,
-      from_group_id: fromGroupId,
-      to_group_id: toGroupId,
-    });
-
-    return DatabaseEventMoveGroup(payload);
-  };
-
-  /// Get all fields in database
-  getFields = async (fieldIds?: FieldIdPB[]) => {
-    const payload = GetFieldPayloadPB.fromObject({ view_id: this.viewId });
-
-    if (!fieldIds) {
-      payload.field_ids = RepeatedFieldIdPB.fromObject({ items: fieldIds });
-    }
-
-    return DatabaseEventGetFields(payload).then((result) => result.map((value) => value.items));
-  };
-
-  /// Get a group by id
-  getGroup = (groupId: string) => {
-    const payload = DatabaseGroupIdPB.fromObject({ view_id: this.viewId, group_id: groupId });
-
-    return DatabaseEventGetGroup(payload);
-  };
-
-  moveField = (params: { fromFieldId: string; toFieldId: string }) => {
-    const payload = MoveFieldPayloadPB.fromObject({
-      view_id: this.viewId,
-      from_field_id: params.fromFieldId,
-      to_field_id: params.toFieldId,
-    });
-
-    return DatabaseEventMoveField(payload);
-  };
-
-  changeWidth = (params: { fieldId: string; width: number }) => {
-    const payload = FieldChangesetPB.fromObject({
-      view_id: this.viewId,
-      field_id: params.fieldId,
-      width: params.width,
-    });
-
-    return DatabaseEventUpdateField(payload);
-  };
-
-  duplicateField = (fieldId: string) => {
-    const payload = DuplicateFieldPayloadPB.fromObject({ view_id: this.viewId, field_id: fieldId });
-
-    return DatabaseEventDuplicateField(payload);
-  };
-
-  createField = async () => {
-    const fieldController = new TypeOptionController(this.viewId, None);
-
-    await fieldController.initialize();
-  };
-
-  /// Get all groups in database
-  /// It should only call once after the board open
-  loadGroups = () => {
-    const payload = DatabaseViewIdPB.fromObject({ value: this.viewId });
-
-    return DatabaseEventGetGroups(payload);
-  };
-
-  getSettings = () => {
-    const payload = DatabaseViewIdPB.fromObject({ value: this.viewId });
-
-    return DatabaseEventGetDatabaseSetting(payload);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts
deleted file mode 100644
index 0a33ce2817..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts
+++ /dev/null
@@ -1,260 +0,0 @@
-import { DatabaseBackendService } from './database_bd_svc';
-import { FieldController, FieldInfo } from './field/field_controller';
-import { DatabaseViewCache } from './view/database_view_cache';
-import { DatabasePB, GroupPB, FlowyError, OrderObjectPositionTypePB } from '@/services/backend';
-import { RowChangedReason, RowInfo } from './row/row_cache';
-import { Err, Ok } from 'ts-results';
-import { DatabaseGroupController } from './group/group_controller';
-import { BehaviorSubject } from 'rxjs';
-import { DatabaseGroupObserver } from './group/group_observer';
-import { Log } from '$app/utils/log';
-import { FilterController } from '$app/stores/effects/database/filter/filter_controller';
-import { FilterParsed } from '$app/stores/effects/database/filter/filter_bd_svc';
-import { SortController } from '$app/stores/effects/database/sort/sort_controller';
-import { IDatabaseSort } from '$app_reducers/database/slice';
-
-export type DatabaseSubscriberCallbacks = {
-  onViewChanged?: (data: DatabasePB) => void;
-  onRowsChanged?: (rowInfos: readonly RowInfo[], reason: RowChangedReason) => void;
-  onFieldsChanged?: (fieldInfos: readonly FieldInfo[]) => void;
-  onFiltersChanged?: (filters: readonly FilterParsed[]) => void;
-  onSortChanged?: (sorts: readonly IDatabaseSort[]) => void;
-  onGroupByField?: (groups: GroupPB[]) => void;
-
-  onNumOfGroupChanged?: {
-    onUpdateGroup: (value: GroupPB[]) => void;
-    onDeleteGroup: (value: GroupPB[]) => void;
-    onInsertGroup: (value: GroupPB[]) => void;
-  };
-};
-
-export class DatabaseController {
-  private readonly backendService: DatabaseBackendService;
-  fieldController: FieldController;
-  sortController: SortController;
-  filterController: FilterController;
-  databaseViewCache: DatabaseViewCache;
-  private _callback?: DatabaseSubscriberCallbacks;
-  public groups: BehaviorSubject<DatabaseGroupController[]>;
-  private groupsObserver: DatabaseGroupObserver;
-
-  constructor(public readonly viewId: string) {
-    this.backendService = new DatabaseBackendService(viewId);
-    this.fieldController = new FieldController(viewId);
-    this.filterController = new FilterController(viewId);
-    this.sortController = new SortController(viewId);
-    this.databaseViewCache = new DatabaseViewCache(viewId, this.fieldController);
-    this.groups = new BehaviorSubject<DatabaseGroupController[]>([]);
-    this.groupsObserver = new DatabaseGroupObserver(viewId);
-  }
-
-  subscribe = (callbacks: DatabaseSubscriberCallbacks) => {
-    this._callback = callbacks;
-    this.fieldController.subscribe({ onNumOfFieldsChanged: callbacks.onFieldsChanged });
-    this.filterController.subscribe({ onFiltersChanged: callbacks.onFiltersChanged });
-    this.sortController.subscribe({ onSortChanged: callbacks.onSortChanged });
-    this.databaseViewCache.getRowCache().subscribe({
-      onRowsChanged: (reason) => {
-        this._callback?.onRowsChanged?.(this.databaseViewCache.rowInfos, reason);
-      },
-    });
-  };
-
-  open = async () => {
-    const openDatabaseResult = await this.backendService.openDatabase();
-
-    if (openDatabaseResult.ok) {
-      const database: DatabasePB = openDatabaseResult.val;
-
-      await this.databaseViewCache.initialize();
-      await this.fieldController.initialize();
-      await this.filterController.initialize();
-      await this.sortController.initialize();
-
-      // subscriptions
-      await this.subscribeOnGroupsChanged();
-
-      // load database initial data
-      await this.fieldController.loadFields(database.fields);
-
-      this.databaseViewCache.initializeWithRows(database.rows);
-
-      this._callback?.onViewChanged?.(database);
-      return Ok(database.rows);
-    } else {
-      return Err(openDatabaseResult.val);
-    }
-  };
-
-  getGroupByFieldId = async () => {
-    const settingsResult = await this.backendService.getSettings();
-
-    if (settingsResult.ok) {
-      const settings = settingsResult.val;
-      const groupConfig = settings.group_settings.items;
-
-      if (groupConfig.length === 0) {
-        return Err(new FlowyError({ msg: 'this database has no groups' }));
-      }
-
-      return Ok(settings.group_settings.items[0].field_id);
-    } else {
-      return Err(settingsResult.val);
-    }
-  };
-
-  createRow = () => {
-    return this.backendService.createRow();
-  };
-
-  createRowAfter = (rowId: string) => {
-    return this.backendService.createRow({ rowId, position: OrderObjectPositionTypePB.After });
-  };
-
-  duplicateRow = async (rowId: string) => {
-    return this.backendService.duplicateRow(rowId);
-  };
-
-  deleteRow = async (rowId: string) => {
-    return this.backendService.deleteRow(rowId);
-  };
-
-  moveRow = (fromRowId: string, toRowId: string) => {
-    return this.backendService.moveRow(fromRowId, toRowId);
-  };
-
-  moveGroupRow = (rowId: string, groupId: string) => {
-    return this.backendService.moveGroupRow(rowId, groupId);
-  };
-
-  exchangeGroupRow = async (fromRowId: string, toGroupId: string, toRowId?: string) => {
-    await this.backendService.moveGroupRow(fromRowId, toGroupId, toRowId);
-    await this.loadGroup();
-  };
-
-  moveGroup = (fromGroupId: string, toGroupId: string) => {
-    return this.backendService.moveGroup(fromGroupId, toGroupId);
-  };
-
-  moveField = (params: { fromFieldId: string; toFieldId: string }) => {
-    return this.backendService.moveField(params);
-  };
-
-  changeWidth = (params: { fieldId: string; width: number }) => {
-    return this.backendService.changeWidth(params);
-  };
-
-  duplicateField = (fieldId: string) => {
-    return this.backendService.duplicateField(fieldId);
-  };
-
-  addFieldToLeft = async (fieldId: string) => {
-    await this.backendService.createField();
-
-    const newFieldId = this.fieldController.fieldInfos[this.fieldController.fieldInfos.length - 1].field.id;
-
-    await this.moveField({
-      fromFieldId: newFieldId,
-      toFieldId: fieldId,
-    });
-  };
-
-  addFieldToRight = async (fieldId: string) => {
-    await this.backendService.createField();
-
-    const newFieldId = this.fieldController.fieldInfos[this.fieldController.fieldInfos.length - 1].field.id;
-
-    const index = this.fieldController.fieldInfos.findIndex((fieldInfo) => fieldInfo.field.id === fieldId);
-
-    const toFieldId = this.fieldController.fieldInfos[index + 1].field.id;
-
-    await this.moveField({
-      fromFieldId: newFieldId,
-      toFieldId: toFieldId,
-    });
-  };
-
-  private loadGroup = async () => {
-    const result = await this.backendService.loadGroups();
-
-    if (result.ok) {
-      const groups = result.val.items;
-
-      await this.initialGroups(groups);
-    }
-
-    return result;
-  };
-
-  private initialGroups = async (groups: GroupPB[]) => {
-    this.groups.getValue().forEach((controller) => {
-      void controller.dispose();
-    });
-
-    const controllers: DatabaseGroupController[] = [];
-
-    for (const groupPB of groups) {
-      const controller = new DatabaseGroupController(groupPB, this.backendService);
-
-      await controller.initialize();
-      controllers.push(controller);
-    }
-
-    this.groups.next(controllers);
-    this.groups.value;
-  };
-
-  private subscribeOnGroupsChanged = async () => {
-    await this.groupsObserver.subscribe({
-      onGroupBy: async (result) => {
-        if (result.ok) {
-          await this.initialGroups(result.val);
-        }
-      },
-      onGroupChangeset: (result) => {
-        if (result.err) {
-          Log.error(result.val);
-          return;
-        }
-
-        const changeset = result.val;
-        let existControllers = [...this.groups.getValue()];
-
-        for (const deleteId of changeset.deleted_groups) {
-          existControllers = existControllers.filter((c) => c.groupId !== deleteId);
-        }
-
-        for (const update of changeset.update_groups) {
-          const index = existControllers.findIndex((c) => c.groupId === update.group_id);
-
-          if (index !== -1) {
-            existControllers[index].updateGroup(update);
-          }
-        }
-
-        for (const insert of changeset.inserted_groups) {
-          const controller = new DatabaseGroupController(insert.group, this.backendService);
-
-          if (insert.index > existControllers.length) {
-            existControllers.push(controller);
-          } else {
-            existControllers.splice(insert.index, 0, controller);
-          }
-        }
-
-        this.groups.next(existControllers);
-      },
-    });
-  };
-
-  dispose = async () => {
-    this.groups.value.forEach((group) => {
-      void group.dispose();
-    });
-    await this.groupsObserver.unsubscribe();
-    await this.backendService.closeDatabase();
-    await this.fieldController.dispose();
-    this.filterController.dispose();
-    await this.databaseViewCache.dispose();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_bd_svc.ts
deleted file mode 100644
index 86f4314693..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_bd_svc.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import {
-  DeleteFieldPayloadPB,
-  DuplicateFieldPayloadPB,
-  FieldChangesetPB,
-  TypeOptionChangesetPB,
-} from '@/services/backend';
-import {
-  DatabaseEventDeleteField,
-  DatabaseEventDuplicateField,
-  DatabaseEventUpdateField,
-  DatabaseEventUpdateFieldTypeOption,
-} from '@/services/backend/events/flowy-database2';
-
-export abstract class TypeOptionParser<T> {
-  abstract fromBuffer(buffer: Uint8Array): T;
-}
-
-export class FieldBackendService {
-  constructor(public readonly viewId: string, public readonly fieldId: string) {}
-
-  updateField = (data: { name?: string; frozen?: boolean; visibility?: boolean; width?: number }) => {
-    const payload = FieldChangesetPB.fromObject({ view_id: this.viewId, field_id: this.fieldId });
-
-    if (data.name !== undefined) {
-      payload.name = data.name;
-    }
-
-    if (data.frozen !== undefined) {
-      payload.frozen = data.frozen;
-    }
-
-    if (data.visibility !== undefined) {
-      payload.visibility = data.visibility;
-    }
-
-    if (data.width !== undefined) {
-      payload.width = data.width;
-    }
-
-    return DatabaseEventUpdateField(payload);
-  };
-
-  updateTypeOption = (typeOptionData: Uint8Array) => {
-    const payload = TypeOptionChangesetPB.fromObject({
-      view_id: this.viewId,
-      field_id: this.fieldId,
-      type_option_data: typeOptionData,
-    });
-
-    return DatabaseEventUpdateFieldTypeOption(payload);
-  };
-
-  deleteField = () => {
-    const payload = DeleteFieldPayloadPB.fromObject({ view_id: this.viewId, field_id: this.fieldId });
-
-    return DatabaseEventDeleteField(payload);
-  };
-
-  duplicateField = () => {
-    const payload = DuplicateFieldPayloadPB.fromObject({ view_id: this.viewId, field_id: this.fieldId });
-
-    return DatabaseEventDuplicateField(payload);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts
deleted file mode 100644
index 2234c06dbd..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import { Log } from '$app/utils/log';
-import { DatabaseBackendService } from '../database_bd_svc';
-import { DatabaseFieldChangesetObserver } from './field_observer';
-import { FieldIdPB, FieldPB, IndexFieldPB } from '@/services/backend';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-
-export class FieldController {
-  private backendService: DatabaseBackendService;
-  private fieldChangesetObserver: DatabaseFieldChangesetObserver;
-  private numOfFieldsNotifier = new NumOfFieldsNotifier([]);
-
-  constructor(public readonly viewId: string) {
-    this.backendService = new DatabaseBackendService(viewId);
-    this.fieldChangesetObserver = new DatabaseFieldChangesetObserver(viewId);
-  }
-
-  dispose = async () => {
-    this.numOfFieldsNotifier.unsubscribe();
-    await this.fieldChangesetObserver.unsubscribe();
-  };
-
-  get fieldInfos(): readonly FieldInfo[] {
-    return this.numOfFieldsNotifier.fieldInfos;
-  }
-
-  getField = (fieldId: string): FieldInfo | undefined => {
-    return this.numOfFieldsNotifier.fieldInfos.find((element) => element.field.id === fieldId);
-  };
-
-  loadFields = async (fieldIds: FieldIdPB[]) => {
-    const result = await this.backendService.getFields(fieldIds);
-
-    if (result.ok) {
-      this.numOfFieldsNotifier.fieldInfos = result.val.map((field) => new FieldInfo(field));
-    } else {
-      Log.error(result.val);
-    }
-  };
-
-  subscribe = (callbacks: { onNumOfFieldsChanged?: (fieldInfos: readonly FieldInfo[]) => void }) => {
-    this.numOfFieldsNotifier.observer?.subscribe((fieldInfos) => {
-      callbacks.onNumOfFieldsChanged?.(fieldInfos);
-    });
-  };
-
-  initialize = async () => {
-    await this.fieldChangesetObserver.subscribe({
-      onFieldsChanged: (result) => {
-        if (result.ok) {
-          const changeset = result.val;
-
-          this._deleteFields(changeset.deleted_fields);
-          this._insertFields(changeset.inserted_fields);
-          this._updateFields(changeset.updated_fields);
-        } else {
-          Log.error(result.val);
-        }
-      },
-    });
-  };
-
-  private _deleteFields = (deletedFields: FieldIdPB[]) => {
-    if (deletedFields.length === 0) {
-      return;
-    }
-
-    const deletedFieldIds = deletedFields.map((field) => field.field_id);
-    const predicate = (element: FieldInfo): boolean => {
-      return !deletedFieldIds.includes(element.field.id);
-    };
-
-    this.numOfFieldsNotifier.fieldInfos = [...this.fieldInfos].filter(predicate);
-  };
-
-  private _insertFields = (insertedFields: IndexFieldPB[]) => {
-    if (insertedFields.length === 0) {
-      return;
-    }
-
-    const newFieldInfos = [...this.fieldInfos];
-
-    insertedFields.forEach((insertedField) => {
-      const fieldInfo = new FieldInfo(insertedField.field);
-
-      if (newFieldInfos.length > insertedField.index) {
-        newFieldInfos.splice(insertedField.index, 0, fieldInfo);
-      } else {
-        newFieldInfos.push(fieldInfo);
-      }
-    });
-    this.numOfFieldsNotifier.fieldInfos = newFieldInfos;
-  };
-
-  private _updateFields = (updatedFields: FieldPB[]) => {
-    if (updatedFields.length === 0) {
-      return;
-    }
-
-    const newFieldInfos = [...this.fieldInfos];
-
-    updatedFields.forEach((updatedField) => {
-      const index = newFieldInfos.findIndex((fieldInfo) => {
-        return fieldInfo.field.id === updatedField.id;
-      });
-
-      if (index !== -1) {
-        newFieldInfos.splice(index, 1, new FieldInfo(updatedField));
-      }
-    });
-    this.numOfFieldsNotifier.fieldInfos = newFieldInfos;
-  };
-}
-
-class NumOfFieldsNotifier extends ChangeNotifier<FieldInfo[]> {
-  constructor(private _fieldInfos: FieldInfo[]) {
-    super();
-  }
-
-  set fieldInfos(newFieldInfos: FieldInfo[]) {
-    if (this._fieldInfos !== newFieldInfos) {
-      this._fieldInfos = newFieldInfos;
-      this.notify(this._fieldInfos);
-    }
-  }
-
-  /// Return a readonly list
-  get fieldInfos(): FieldInfo[] {
-    return this._fieldInfos;
-  }
-}
-
-export class FieldInfo {
-  constructor(public readonly field: FieldPB) {}
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts
deleted file mode 100644
index 162c5c972a..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { Ok, Result } from "ts-results";
-import { DatabaseNotification, DatabaseFieldChangesetPB, FlowyError, FieldPB } from "@/services/backend";
-import { ChangeNotifier } from "$app/utils/change_notifier";
-import { DatabaseNotificationObserver } from "../notifications/observer";
-
-export type FieldChangesetSubscribeCallback = (value: Result<DatabaseFieldChangesetPB, FlowyError>) => void;
-
-export class DatabaseFieldChangesetObserver {
-  private notifier?: ChangeNotifier<Result<DatabaseFieldChangesetPB, FlowyError>>;
-  private listener?: DatabaseNotificationObserver;
-
-  constructor(public readonly viewId: string) {
-  }
-
-  subscribe = async (callbacks: { onFieldsChanged: FieldChangesetSubscribeCallback }) => {
-    this.notifier = new ChangeNotifier();
-    this.notifier?.observer?.subscribe(callbacks.onFieldsChanged);
-
-    this.listener = new DatabaseNotificationObserver({
-      id: this.viewId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case DatabaseNotification.DidUpdateFields:
-            if (result.ok) {
-              this.notifier?.notify(Ok(DatabaseFieldChangesetPB.deserializeBinary(result.val)));
-            } else {
-              this.notifier?.notify(result);
-            }
-
-            return;
-          default:
-            break;
-        }
-      }
-    });
-    await this.listener.start();
-  };
-
-  unsubscribe = async () => {
-    this.notifier?.unsubscribe();
-    await this.listener?.stop();
-  };
-}
-
-export type FieldSubscribeCallback = (value: Result<FieldPB, FlowyError>) => void;
-
-export class DatabaseFieldObserver {
-  private _notifier?: ChangeNotifier<Result<FieldPB, FlowyError>>;
-  private _listener?: DatabaseNotificationObserver;
-
-  constructor(public readonly fieldId: string) {
-  }
-
-  subscribe = async (callbacks: { onFieldChanged: FieldSubscribeCallback }) => {
-    this._notifier = new ChangeNotifier();
-    this._notifier?.observer?.subscribe(callbacks.onFieldChanged);
-
-    this._listener = new DatabaseNotificationObserver({
-      id: this.fieldId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case DatabaseNotification.DidUpdateField:
-            if (result.ok) {
-              this._notifier?.notify(Ok(FieldPB.deserializeBinary(result.val)));
-            } else {
-              this._notifier?.notify(result);
-            }
-
-            break;
-          default:
-            break;
-        }
-      }
-    });
-    await this._listener.start();
-  };
-
-  unsubscribe = async () => {
-    this._notifier?.unsubscribe();
-    await this._listener?.stop();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_bd_svc.ts
deleted file mode 100644
index eeca1dc102..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_bd_svc.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { CreateFieldPayloadPB, FieldType, UpdateFieldTypePayloadPB } from '@/services/backend';
-import {
-  DatabaseEventCreateField,
-  DatabaseEventUpdateFieldType,
-} from '@/services/backend/events/flowy-database2';
-
-export class TypeOptionBackendService {
-  constructor(public readonly viewId: string) {}
-
-  createTypeOption = (fieldType: FieldType) => {
-    const payload = CreateFieldPayloadPB.fromObject({ view_id: this.viewId, field_type: fieldType });
-
-    return DatabaseEventCreateField(payload);
-  };
-
-  updateTypeOptionType = (fieldId: string, fieldType: FieldType) => {
-    const payload = UpdateFieldTypePayloadPB.fromObject({
-      view_id: this.viewId,
-      field_id: fieldId,
-      field_type: fieldType,
-    });
-
-    return DatabaseEventUpdateFieldType(payload);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts
deleted file mode 100644
index 8f37673be7..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts
+++ /dev/null
@@ -1,209 +0,0 @@
-import { None, Option, Some } from 'ts-results';
-import { TypeOptionController } from './type_option_controller';
-import {
-  CheckboxTypeOptionPB,
-  ChecklistTypeOptionPB,
-  DateTypeOptionPB,
-  MultiSelectTypeOptionPB,
-  NumberTypeOptionPB,
-  SingleSelectTypeOptionPB,
-  URLTypeOptionPB,
-} from '@/services/backend';
-import { utf8Decoder, utf8Encoder } from '../../cell/data_parser';
-import { DatabaseFieldObserver } from '../field_observer';
-
-abstract class TypeOptionSerde<T> {
-  abstract deserialize(buffer: Uint8Array): T;
-
-  abstract serialize(value: T): Uint8Array;
-}
-
-// RichText
-export function makeRichTextTypeOptionContext(controller: TypeOptionController): RichTextTypeOptionContext {
-  const parser = new RichTextTypeOptionSerde();
-
-  return new TypeOptionContext<string>(parser, controller);
-}
-
-export type RichTextTypeOptionContext = TypeOptionContext<string>;
-
-class RichTextTypeOptionSerde extends TypeOptionSerde<string> {
-  deserialize(buffer: Uint8Array): string {
-    return utf8Decoder.decode(buffer);
-  }
-
-  serialize(value: string): Uint8Array {
-    return utf8Encoder.encode(value);
-  }
-}
-
-// Number
-export function makeNumberTypeOptionContext(controller: TypeOptionController): NumberTypeOptionContext {
-  const parser = new NumberTypeOptionSerde();
-
-  return new TypeOptionContext<NumberTypeOptionPB>(parser, controller);
-}
-
-export type NumberTypeOptionContext = TypeOptionContext<NumberTypeOptionPB>;
-
-class NumberTypeOptionSerde extends TypeOptionSerde<NumberTypeOptionPB> {
-  deserialize(buffer: Uint8Array): NumberTypeOptionPB {
-    return NumberTypeOptionPB.deserializeBinary(buffer);
-  }
-
-  serialize(value: NumberTypeOptionPB): Uint8Array {
-    return value.serializeBinary();
-  }
-}
-
-// Checkbox
-export function makeCheckboxTypeOptionContext(controller: TypeOptionController): CheckboxTypeOptionContext {
-  const parser = new CheckboxTypeOptionSerde();
-
-  return new TypeOptionContext<CheckboxTypeOptionPB>(parser, controller);
-}
-
-export type CheckboxTypeOptionContext = TypeOptionContext<CheckboxTypeOptionPB>;
-
-class CheckboxTypeOptionSerde extends TypeOptionSerde<CheckboxTypeOptionPB> {
-  deserialize(buffer: Uint8Array): CheckboxTypeOptionPB {
-    return CheckboxTypeOptionPB.deserializeBinary(buffer);
-  }
-
-  serialize(value: CheckboxTypeOptionPB): Uint8Array {
-    return value.serializeBinary();
-  }
-}
-
-// URL
-export function makeURLTypeOptionContext(controller: TypeOptionController): URLTypeOptionContext {
-  const parser = new URLTypeOptionSerde();
-
-  return new TypeOptionContext<URLTypeOptionPB>(parser, controller);
-}
-
-export type URLTypeOptionContext = TypeOptionContext<URLTypeOptionPB>;
-
-class URLTypeOptionSerde extends TypeOptionSerde<URLTypeOptionPB> {
-  deserialize(buffer: Uint8Array): URLTypeOptionPB {
-    return URLTypeOptionPB.deserializeBinary(buffer);
-  }
-
-  serialize(value: URLTypeOptionPB): Uint8Array {
-    return value.serializeBinary();
-  }
-}
-
-// Date
-export function makeDateTypeOptionContext(controller: TypeOptionController): DateTypeOptionContext {
-  const parser = new DateTypeOptionSerde();
-
-  return new TypeOptionContext<DateTypeOptionPB>(parser, controller);
-}
-
-export type DateTypeOptionContext = TypeOptionContext<DateTypeOptionPB>;
-
-class DateTypeOptionSerde extends TypeOptionSerde<DateTypeOptionPB> {
-  deserialize(buffer: Uint8Array): DateTypeOptionPB {
-    return DateTypeOptionPB.deserializeBinary(buffer);
-  }
-
-  serialize(value: DateTypeOptionPB): Uint8Array {
-    return value.serializeBinary();
-  }
-}
-
-// SingleSelect
-export function makeSingleSelectTypeOptionContext(controller: TypeOptionController): SingleSelectTypeOptionContext {
-  const parser = new SingleSelectTypeOptionSerde();
-
-  return new TypeOptionContext<SingleSelectTypeOptionPB>(parser, controller);
-}
-
-export type SingleSelectTypeOptionContext = TypeOptionContext<SingleSelectTypeOptionPB>;
-
-class SingleSelectTypeOptionSerde extends TypeOptionSerde<SingleSelectTypeOptionPB> {
-  deserialize(buffer: Uint8Array): SingleSelectTypeOptionPB {
-    return SingleSelectTypeOptionPB.deserializeBinary(buffer);
-  }
-
-  serialize(value: SingleSelectTypeOptionPB): Uint8Array {
-    return value.serializeBinary();
-  }
-}
-
-// Multi-select
-export function makeMultiSelectTypeOptionContext(controller: TypeOptionController): MultiSelectTypeOptionContext {
-  const parser = new MultiSelectTypeOptionSerde();
-
-  return new TypeOptionContext<MultiSelectTypeOptionPB>(parser, controller);
-}
-
-export type MultiSelectTypeOptionContext = TypeOptionContext<MultiSelectTypeOptionPB>;
-
-class MultiSelectTypeOptionSerde extends TypeOptionSerde<MultiSelectTypeOptionPB> {
-  deserialize(buffer: Uint8Array): MultiSelectTypeOptionPB {
-    return MultiSelectTypeOptionPB.deserializeBinary(buffer);
-  }
-
-  serialize(value: MultiSelectTypeOptionPB): Uint8Array {
-    return value.serializeBinary();
-  }
-}
-
-// Checklist
-export function makeChecklistTypeOptionContext(controller: TypeOptionController): ChecklistTypeOptionContext {
-  const parser = new ChecklistTypeOptionSerde();
-
-  return new TypeOptionContext<ChecklistTypeOptionPB>(parser, controller);
-}
-
-export type ChecklistTypeOptionContext = TypeOptionContext<ChecklistTypeOptionPB>;
-
-class ChecklistTypeOptionSerde extends TypeOptionSerde<ChecklistTypeOptionPB> {
-  deserialize(buffer: Uint8Array): ChecklistTypeOptionPB {
-    return ChecklistTypeOptionPB.deserializeBinary(buffer);
-  }
-
-  serialize(value: ChecklistTypeOptionPB): Uint8Array {
-    return value.serializeBinary();
-  }
-}
-
-export class TypeOptionContext<T> {
-  private typeOption: Option<T>;
-  private fieldObserver: DatabaseFieldObserver;
-
-  constructor(public readonly parser: TypeOptionSerde<T>, private readonly controller: TypeOptionController) {
-    this.typeOption = None;
-    this.fieldObserver = new DatabaseFieldObserver(controller.fieldId);
-
-    void this.fieldObserver.subscribe({
-      onFieldChanged: () => {
-        void this.getTypeOption();
-      },
-    });
-  }
-
-  get viewId(): string {
-    return this.controller.viewId;
-  }
-
-  getTypeOption = (): T => {
-    const type_option_data = this.controller.getTypeOption();
-    const typeOption = this.parser.deserialize(type_option_data);
-
-    this.typeOption = Some(typeOption);
-    return typeOption;
-  };
-
-  // Save the typeOption to disk
-  setTypeOption = async (typeOption: T) => {
-    await this.controller.saveTypeOption(this.parser.serialize(typeOption));
-    this.typeOption = Some(typeOption);
-  };
-
-  dispose = async () => {
-    await this.fieldObserver.unsubscribe();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts
deleted file mode 100644
index 342a910206..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import { FieldPB, FieldType } from '@/services/backend';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { FieldBackendService } from '../field_bd_svc';
-import { Log } from '$app/utils/log';
-import { None, Option, Some } from 'ts-results';
-import { FieldInfo } from '../field_controller';
-import { TypeOptionBackendService } from './type_option_bd_svc';
-
-export class TypeOptionController {
-  private fieldNotifier = new ChangeNotifier<FieldPB>();
-  private field: Option<FieldPB>;
-  private fieldBackendSvc?: FieldBackendService;
-  private typeOptionBackendSvc: TypeOptionBackendService;
-
-  // Must call [initialize] if the passed-in fieldInfo is None
-  constructor(
-    public readonly viewId: string,
-    private readonly initialFieldInfo: Option<FieldInfo> = None,
-    private readonly defaultFieldType: FieldType = FieldType.RichText
-  ) {
-    if (initialFieldInfo.none) {
-      this.field = None;
-    } else {
-      this.field = Some(initialFieldInfo.val.field);    
-      this.fieldBackendSvc = new FieldBackendService(this.viewId, initialFieldInfo.val.field.id);
-    }
-
-    this.typeOptionBackendSvc = new TypeOptionBackendService(viewId);
-  }
-
-  // It will create a new field for the defaultFieldType if the [initialFieldInfo] is None.
-  // Otherwise, it will get the type option of the [initialFieldInfo]
-  initialize = async () => {
-    if (this.initialFieldInfo.none) {
-      await this.createTypeOption(this.defaultFieldType);
-    }
-  };
-
-  get fieldId(): string {
-    return this.getFieldInfo().field.id;
-  }
-
-  get fieldType(): FieldType {
-    return this.getFieldInfo().field.field_type;
-  }
-
-  getFieldInfo = (): FieldInfo => {
-    if (this.field.none) {
-      if (this.initialFieldInfo.some) {
-        return this.initialFieldInfo.val;
-      } else {
-        throw Error('Unexpected empty type option data. Should call initialize first');
-      }
-    }
-
-    return new FieldInfo(this.field.val);
-  };
-
-  switchToField = async (fieldType: FieldType) => {
-    if (this.field.some) {
-      this.field.val.field_type = fieldType;
-      await this.typeOptionBackendSvc.updateTypeOptionType(this.fieldId, fieldType).then((result) => {
-        if (result.err) {
-          Log.error(result.val);
-        }
-      });
-      this.fieldNotifier.notify(this.field.val);
-    } else {
-      throw Error('Unexpected empty type option data. Should call initialize first');
-    }
-  };
-
-  setFieldName = async (name: string) => {
-    if (this.field.some) {
-      this.field.val.name = name;
-      void this.fieldBackendSvc?.updateField({ name: name });
-      this.fieldNotifier.notify(this.field.val);
-    } 
-  };
-
-  hideField = async () => {
-    if (this.fieldBackendSvc) {
-      void this.fieldBackendSvc.updateField({ visibility: false });
-    } else {
-      throw Error('Unexpected empty field backend service');
-    }
-  };
-
-  showField = async () => {
-    if (this.fieldBackendSvc) {
-      void this.fieldBackendSvc.updateField({ visibility: true });
-    } else {
-      throw Error('Unexpected empty field backend service');
-    }
-  };
-
-  changeWidth = async (width: number) => {
-    if (this.fieldBackendSvc) {
-      void this.fieldBackendSvc.updateField({ width: width });
-    } else {
-      throw Error('Unexpected empty field backend service');
-    }
-  };
-
-  saveTypeOption = async (data: Uint8Array) => {
-    if (this.field.some) {
-      this.field.val.type_option_data = data;
-      await this.fieldBackendSvc?.updateTypeOption(data).then((result) => {
-        if (result.err) {
-          Log.error(result.val);
-        }
-      });
-    } else {
-      throw Error('Unexpected empty type option data. Should call initialize first');
-    }
-  };
-
-  deleteField = async () => {
-    if (this.fieldBackendSvc === undefined) {
-      Log.error('Unexpected empty field backend service');
-    }
-
-    return this.fieldBackendSvc?.deleteField();
-  };
-
-  duplicateField = async () => {
-    if (this.fieldBackendSvc === undefined) {
-      Log.error('Unexpected empty field backend service');
-    }
-
-    return this.fieldBackendSvc?.duplicateField();
-  };
-
-  // Returns the type option for specific field with specific fieldType
-  getTypeOption = () => {
-    if (this.field.some) {
-      return this.field.val.type_option_data;
-    } else {
-      throw Error('Unexpected empty type option data. Should call initialize first');
-    }
-  };
-
-  private createTypeOption = async (fieldType: FieldType) => {
-    const result = await this.typeOptionBackendSvc.createTypeOption(fieldType);
-
-    if (result.ok) {
-      this.updateField(result.val);
-    }
-
-    return result;
-  };
-
-  private updateField = (field: FieldPB) => {
-    this.field = Some(field);    
-    this.fieldBackendSvc = new FieldBackendService(this.viewId, field.id);
-    this.fieldNotifier.notify(field);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/filter/filter_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/filter/filter_bd_svc.ts
deleted file mode 100644
index 3fa6982933..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/filter/filter_bd_svc.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import {
-  CheckboxFilterPB,
-  DatabaseSettingChangesetPB,
-  DatabaseViewIdPB,
-  DeleteFilterPayloadPB,
-  FieldType,
-  FilterPB,
-  FlowyError,
-  SelectOptionFilterPB,
-  TextFilterPB,
-  UpdateFilterPayloadPB,
-} from '@/services/backend';
-import {
-  DatabaseEventGetAllFilters,
-  DatabaseEventUpdateDatabaseSetting,
-} from '@/services/backend/events/flowy-database2';
-import { Err, Ok, Result } from 'ts-results';
-import { nanoid } from 'nanoid';
-
-export class FilterBackendService {
-  constructor(public readonly viewId: string) {}
-
-  getFilters = async (): Promise<Result<FilterParsed[], FlowyError>> => {
-    const payload = DatabaseViewIdPB.fromObject({
-      value: this.viewId,
-    });
-
-    const res = await DatabaseEventGetAllFilters(payload);
-
-    if (res.ok) {
-      return Ok(res.val.items.map<FilterParsed>((f) => new FilterParsed(this.viewId, f)));
-    } else {
-      return Err(res.val);
-    }
-  };
-
-  addFilter = async (
-    fieldId: string,
-    fieldType: FieldType,
-    filter: TextFilterPB | SelectOptionFilterPB | CheckboxFilterPB
-  ) => {
-    const data = filter.serializeBinary();
-    const id = nanoid(4);
-
-    await DatabaseEventUpdateDatabaseSetting(
-      DatabaseSettingChangesetPB.fromObject({
-        view_id: this.viewId,
-        update_filter: UpdateFilterPayloadPB.fromObject({
-          filter_id: id,
-          view_id: this.viewId,
-          field_id: fieldId,
-          field_type: fieldType,
-          data,
-        }),
-      })
-    );
-    return id;
-  };
-
-  updateFilter = (
-    filterId: string,
-    fieldId: string,
-    fieldType: FieldType,
-    filter: TextFilterPB | SelectOptionFilterPB | CheckboxFilterPB
-  ) => {
-    const data = filter.serializeBinary();
-
-    return DatabaseEventUpdateDatabaseSetting(
-      DatabaseSettingChangesetPB.fromObject({
-        view_id: this.viewId,
-        update_filter: UpdateFilterPayloadPB.fromObject({
-          view_id: this.viewId,
-          field_id: fieldId,
-          field_type: fieldType,
-          filter_id: filterId,
-          data,
-        }),
-      })
-    );
-  };
-
-  removeFilter = (fieldId: string, fieldType: FieldType, filterId: string) => {
-    return DatabaseEventUpdateDatabaseSetting(
-      DatabaseSettingChangesetPB.fromObject({
-        view_id: this.viewId,
-        delete_filter: DeleteFilterPayloadPB.fromObject({
-          view_id: this.viewId,
-          field_id: fieldId,
-          field_type: fieldType,
-          filter_id: filterId,
-        }),
-      })
-    );
-  };
-}
-
-export class FilterParsed {
-  view_id: string;
-  id: string;
-  field_id: string;
-  field_type: FieldType;
-  data: TextFilterPB | SelectOptionFilterPB | CheckboxFilterPB | Uint8Array;
-
-  constructor(view_id: string, filter: FilterPB) {
-    this.view_id = view_id;
-
-    this.id = filter.id;
-    this.field_id = filter.field_id;
-    this.field_type = filter.field_type;
-
-    switch (filter.field_type) {
-      case FieldType.RichText:
-        this.data = TextFilterPB.deserializeBinary(filter.data);
-        break;
-      case FieldType.SingleSelect:
-      case FieldType.MultiSelect:
-        this.data = SelectOptionFilterPB.deserializeBinary(filter.data);
-        break;
-      case FieldType.Checkbox:
-        this.data = CheckboxFilterPB.deserializeBinary(filter.data);
-        break;
-      default:
-        this.data = filter.data;
-        break;
-    }
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/filter/filter_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/filter/filter_controller.ts
deleted file mode 100644
index b56d1e8a58..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/filter/filter_controller.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { FilterBackendService, FilterParsed } from '$app/stores/effects/database/filter/filter_bd_svc';
-import { CheckboxFilterPB, FieldType, SelectOptionFilterPB, TextFilterPB } from '@/services/backend';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-
-export class FilterController {
-  filterService: FilterBackendService;
-  notifier: FilterNotifier;
-
-  constructor(public readonly viewId: string) {
-    this.filterService = new FilterBackendService(viewId);
-    this.notifier = new FilterNotifier();
-  }
-
-  initialize = async () => {
-    await this.readFilters();
-  };
-
-  readFilters = async () => {
-    const result = await this.filterService.getFilters();
-
-    if (result.ok) {
-      this.notifier.filters = result.val;
-    }
-  };
-
-  addFilter = async (
-    fieldId: string,
-    fieldType: FieldType,
-    filter: TextFilterPB | SelectOptionFilterPB | CheckboxFilterPB
-  ) => {
-    const id = await this.filterService.addFilter(fieldId, fieldType, filter);
-
-    await this.readFilters();
-    return id;
-  };
-
-  updateFilter = async (
-    filterId: string,
-    fieldId: string,
-    fieldType: FieldType,
-    filter: TextFilterPB | SelectOptionFilterPB | CheckboxFilterPB
-  ) => {
-    const result = await this.filterService.updateFilter(filterId, fieldId, fieldType, filter);
-
-    if (result.ok) {
-      await this.readFilters();
-    }
-  };
-
-  removeFilter = async (fieldId: string, fieldType: FieldType, filterId: string) => {
-    const result = await this.filterService.removeFilter(fieldId, fieldType, filterId);
-
-    if (result.ok) {
-      await this.readFilters();
-    }
-  };
-
-  subscribe = (callbacks: { onFiltersChanged?: (filters: FilterParsed[]) => void }) => {
-    if (callbacks.onFiltersChanged) {
-      this.notifier.observer?.subscribe(callbacks.onFiltersChanged);
-    }
-  };
-
-  dispose = () => {
-    this.notifier.unsubscribe();
-  };
-}
-
-class FilterNotifier extends ChangeNotifier<FilterParsed[]> {
-  private _filters: FilterParsed[] = [];
-
-  get filters(): FilterParsed[] {
-    return this._filters;
-  }
-
-  set filters(value: FilterParsed[]) {
-    this._filters = value;
-    this.notify(value);
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_controller.ts
deleted file mode 100644
index 0a5c8de4af..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_controller.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-import { DatabaseNotification, FlowyError, GroupPB, GroupRowsNotificationPB, RowMetaPB } from '@/services/backend';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { None, Ok, Option, Result, Some } from 'ts-results';
-import { DatabaseNotificationObserver } from '../notifications/observer';
-import { Log } from '$app/utils/log';
-import { DatabaseBackendService } from '../database_bd_svc';
-
-export type GroupDataCallbacks = {
-  onRemoveRow: (groupId: string, rowId: string) => void;
-  onInsertRow: (groupId: string, row: RowMetaPB, index?: number) => void;
-  onUpdateRow: (groupId: string, row: RowMetaPB) => void;
-
-  onCreateRow: (groupId: string, row: RowMetaPB) => void;
-};
-
-export class DatabaseGroupController {
-  private dataObserver: GroupDataObserver;
-  private callbacks?: GroupDataCallbacks;
-
-  constructor(private group: GroupPB, private databaseBackendSvc: DatabaseBackendService) {
-    this.dataObserver = new GroupDataObserver(group.group_id);
-  }
-
-  get groupId() {
-    return this.group.group_id;
-  }
-
-  get rows() {
-    return this.group.rows;
-  }
-
-  get name() {
-    return this.group.group_name;
-  }
-
-  updateGroup = (group: GroupPB) => {
-    this.group = group;
-  };
-
-  rowAtIndex = (index: number): Option<RowMetaPB> => {
-    if (this.group.rows.length < index) {
-      return None;
-    }
-
-    return Some(this.group.rows[index]);
-  };
-
-  initialize = async () => {
-    await this.dataObserver.subscribe({
-      onRowsChanged: (result) => {
-        if (result.ok) {
-          const changeset = result.val;
-
-          // Delete
-          changeset.deleted_rows.forEach((deletedRowId) => {
-            this.group.rows = this.group.rows.filter((row) => row.id !== deletedRowId);
-            this.callbacks?.onRemoveRow(this.group.group_id, deletedRowId);
-          });
-
-          // Insert
-          changeset.inserted_rows.forEach((insertedRow) => {
-            let index: number | undefined = insertedRow.index;
-
-            if (insertedRow.has_index && this.group.rows.length > insertedRow.index) {
-              this.group.rows.splice(index, 0, insertedRow.row_meta);
-            } else {
-              index = undefined;
-              this.group.rows.push(insertedRow.row_meta);
-            }
-
-            if (insertedRow.is_new) {
-              this.callbacks?.onCreateRow(this.group.group_id, insertedRow.row_meta);
-            } else {
-              this.callbacks?.onInsertRow(this.group.group_id, insertedRow.row_meta, index);
-            }
-          });
-
-          // Update
-          changeset.updated_rows.forEach((updatedRow) => {
-            const index = this.group.rows.findIndex((row) => row.id === updatedRow.id);
-
-            if (index !== -1) {
-              this.group.rows[index] = updatedRow;
-              this.callbacks?.onUpdateRow(this.group.group_id, updatedRow);
-            }
-          });
-        } else {
-          Log.error(result.val);
-        }
-      },
-    });
-  };
-
-  createRow = async () => {
-    return this.databaseBackendSvc.createRow({ groupId: this.group.group_id });
-  };
-
-  subscribe = (callbacks: GroupDataCallbacks) => {
-    this.callbacks = callbacks;
-  };
-
-  unsubscribe = () => {
-    this.callbacks = undefined;
-  };
-
-  dispose = async () => {
-    await this.dataObserver.unsubscribe();
-    this.callbacks = undefined;
-  };
-}
-
-type GroupRowsSubscribeCallback = (value: Result<GroupRowsNotificationPB, FlowyError>) => void;
-
-class GroupDataObserver {
-  private notifier?: ChangeNotifier<Result<GroupRowsNotificationPB, FlowyError>>;
-  private listener?: DatabaseNotificationObserver;
-
-  constructor(public readonly groupId: string) {}
-
-  subscribe = async (callbacks: { onRowsChanged: GroupRowsSubscribeCallback }) => {
-    this.notifier = new ChangeNotifier();
-    this.notifier?.observer?.subscribe(callbacks.onRowsChanged);
-
-    this.listener = new DatabaseNotificationObserver({
-      id: this.groupId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case DatabaseNotification.DidUpdateGroupRow:
-            if (result.ok) {
-              this.notifier?.notify(Ok(GroupRowsNotificationPB.deserializeBinary(result.val)));
-            } else {
-              this.notifier?.notify(result);
-            }
-
-            return;
-          default:
-            break;
-        }
-      },
-    });
-    await this.listener.start();
-  };
-
-  unsubscribe = async () => {
-    await this.listener?.stop();
-    this.notifier?.unsubscribe();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_observer.ts
deleted file mode 100644
index 7967351145..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_observer.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { Ok, Result } from 'ts-results';
-import { DatabaseNotification, FlowyError, GroupChangesPB, GroupPB } from '@/services/backend';
-import { DatabaseNotificationObserver } from '../notifications/observer';
-
-export type GroupByFieldCallback = (value: Result<GroupPB[], FlowyError>) => void;
-export type GroupChangesetSubscribeCallback = (value: Result<GroupChangesPB, FlowyError>) => void;
-
-export class DatabaseGroupObserver {
-  private groupByNotifier?: ChangeNotifier<Result<GroupPB[], FlowyError>>;
-  private groupChangesetNotifier?: ChangeNotifier<Result<GroupChangesPB, FlowyError>>;
-  private listener?: DatabaseNotificationObserver;
-
-  constructor(public readonly viewId: string) {}
-
-  subscribe = async (callbacks: {
-    onGroupBy: GroupByFieldCallback;
-    onGroupChangeset: GroupChangesetSubscribeCallback;
-  }) => {
-    this.groupByNotifier = new ChangeNotifier();
-    this.groupByNotifier?.observer?.subscribe(callbacks.onGroupBy);
-
-    this.groupChangesetNotifier = new ChangeNotifier();
-    this.groupChangesetNotifier?.observer?.subscribe(callbacks.onGroupChangeset);
-
-    this.listener = new DatabaseNotificationObserver({
-      id: this.viewId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case DatabaseNotification.DidGroupByField:
-            if (result.ok) {
-              this.groupByNotifier?.notify(Ok(GroupChangesPB.deserializeBinary(result.val).initial_groups));
-            } else {
-              this.groupByNotifier?.notify(result);
-            }
-
-            break;
-          case DatabaseNotification.DidUpdateNumOfGroups:
-            if (result.ok) {
-              this.groupChangesetNotifier?.notify(Ok(GroupChangesPB.deserializeBinary(result.val)));
-            } else {
-              this.groupChangesetNotifier?.notify(result);
-            }
-
-            break;
-          default:
-            break;
-        }
-      },
-    });
-
-    await this.listener.start();
-  };
-
-  unsubscribe = async () => {
-    this.groupByNotifier?.unsubscribe();
-    this.groupChangesetNotifier?.unsubscribe();
-    await this.listener?.stop();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts
deleted file mode 100644
index 210258cde8..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { DatabaseNotification, FlowyError } from '@/services/backend';
-import { AFNotificationObserver } from '@/services/backend/notifications';
-import { DatabaseNotificationParser } from './parser';
-import { Result } from 'ts-results';
-
-export type ParserHandler = (notification: DatabaseNotification, result: Result<Uint8Array, FlowyError>) => void;
-
-export class DatabaseNotificationObserver extends AFNotificationObserver<DatabaseNotification> {
-  constructor(params: { id?: string; parserHandler: ParserHandler }) {
-    const parser = new DatabaseNotificationParser({
-      callback: params.parserHandler,
-      id: params.id,
-    });
-
-    super(parser);
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/parser.ts
deleted file mode 100644
index caac06d1ba..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/parser.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { DatabaseNotification, FlowyError } from '@/services/backend';
-import { NotificationParser } from '@/services/backend/notifications';
-import { Result } from 'ts-results';
-
-declare type DatabaseNotificationCallback = (ty: DatabaseNotification, payload: Result<Uint8Array, FlowyError>) => void;
-
-export class DatabaseNotificationParser extends NotificationParser<DatabaseNotification> {
-  constructor(params: { id?: string; callback: DatabaseNotificationCallback }) {
-    super(
-      params.callback,
-      (ty) => {
-        const notification = DatabaseNotification[ty];
-
-        if (isDatabaseNotification(notification)) {
-          return DatabaseNotification[notification];
-        } else {
-          return DatabaseNotification.Unknown;
-        }
-      },
-      params.id
-    );
-  }
-}
-
-const isDatabaseNotification = (notification: string): notification is keyof typeof DatabaseNotification => {
-  return Object.values(DatabaseNotification).indexOf(notification) !== -1;
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_cache.ts
deleted file mode 100644
index a353fa6198..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_cache.ts
+++ /dev/null
@@ -1,414 +0,0 @@
-import {
-  InsertedRowPB,
-  UpdatedRowPB,
-  RowIdPB,
-  RowsChangePB,
-  RowsVisibilityChangePB,
-  ReorderSingleRowPB,
-  RowMetaPB,
-} from '@/services/backend';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { FieldInfo } from '../field/field_controller';
-import { CellCache, CellCacheKey } from '../cell/cell_cache';
-import { CellIdentifier } from '../cell/cell_bd_svc';
-import { DatabaseEventGetRowMeta } from '@/services/backend/events/flowy-database2';
-import { None, Option, Some } from 'ts-results';
-import { Log } from '$app/utils/log';
-
-export type CellByFieldId = Map<string, CellIdentifier>;
-
-export class RowCache {
-  private readonly rowList: RowList;
-  private readonly cellCache: CellCache;
-  private readonly notifier: RowChangeNotifier;
-
-  constructor(public readonly viewId: string, private readonly getFieldInfos: () => readonly FieldInfo[]) {
-    this.rowList = new RowList();
-    this.cellCache = new CellCache(viewId);
-    this.notifier = new RowChangeNotifier();
-  }
-
-  get rows(): readonly RowInfo[] {
-    return this.rowList.rows;
-  }
-
-  getCellCache = () => {
-    return this.cellCache;
-  };
-
-  loadCells = async (rowId: string): Promise<CellByFieldId> => {
-    const opRow = this.rowList.getRow(rowId);
-
-    if (opRow.some) {
-      return this._toCellMap(opRow.val.row.id, this.getFieldInfos());
-    } else {
-      const rowResult = await this._loadRow(rowId);
-
-      if (rowResult.ok) {
-        this._refreshRow(rowResult.val);
-        return this._toCellMap(rowId, this.getFieldInfos());
-      } else {
-        Log.error(rowResult.val);
-        return new Map();
-      }
-    }
-  };
-
-  subscribe = (callbacks: {
-    onRowsChanged: (reason: RowChangedReason, cellMap?: Map<string, CellIdentifier>) => void;
-  }) => {
-    return this.notifier.observer?.subscribe((change) => {
-      if (change.rowId !== undefined) {
-        callbacks.onRowsChanged(change.reason, this._toCellMap(change.rowId, this.getFieldInfos()));
-      } else {
-        callbacks.onRowsChanged(change.reason);
-      }
-    });
-  };
-
-  onFieldUpdated = (fieldInfo: FieldInfo) => {
-    // Remove the cell data if the corresponding field was changed
-    this.cellCache.removeWithFieldId(fieldInfo.field.id);
-  };
-
-  onNumberOfFieldsUpdated = (fieldInfos: readonly FieldInfo[]) => {
-    this.rowList.setFieldInfos(fieldInfos);
-    this.notifier.withChange(RowChangedReason.FieldDidChanged);
-  };
-
-  initializeRows = (rows: RowMetaPB[]) => {
-    rows.forEach((rowPB) => {
-      this.rowList.push(this._toRowInfo(rowPB));
-    });
-    this.notifier.withChange(RowChangedReason.ReorderRows);
-  };
-
-  applyRowsChanged = (changeset: RowsChangePB) => {
-    this._deleteRows(changeset.deleted_rows);
-    this._insertRows(changeset.inserted_rows);
-    this._updateRows(changeset.updated_rows);
-  };
-
-  applyRowsVisibility = (changeset: RowsVisibilityChangePB) => {
-    this._hideRows(changeset.invisible_rows);
-    this._displayRows(changeset.visible_rows);
-  };
-
-  applyReorderRows = (rowIds: string[]) => {
-    this.rowList.reorderByRowIds(rowIds);
-    this.notifier.withChange(RowChangedReason.ReorderRows);
-  };
-
-  applyReorderSingleRow = (reorderRow: ReorderSingleRowPB) => {
-    const rowInfo = this.rowList.getRow(reorderRow.row_id);
-
-    if (rowInfo !== undefined) {
-      this.rowList.move({ rowId: reorderRow.row_id, fromIndex: reorderRow.old_index, toIndex: reorderRow.new_index });
-      this.notifier.withChange(RowChangedReason.ReorderSingleRow, reorderRow.row_id);
-    }
-  };
-
-  private _refreshRow = (updatedRow: RowMetaPB) => {
-    const option = this.rowList.getRowWithIndex(updatedRow.id);
-
-    if (option.some) {
-      const { rowInfo, index } = option.val;
-
-      this.rowList.remove(rowInfo.row.id);
-      this.rowList.insert(index, rowInfo.copyWith({ row: updatedRow }));
-    } else {
-      const newRowInfo = new RowInfo(this.viewId, this.getFieldInfos(), updatedRow);
-
-      this.rowList.push(newRowInfo);
-    }
-  };
-
-  private _loadRow = (rowId: string) => {
-    const payload = RowIdPB.fromObject({ view_id: this.viewId, row_id: rowId });
-
-    return DatabaseEventGetRowMeta(payload);
-  };
-
-  private _deleteRows = (rowIds: string[]) => {
-    rowIds.forEach((rowId) => {
-      const deletedRow = this.rowList.remove(rowId);
-
-      if (deletedRow !== undefined) {
-        this.notifier.withChange(RowChangedReason.Delete, deletedRow.rowInfo.row.id);
-      }
-    });
-  };
-
-  private _insertRows = (rows: InsertedRowPB[]) => {
-    rows.forEach((insertedRow) => {
-      const rowInfo = this._toRowInfo(insertedRow.row_meta);
-      const insertedIndex = this.rowList.insert(insertedRow.index, rowInfo);
-
-      if (insertedIndex !== undefined) {
-        this.notifier.withChange(RowChangedReason.Insert, insertedIndex.rowId);
-      }
-    });
-  };
-
-  private _updateRows = (updatedRows: UpdatedRowPB[]) => {
-    if (updatedRows.length === 0) {
-      return;
-    }
-
-    const rowInfos: RowInfo[] = [];
-
-    updatedRows.forEach((updatedRow) => {
-      updatedRow.field_ids.forEach((fieldId) => {
-        const key = new CellCacheKey(fieldId, updatedRow.row_meta.id);
-
-        this.cellCache.remove(key);
-      });
-
-      rowInfos.push(this._toRowInfo(updatedRow.row_meta));
-    });
-
-    const updatedIndexs = this.rowList.insertRows(rowInfos);
-
-    updatedIndexs.forEach((row) => {
-      this.notifier.withChange(RowChangedReason.Update, row.rowId);
-    });
-  };
-
-  private _hideRows = (rowIds: string[]) => {
-    rowIds.forEach((rowId) => {
-      const deletedRow = this.rowList.remove(rowId);
-
-      if (deletedRow !== undefined) {
-        this.notifier.withChange(RowChangedReason.Delete, deletedRow.rowInfo.row.id);
-      }
-    });
-  };
-
-  private _displayRows = (insertedRows: InsertedRowPB[]) => {
-    insertedRows.forEach((insertedRow) => {
-      const insertedIndex = this.rowList.insert(insertedRow.index, this._toRowInfo(insertedRow.row_meta));
-
-      if (insertedIndex !== undefined) {
-        this.notifier.withChange(RowChangedReason.Insert, insertedIndex.rowId);
-      }
-    });
-  };
-
-  dispose = async () => {
-    this.notifier.dispose();
-  };
-
-  private _toRowInfo = (rowPB: RowMetaPB) => {
-    return new RowInfo(this.viewId, this.getFieldInfos(), rowPB);
-  };
-
-  private _toCellMap = (rowId: string, fieldInfos: readonly FieldInfo[]): CellByFieldId => {
-    const cellIdentifierByFieldId: Map<string, CellIdentifier> = new Map();
-
-    fieldInfos.forEach((fieldInfo) => {
-      const identifier = new CellIdentifier(this.viewId, rowId, fieldInfo.field.id, fieldInfo.field.field_type);
-
-      cellIdentifierByFieldId.set(fieldInfo.field.id, identifier);
-    });
-
-    return cellIdentifierByFieldId;
-  };
-}
-
-class RowList {
-  _rowInfos: RowInfo[] = [];
-  _rowInfoByRowId: Map<string, RowInfo> = new Map();
-
-  get rows(): readonly RowInfo[] {
-    return this._rowInfos;
-  }
-
-  getRow = (rowId: string): Option<RowInfo> => {
-    const rowInfo = this._rowInfoByRowId.get(rowId);
-
-    if (rowInfo === undefined) {
-      return None;
-    } else {
-      return Some(rowInfo);
-    }
-  };
-  getRowWithIndex = (rowId: string): Option<{ rowInfo: RowInfo; index: number }> => {
-    const rowInfo = this._rowInfoByRowId.get(rowId);
-
-    if (rowInfo !== undefined) {
-      const index = this._rowInfos.indexOf(rowInfo, 0);
-
-      return Some({ rowInfo: rowInfo, index: index });
-    }
-
-    return None;
-  };
-
-  indexOfRow = (rowId: string): number => {
-    const rowInfo = this._rowInfoByRowId.get(rowId);
-
-    if (rowInfo !== undefined) {
-      return this._rowInfos.indexOf(rowInfo, 0);
-    }
-
-    return -1;
-  };
-
-  push = (rowInfo: RowInfo) => {
-    const index = this.indexOfRow(rowInfo.row.id);
-
-    if (index !== -1) {
-      this._rowInfos.splice(index, 1, rowInfo);
-    } else {
-      this._rowInfos.push(rowInfo);
-    }
-
-    this._rowInfoByRowId.set(rowInfo.row.id, rowInfo);
-  };
-
-  remove = (rowId: string): DeletedRow | undefined => {
-    const result = this.getRowWithIndex(rowId);
-
-    if (result.some) {
-      const { rowInfo, index } = result.val;
-
-      this._rowInfoByRowId.delete(rowInfo.row.id);
-      this._rowInfos.splice(index, 1);
-      return new DeletedRow(index, rowInfo);
-    } else {
-      return undefined;
-    }
-  };
-
-  insert = (insertIndex: number, newRowInfo: RowInfo): InsertedRow | undefined => {
-    const rowId = newRowInfo.row.id;
-    // Calibrate where to insert
-    let insertedIndex = insertIndex;
-
-    if (this._rowInfos.length <= insertedIndex) {
-      insertedIndex = this._rowInfos.length;
-    }
-
-    const result = this.getRowWithIndex(rowId);
-
-    if (result.some) {
-      const { index } = result.val;
-
-      // remove the old row info
-      this._rowInfos.splice(index, 1);
-      // insert the new row info to the insertedIndex
-      this._rowInfos.splice(insertedIndex, 0, newRowInfo);
-      this._rowInfoByRowId.set(rowId, newRowInfo);
-      return undefined;
-    } else {
-      this._rowInfos.splice(insertedIndex, 0, newRowInfo);
-      this._rowInfoByRowId.set(rowId, newRowInfo);
-      return new InsertedRow(insertedIndex, rowId);
-    }
-  };
-
-  insertRows = (rowInfos: RowInfo[]) => {
-    const map = new Map<string, InsertedRow>();
-
-    rowInfos.forEach((rowInfo) => {
-      const index = this.indexOfRow(rowInfo.row.id);
-
-      if (index !== -1) {
-        this._rowInfos.splice(index, 1, rowInfo);
-        this._rowInfoByRowId.set(rowInfo.row.id, rowInfo);
-
-        map.set(rowInfo.row.id, new InsertedRow(index, rowInfo.row.id));
-      }
-    });
-    return map;
-  };
-
-  move = (params: { rowId: string; fromIndex: number; toIndex: number }) => {
-    const currentIndex = this.indexOfRow(params.rowId);
-
-    if (currentIndex !== -1 && currentIndex !== params.toIndex) {
-      const rowInfo = this.remove(params.rowId)?.rowInfo;
-
-      if (rowInfo !== undefined) {
-        this.insert(params.toIndex, rowInfo);
-      }
-    }
-  };
-
-  reorderByRowIds = (rowIds: string[]) => {
-    // remove all the elements
-    this._rowInfos = [];
-    rowIds.forEach((rowId) => {
-      const rowInfo = this._rowInfoByRowId.get(rowId);
-
-      if (rowInfo !== undefined) {
-        this._rowInfos.push(rowInfo);
-      }
-    });
-  };
-
-  includes = (rowId: string): boolean => {
-    return this._rowInfoByRowId.has(rowId);
-  };
-
-  setFieldInfos = (fieldInfos: readonly FieldInfo[]) => {
-    const newRowInfos: RowInfo[] = [];
-
-    this._rowInfos.forEach((rowInfo) => {
-      newRowInfos.push(rowInfo.copyWith({ fieldInfos: fieldInfos }));
-    });
-    this._rowInfos = newRowInfos;
-  };
-}
-
-export class RowInfo {
-  constructor(
-    public readonly viewId: string,
-    public readonly fieldInfos: readonly FieldInfo[],
-    public readonly row: RowMetaPB
-  ) {}
-
-  copyWith = (params: { row?: RowMetaPB; fieldInfos?: readonly FieldInfo[] }) => {
-    return new RowInfo(this.viewId, params.fieldInfos || this.fieldInfos, params.row || this.row);
-  };
-}
-
-export class DeletedRow {
-  constructor(public readonly index: number, public readonly rowInfo: RowInfo) {}
-}
-
-export class InsertedRow {
-  constructor(public readonly index: number, public readonly rowId: string) {}
-}
-
-export class RowChanged {
-  constructor(public readonly reason: RowChangedReason, public readonly rowId?: string) {}
-}
-
-// eslint-disable-next-line no-shadow
-export enum RowChangedReason {
-  Insert,
-  Delete,
-  Update,
-  Initial,
-  FieldDidChanged,
-  ReorderRows,
-  ReorderSingleRow,
-}
-
-export class RowChangeNotifier extends ChangeNotifier<RowChanged> {
-  _currentChanged = new RowChanged(RowChangedReason.Initial);
-
-  withChange = (reason: RowChangedReason, rowId?: string) => {
-    const newChange = new RowChanged(reason, rowId);
-
-    if (this._currentChanged !== newChange) {
-      this._currentChanged = newChange;
-      this.notify(this._currentChanged);
-    }
-  };
-
-  dispose = () => {
-    this.unsubscribe();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_controller.ts
deleted file mode 100644
index 7de6ee0e57..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_controller.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { CellByFieldId, RowCache, RowInfo } from './row_cache';
-import { FieldController } from '../field/field_controller';
-
-export class RowController {
-  constructor(
-    public readonly rowInfo: RowInfo,
-    public readonly fieldController: FieldController,
-    private readonly cache: RowCache
-  ) {
-    //
-  }
-
-  loadCells = async (): Promise<CellByFieldId> => {
-    return this.cache.loadCells(this.rowInfo.row.id);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/sort/sort_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/sort/sort_bd_svc.ts
deleted file mode 100644
index 1eabf080d2..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/sort/sort_bd_svc.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import {
-  DatabaseSettingChangesetPB,
-  DatabaseViewIdPB,
-  DeleteSortPayloadPB,
-  FieldType,
-  FlowyError,
-  SortConditionPB,
-  UpdateSortPayloadPB,
-} from '@/services/backend';
-import { DatabaseEventGetAllSorts, DatabaseEventUpdateDatabaseSetting } from '@/services/backend/events/flowy-database2';
-import { Err, Ok, Result } from 'ts-results';
-import { nanoid } from 'nanoid';
-import type { IDatabaseSort } from '$app_reducers/database/slice';
-
-export class SortBackendService {
-  constructor(public readonly viewId: string) {}
-
-  getSorts = async (): Promise<Result<IDatabaseSort[], FlowyError>> => {
-    const payload = DatabaseViewIdPB.fromObject({
-      value: this.viewId,
-    });
-
-    const res = await DatabaseEventGetAllSorts(payload);
-
-    if (res.ok) {
-      return Ok(
-        res.val.items.map<IDatabaseSort>((o) => ({
-          id: o.id,
-          fieldId: o.field_id,
-          fieldType: o.field_type,
-          order: o.condition,
-        }))
-      );
-    } else {
-      return Err(res.val);
-    }
-  };
-
-  addSort = async (fieldId: string, fieldType: FieldType, order: SortConditionPB) => {
-    const id = nanoid(4);
-
-    await DatabaseEventUpdateDatabaseSetting(
-      DatabaseSettingChangesetPB.fromObject({
-        view_id: this.viewId,
-        update_sort: UpdateSortPayloadPB.fromObject({
-          view_id: this.viewId,
-          field_id: fieldId,
-          field_type: fieldType,
-          sort_id: id,
-          condition: order,
-        }),
-      })
-    );
-    return id;
-  };
-
-  updateSort = (sortId: string, fieldId: string, fieldType: FieldType, order: SortConditionPB) => {
-    return DatabaseEventUpdateDatabaseSetting(
-      DatabaseSettingChangesetPB.fromObject({
-        view_id: this.viewId,
-        update_sort: UpdateSortPayloadPB.fromObject({
-          view_id: this.viewId,
-          field_id: fieldId,
-          field_type: fieldType,
-          sort_id: sortId,
-          condition: order,
-        }),
-      })
-    );
-  };
-
-  removeSort = (fieldId: string, fieldType: FieldType, sortId: string) => {
-    return DatabaseEventUpdateDatabaseSetting(
-      DatabaseSettingChangesetPB.fromObject({
-        view_id: this.viewId,
-        delete_sort: DeleteSortPayloadPB.fromObject({
-          view_id: this.viewId,
-          field_id: fieldId,
-          field_type: fieldType,
-          sort_id: sortId,
-        }),
-      })
-    );
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/sort/sort_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/sort/sort_controller.ts
deleted file mode 100644
index 2bf7dcde90..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/sort/sort_controller.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { FieldType, SortConditionPB } from '@/services/backend';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { IDatabaseSort } from '$app_reducers/database/slice';
-import { SortBackendService } from '$app/stores/effects/database/sort/sort_bd_svc';
-
-export class SortController {
-  sortService: SortBackendService;
-  notifier: SortNotifier;
-
-  constructor(public readonly viewId: string) {
-    this.sortService = new SortBackendService(viewId);
-    this.notifier = new SortNotifier();
-  }
-
-  initialize = async () => {
-    await this.readSorts();
-  };
-
-  readSorts = async () => {
-    const result = await this.sortService.getSorts();
-
-    if (result.ok) {
-      this.notifier.sorts = result.val;
-    }
-  };
-
-  addSort = async (fieldId: string, fieldType: FieldType, sort: SortConditionPB) => {
-    const id = await this.sortService.addSort(fieldId, fieldType, sort);
-
-    await this.readSorts();
-    return id;
-  };
-
-  updateSort = async (sortId: string, fieldId: string, fieldType: FieldType, sort: SortConditionPB) => {
-    const result = await this.sortService.updateSort(sortId, fieldId, fieldType, sort);
-
-    if (result.ok) {
-      await this.readSorts();
-    }
-  };
-
-  removeSort = async (fieldId: string, fieldType: FieldType, sortId: string) => {
-    const result = await this.sortService.removeSort(fieldId, fieldType, sortId);
-
-    if (result.ok) {
-      await this.readSorts();
-    }
-  };
-
-  subscribe = (callbacks: { onSortChanged?: (sorts: IDatabaseSort[]) => void }) => {
-    if (callbacks.onSortChanged) {
-      this.notifier.observer?.subscribe(callbacks.onSortChanged);
-    }
-  };
-
-  dispose = () => {
-    this.notifier.unsubscribe();
-  };
-}
-
-class SortNotifier extends ChangeNotifier<IDatabaseSort[]> {
-  private _sorts: IDatabaseSort[] = [];
-
-  get sorts(): IDatabaseSort[] {
-    return this._sorts;
-  }
-
-  set sorts(value: IDatabaseSort[]) {
-    this._sorts = value;
-    this.notify(value);
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts
deleted file mode 100644
index 072dae5189..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { DatabaseViewRowsObserver } from './view_row_observer';
-import { RowCache, RowInfo } from '../row/row_cache';
-import { FieldController } from '../field/field_controller';
-import { RowMetaPB } from '@/services/backend';
-
-export class DatabaseViewCache {
-  private readonly rowsObserver: DatabaseViewRowsObserver;
-  private readonly rowCache: RowCache;
-
-  constructor(public readonly viewId: string, fieldController: FieldController) {
-    this.rowsObserver = new DatabaseViewRowsObserver(viewId);
-    this.rowCache = new RowCache(viewId, () => fieldController.fieldInfos);
-    fieldController.subscribe({
-      onNumOfFieldsChanged: (fieldInfos) => {
-        fieldInfos.forEach((fieldInfo) => {
-          this.rowCache.onFieldUpdated(fieldInfo);
-        });
-        this.rowCache.onNumberOfFieldsUpdated(fieldInfos);
-      },
-    });
-  }
-
-  initializeWithRows = (rows: RowMetaPB[]) => {
-    this.rowCache.initializeRows(rows);
-  };
-
-  get rowInfos(): readonly RowInfo[] {
-    return this.rowCache.rows;
-  }
-
-  getRowCache = () => {
-    return this.rowCache;
-  };
-
-  dispose = async () => {
-    await this.rowsObserver.unsubscribe();
-    await this.rowCache.dispose();
-  };
-
-  initialize = async () => {
-    await this.rowsObserver.subscribe({
-      onRowsVisibilityChanged: (result) => {
-        if (result.ok) {
-          this.rowCache.applyRowsVisibility(result.val);
-        }
-      },
-      onNumberOfRowsChanged: (result) => {
-        if (result.ok) {
-          this.rowCache.applyRowsChanged(result.val);
-        }
-      },
-      onReorderRows: (result) => {
-        if (result.ok) {
-          this.rowCache.applyReorderRows(result.val);
-        }
-      },
-      onReorderSingleRow: (result) => {
-        if (result.ok) {
-          this.rowCache.applyReorderSingleRow(result.val);
-        }
-      },
-    });
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts
deleted file mode 100644
index 2b7a67e4f1..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import { Ok, Result } from 'ts-results';
-import {
-  DatabaseNotification,
-  FlowyError,
-  ReorderAllRowsPB,
-  ReorderSingleRowPB,
-  RowsChangePB,
-  RowsVisibilityChangePB,
-} from '@/services/backend';
-import { ChangeNotifier } from '$app/utils/change_notifier';
-import { DatabaseNotificationObserver } from '../notifications/observer';
-
-export type RowsVisibilityNotifyValue = Result<RowsVisibilityChangePB, FlowyError>;
-export type RowsNotifyValue = Result<RowsChangePB, FlowyError>;
-export type ReorderRowsNotifyValue = Result<string[], FlowyError>;
-export type ReorderSingleRowNotifyValue = Result<ReorderSingleRowPB, FlowyError>;
-
-export class DatabaseViewRowsObserver {
-  private rowsVisibilityNotifier = new ChangeNotifier<RowsVisibilityNotifyValue>();
-  private rowsNotifier = new ChangeNotifier<RowsNotifyValue>();
-  private reorderRowsNotifier = new ChangeNotifier<ReorderRowsNotifyValue>();
-  private reorderSingleRowNotifier = new ChangeNotifier<ReorderSingleRowNotifyValue>();
-
-  private _listener?: DatabaseNotificationObserver;
-
-  constructor(public readonly viewId: string) {}
-
-  subscribe = async (callbacks: {
-    onRowsVisibilityChanged?: (value: RowsVisibilityNotifyValue) => void;
-    onNumberOfRowsChanged?: (value: RowsNotifyValue) => void;
-    onReorderRows?: (value: ReorderRowsNotifyValue) => void;
-    onReorderSingleRow?: (value: ReorderSingleRowNotifyValue) => void;
-  }) => {
-    //
-    this.rowsVisibilityNotifier.observer?.subscribe(callbacks.onRowsVisibilityChanged);
-    this.rowsNotifier.observer?.subscribe(callbacks.onNumberOfRowsChanged);
-    this.reorderRowsNotifier.observer?.subscribe(callbacks.onReorderRows);
-    this.reorderSingleRowNotifier.observer?.subscribe(callbacks.onReorderSingleRow);
-
-    this._listener = new DatabaseNotificationObserver({
-      id: this.viewId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case DatabaseNotification.DidUpdateViewRowsVisibility:
-            if (result.ok) {
-              this.rowsVisibilityNotifier.notify(Ok(RowsVisibilityChangePB.deserializeBinary(result.val)));
-            } else {
-              this.rowsVisibilityNotifier.notify(result);
-            }
-
-            break;
-          case DatabaseNotification.DidUpdateViewRows:
-            if (result.ok) {
-              this.rowsNotifier.notify(Ok(RowsChangePB.deserializeBinary(result.val)));
-            } else {
-              this.rowsNotifier.notify(result);
-            }
-
-            break;
-          case DatabaseNotification.DidReorderRows:
-            if (result.ok) {
-              this.reorderRowsNotifier.notify(Ok(ReorderAllRowsPB.deserializeBinary(result.val).row_orders));
-            } else {
-              this.reorderRowsNotifier.notify(result);
-            }
-
-            break;
-          case DatabaseNotification.DidReorderSingleRow:
-            if (result.ok) {
-              this.reorderSingleRowNotifier.notify(Ok(ReorderSingleRowPB.deserializeBinary(result.val)));
-            } else {
-              this.reorderSingleRowNotifier.notify(result);
-            }
-
-            break;
-          default:
-            break;
-        }
-      },
-    });
-    await this._listener.start();
-  };
-
-  unsubscribe = async () => {
-    this.rowsVisibilityNotifier.unsubscribe();
-    this.reorderRowsNotifier.unsubscribe();
-    this.rowsNotifier.unsubscribe();
-    this.reorderSingleRowNotifier.unsubscribe();
-    await this._listener?.stop();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts
deleted file mode 100644
index 481c7de359..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import { nanoid } from '@reduxjs/toolkit';
-import {
-  AppearanceSettingsPB,
-  UserEventGetAppearanceSetting,
-  UserEventGetUserProfile,
-  UserEventGetUserSetting,
-  UserEventSetAppearanceSetting,
-  UserEventSignInWithEmailPassword,
-  UserEventSignOut,
-  UserEventSignUp,
-  UserEventUpdateUserProfile,
-} from '@/services/backend/events/flowy-user';
-import {
-  CreateWorkspacePayloadPB,
-  SignInPayloadPB,
-  SignUpPayloadPB,
-  UpdateUserProfilePayloadPB,
-  WorkspacePB,
-  WorkspaceSettingPB,
-} from '@/services/backend';
-import {
-  FolderEventCreateWorkspace,
-  FolderEventGetCurrentWorkspaceSetting,
-  FolderEventReadCurrentWorkspace,
-} from '@/services/backend/events/flowy-folder';
-
-export class UserBackendService {
-  constructor(public readonly userId: number) {}
-
-  static getUserProfile = () => {
-    return UserEventGetUserProfile();
-  };
-
-  updateUserProfile = (params: { name?: string; password?: string; email?: string; openAIKey?: string }) => {
-    const payload = UpdateUserProfilePayloadPB.fromObject({ id: this.userId });
-
-    if (params.name !== undefined) {
-      payload.name = params.name;
-    }
-
-    if (params.password !== undefined) {
-      payload.password = params.password;
-    }
-
-    if (params.email !== undefined) {
-      payload.email = params.email;
-    }
-
-    // if (params.openAIKey !== undefined) {
-    // }
-    return UserEventUpdateUserProfile(payload);
-  };
-
-  getCurrentWorkspaceSetting = async (): Promise<WorkspaceSettingPB> => {
-    const result = await FolderEventGetCurrentWorkspaceSetting();
-
-    if (result.ok) {
-      return result.val;
-    } else {
-      throw new Error(result.val.msg);
-    }
-  };
-
-  getWorkspaces = () => {
-    return FolderEventReadCurrentWorkspace();
-  };
-
-  createWorkspace = async (params: { name: string; desc: string }): Promise<WorkspacePB> => {
-    const payload = CreateWorkspacePayloadPB.fromObject({ name: params.name, desc: params.desc });
-    const result = await FolderEventCreateWorkspace(payload);
-
-    if (result.ok) {
-      return result.val;
-    } else {
-      throw new Error(result.val.msg);
-    }
-  };
-
-  signOut = () => {
-    return UserEventSignOut();
-  };
-
-  setAppearanceSettings = (params: ReturnType<typeof AppearanceSettingsPB.prototype.toObject>) => {
-    const payload = AppearanceSettingsPB.fromObject(params);
-
-    return UserEventSetAppearanceSetting(payload);
-  };
-
-  getAppearanceSettings = () => {
-    return UserEventGetAppearanceSetting();
-  };
-
-  getStorageSettings = () => {
-    return UserEventGetUserSetting();
-  };
-}
-
-export class AuthBackendService {
-  signIn = (params: { email: string; password: string }) => {
-    const payload = SignInPayloadPB.fromObject({ email: params.email, password: params.password });
-
-    return UserEventSignInWithEmailPassword(payload);
-  };
-
-  signUp = (params: { name: string; email: string; password: string }) => {
-    const deviceId = nanoid(8);
-    const payload = SignUpPayloadPB.fromObject({
-      name: params.name,
-      email: params.email,
-      password: params.password,
-      device_id: deviceId,
-    });
-
-    return UserEventSignUp(payload);
-  };
-
-  signOut = () => {
-    return UserEventSignOut();
-  };
-
-  autoSignUp = () => {
-    const password = 'AppFlowy123@';
-    const email = nanoid(4) + '@appflowy.io';
-
-    return this.signUp({ name: 'Me', email: email, password: password });
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_setting_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_setting_controller.ts
deleted file mode 100644
index ec4ea12c49..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_setting_controller.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import { UserBackendService } from '$app/stores/effects/user/user_bd_svc';
-import { AppearanceSettingsPB } from '@/services/backend';
-import { Theme, ThemeMode, UserSetting } from '$app/stores/reducers/current-user/slice';
-
-export class UserSettingController {
-  private readonly backendService: UserBackendService;
-  constructor(private userId: number) {
-    this.backendService = new UserBackendService(userId);
-  }
-
-  getStorageSettings = async () => {
-    const userSetting = await this.backendService.getStorageSettings();
-
-    if (userSetting.ok) {
-      return userSetting.val;
-    }
-
-    return {};
-  };
-
-  getAppearanceSetting = async (): Promise<Partial<UserSetting> | undefined> => {
-    const appearanceSetting = await this.backendService.getAppearanceSettings();
-
-    if (appearanceSetting.ok) {
-      const res = appearanceSetting.val;
-      const { locale, theme = Theme.Default, theme_mode = ThemeMode.Light } = res;
-      let language = 'en';
-
-      if (locale.language_code && locale.country_code) {
-        language = `${locale.language_code}-${locale.country_code}`;
-      } else if (locale.language_code) {
-        language = locale.language_code;
-      }
-
-      return {
-        themeMode: theme_mode,
-        theme: theme as Theme,
-        language: language,
-      };
-    }
-
-    return;
-  };
-
-  setAppearanceSetting = async (params: ReturnType<typeof AppearanceSettingsPB.prototype.toObject>) => {
-    const res = await this.backendService.setAppearanceSettings(params);
-
-    if (res.ok) {
-      return res.val;
-    }
-
-    return Promise.reject(res.err);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/notifications/observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/notifications/observer.ts
deleted file mode 100644
index 4633328944..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/notifications/observer.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { OnNotificationError, AFNotificationObserver } from '@/services/backend/notifications';
-import { FlowyError, FolderNotification } from '@/services/backend';
-import { Result } from 'ts-results';
-import { WorkspaceNotificationParser } from './parser';
-
-export type ParserHandler = (notification: FolderNotification, payload: Result<Uint8Array, FlowyError>) => void;
-
-export class WorkspaceNotificationObserver extends AFNotificationObserver<FolderNotification> {
-  constructor(params: { id?: string; parserHandler: ParserHandler; onError?: OnNotificationError }) {
-    const parser = new WorkspaceNotificationParser({
-      callback: params.parserHandler,
-      id: params.id,
-    });
-
-    super(parser);
-  }
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/notifications/parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/notifications/parser.ts
deleted file mode 100644
index cab08feee3..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/notifications/parser.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { NotificationParser, OnNotificationError } from '@/services/backend/notifications';
-import { FlowyError, FolderNotification } from '@/services/backend';
-import { Result } from 'ts-results';
-
-declare type WorkspaceNotificationCallback = (ty: FolderNotification, payload: Result<Uint8Array, FlowyError>) => void;
-
-export class WorkspaceNotificationParser extends NotificationParser<FolderNotification> {
-  constructor(params: { id?: string; callback: WorkspaceNotificationCallback; onError?: OnNotificationError }) {
-    super(
-      params.callback,
-      (ty) => {
-        const notification = FolderNotification[ty];
-
-        if (isFolderNotification(notification)) {
-          return FolderNotification[notification];
-        } else {
-          return FolderNotification.Unknown;
-        }
-      },
-      params.id
-    );
-  }
-}
-
-const isFolderNotification = (notification: string): notification is keyof typeof FolderNotification => {
-  return Object.values(FolderNotification).indexOf(notification) !== -1;
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/page/page_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/page/page_bd_svc.ts
deleted file mode 100644
index 6dc5752da0..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/page/page_bd_svc.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import {
-  FolderEventCreateView,
-  FolderEventUpdateView,
-  FolderEventDeleteView,
-  FolderEventDuplicateView,
-  FolderEventCloseView,
-  FolderEventImportData,
-  ViewIdPB,
-  CreateViewPayloadPB,
-  UpdateViewPayloadPB,
-  RepeatedViewIdPB,
-  ViewPB,
-  ImportPB,
-  MoveNestedViewPayloadPB,
-  FolderEventMoveNestedView,
-  ViewIconPB,
-  UpdateViewIconPayloadPB,
-  FolderEventUpdateViewIcon,
-  FolderEventCreateOrphanView,
-  CreateOrphanViewPayloadPB,
-  FolderEventGetView,
-} from '@/services/backend/events/flowy-folder';
-import { Page, PageIcon } from '$app_reducers/pages/slice';
-
-export class PageBackendService {
-  constructor() {
-    //
-  }
-
-  getPage = async (viewId: string) => {
-    const payload = new ViewIdPB({
-      value: viewId,
-    });
-
-    return FolderEventGetView(payload);
-  };
-
-  movePage = async (params: { viewId: string; parentId: string; prevId?: string }) => {
-    const payload = new MoveNestedViewPayloadPB({
-      view_id: params.viewId,
-      new_parent_id: params.parentId,
-      prev_view_id: params.prevId,
-    });
-
-    return FolderEventMoveNestedView(payload);
-  };
-
-  createPage = async (params: ReturnType<typeof CreateViewPayloadPB.prototype.toObject>) => {
-    const payload = CreateViewPayloadPB.fromObject(params);
-
-    return FolderEventCreateView(payload);
-  };
-
-  updatePage = async (page: { id: string } & Partial<Page>) => {
-    const payload = new UpdateViewPayloadPB();
-
-    payload.view_id = page.id;
-    if (page.name !== undefined) {
-      payload.name = page.name;
-    }
-
-    return FolderEventUpdateView(payload);
-  };
-
-  updatePageIcon = async (viewId: string, icon?: PageIcon) => {
-    const payload = new UpdateViewIconPayloadPB({
-      view_id: viewId,
-      icon: icon
-        ? new ViewIconPB({
-            ty: icon.ty,
-            value: icon.value,
-          })
-        : undefined,
-    });
-
-    return FolderEventUpdateViewIcon(payload);
-  };
-
-  deletePage = async (viewId: string) => {
-    const payload = new RepeatedViewIdPB({
-      items: [viewId],
-    });
-
-    return FolderEventDeleteView(payload);
-  };
-
-  duplicatePage = async (params: ReturnType<typeof ViewPB.prototype.toObject>) => {
-    const payload = ViewPB.fromObject(params);
-
-    return FolderEventDuplicateView(payload);
-  };
-
-  createOrphanPage = async (params: ReturnType<typeof CreateOrphanViewPayloadPB.prototype.toObject>) => {
-    const payload = CreateOrphanViewPayloadPB.fromObject(params);
-
-    return FolderEventCreateOrphanView(payload);
-  };
-
-  closePage = async (viewId: string) => {
-    const payload = new ViewIdPB({
-      value: viewId,
-    });
-
-    return FolderEventCloseView(payload);
-  };
-
-  importData = async (params: ReturnType<typeof ImportPB.prototype.toObject>) => {
-    const payload = ImportPB.fromObject(params);
-
-    return FolderEventImportData(payload);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/page/page_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/page/page_controller.ts
deleted file mode 100644
index 3ff5ac9530..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/page/page_controller.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-import { ViewLayoutPB, ViewPB } from '@/services/backend';
-import { PageBackendService } from '$app/stores/effects/workspace/page/page_bd_svc';
-import { WorkspaceObserver } from '$app/stores/effects/workspace/workspace_observer';
-import { Page, PageIcon, parserViewPBToPage } from '$app_reducers/pages/slice';
-
-export class PageController {
-  private readonly backendService: PageBackendService = new PageBackendService();
-
-  private readonly observer: WorkspaceObserver = new WorkspaceObserver();
-  constructor(private readonly id: string) {
-    //
-  }
-
-  dispose = async () => {
-    await this.observer.unsubscribe();
-  };
-
-  createPage = async (params: { name: string; layout: ViewLayoutPB }): Promise<string> => {
-    const result = await this.backendService.createPage({
-      name: params.name,
-      layout: params.layout,
-      parent_view_id: this.id,
-    });
-
-    if (result.ok) {
-      return result.val.id;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  movePage = async (params: { parentId: string; prevId?: string }): Promise<void> => {
-    const result = await this.backendService.movePage({
-      viewId: this.id,
-      parentId: params.parentId,
-      prevId: params.prevId,
-    });
-
-    if (result.ok) {
-      return result.val;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  getChildPages = async (): Promise<Page[]> => {
-    const result = await this.backendService.getPage(this.id);
-
-    if (result.ok) {
-      return result.val.child_views.map(parserViewPBToPage);
-    }
-
-    return [];
-  };
-
-  getPage = async (id?: string) => {
-    const result = await this.backendService.getPage(id || this.id);
-
-    if (result.ok) {
-      return parserViewPBToPage(result.val);
-    }
-
-    return Promise.reject(result.val);
-  };
-
-  getParentPage = async (): Promise<Page> => {
-    const page = await this.getPage();
-    const parentPageId = page.parentId;
-
-    return this.getPage(parentPageId);
-  };
-
-  subscribe = async (callbacks: { onPageChanged?: (page: Page, children: Page[]) => void }) => {
-    const didUpdateView = (payload: Uint8Array) => {
-      const res = ViewPB.deserializeBinary(payload);
-      const page = parserViewPBToPage(res);
-
-      const childPages = res.child_views.map(parserViewPBToPage);
-
-      callbacks.onPageChanged?.(page, childPages);
-    };
-
-    await this.observer.subscribeView(this.id, {
-      didUpdateView,
-    });
-  };
-
-  unsubscribe = async () => {
-    await this.observer.unsubscribe();
-  };
-
-  updatePage = async (page: { id: string } & Partial<Page>) => {
-    const result = await this.backendService.updatePage(page);
-
-    if (result.ok) {
-      return result.val.toObject();
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  updatePageIcon = async (icon?: PageIcon) => {
-    const result = await this.backendService.updatePageIcon(this.id, icon);
-
-    if (result.ok) {
-      return result.val;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  deletePage = async () => {
-    const result = await this.backendService.deletePage(this.id);
-
-    if (result.ok) {
-      return result.val;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  duplicatePage = async () => {
-    const page = await this.getPage();
-    const result = await this.backendService.duplicatePage(page);
-
-    if (result.ok) {
-      return result.val;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  createOrphanPage = async (params: { name: string; layout: ViewLayoutPB }): Promise<Page> => {
-    const result = await this.backendService.createOrphanPage({
-      view_id: this.id,
-      name: params.name,
-      layout: params.layout,
-    });
-
-    if (result.ok) {
-      return parserViewPBToPage(result.val);
-    }
-
-    return Promise.reject(result.val);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/trash/bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/trash/bd_svc.ts
deleted file mode 100644
index e57d74107b..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/trash/bd_svc.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import {
-  TrashIdPB,
-  RepeatedTrashIdPB,
-  FolderEventListTrashItems,
-  FolderEventRestoreTrashItem,
-  FolderEventPermanentlyDeleteTrashItem,
-  FolderEventPermanentlyDeleteAllTrashItem,
-  FolderEventRecoverAllTrashItems,
-} from '@/services/backend/events/flowy-folder';
-
-export class TrashBackendService {
-  constructor() {
-    //
-  }
-
-  getTrash = async () => {
-    return FolderEventListTrashItems();
-  };
-
-  putback = async (id: string) => {
-    const payload = new TrashIdPB({
-      id,
-    });
-
-    return FolderEventRestoreTrashItem(payload);
-  };
-
-  delete = async (ids: string[]) => {
-    const items = ids.map((id) => new TrashIdPB({ id }));
-    const payload = new RepeatedTrashIdPB({
-      items,
-    });
-
-    return FolderEventPermanentlyDeleteTrashItem(payload);
-  };
-
-  deleteAll = async () => {
-    return FolderEventPermanentlyDeleteAllTrashItem();
-  };
-
-  restoreAll = async () => {
-    return FolderEventRecoverAllTrashItems();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/trash/controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/trash/controller.ts
deleted file mode 100644
index 86563a0ab7..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/trash/controller.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { TrashBackendService } from '$app/stores/effects/workspace/trash/bd_svc';
-import { WorkspaceObserver } from '$app/stores/effects/workspace/workspace_observer';
-import { RepeatedTrashPB, TrashPB } from '@/services/backend';
-
-export class TrashController {
-  private readonly observer: WorkspaceObserver = new WorkspaceObserver();
-
-  private readonly backendService: TrashBackendService = new TrashBackendService();
-
-  subscribe = async (callbacks: { onTrashChanged?: (trash: TrashPB[]) => void }) => {
-    const didUpdateTrash = (payload: Uint8Array) => {
-      const res = RepeatedTrashPB.deserializeBinary(payload);
-
-      callbacks.onTrashChanged?.(res.items);
-    };
-
-    await this.observer.subscribeTrash({
-      didUpdateTrash,
-    });
-  };
-
-  dispose = async () => {
-    await this.observer.unsubscribe();
-  };
-  getTrash = async () => {
-    const res = await this.backendService.getTrash();
-
-    if (res.ok) {
-      return res.val.items;
-    }
-
-    return [];
-  };
-
-  putback = async (id: string) => {
-    const res = await this.backendService.putback(id);
-
-    if (res.ok) {
-      return res.val;
-    }
-
-    return Promise.reject(res.err);
-  };
-
-  delete = async (ids: string[]) => {
-    const res = await this.backendService.delete(ids);
-
-    if (res.ok) {
-      return res.val;
-    }
-
-    return Promise.reject(res.err);
-  };
-
-  deleteAll = async () => {
-    const res = await this.backendService.deleteAll();
-
-    if (res.ok) {
-      return res.val;
-    }
-
-    return Promise.reject(res.err);
-  };
-
-  restoreAll = async () => {
-    const res = await this.backendService.restoreAll();
-
-    if (res.ok) {
-      return res.val;
-    }
-
-    return Promise.reject(res.err);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_bd_svc.ts
deleted file mode 100644
index fc4d81f58b..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_bd_svc.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import {
-  FolderEventCreateWorkspace,
-  CreateWorkspacePayloadPB,
-  FolderEventDeleteWorkspace,
-  WorkspaceIdPB,
-  FolderEventReadWorkspaceViews,
-  FolderEventReadCurrentWorkspace,
-} from '@/services/backend/events/flowy-folder';
-import { UserEventOpenWorkspace, UserWorkspaceIdPB } from '@/services/backend/events/flowy-user';
-
-export class WorkspaceBackendService {
-  constructor() {
-    //
-  }
-
-  createWorkspace = async (params: ReturnType<typeof CreateWorkspacePayloadPB.prototype.toObject>) => {
-    const { name, desc } = params;
-    const payload = CreateWorkspacePayloadPB.fromObject({
-      name,
-      desc,
-    });
-
-    return FolderEventCreateWorkspace(payload);
-  };
-
-  openWorkspace = async (workspaceId: string) => {
-    const payload = new UserWorkspaceIdPB({
-      workspace_id: workspaceId,
-    });
-
-    return UserEventOpenWorkspace(payload);
-  };
-
-  deleteWorkspace = async (workspaceId: string) => {
-    const payload = new WorkspaceIdPB({
-      value: workspaceId,
-    });
-
-    return FolderEventDeleteWorkspace(payload);
-  };
-
-  getWorkspaces = async () => {
-    return FolderEventReadCurrentWorkspace();
-  };
-
-  getCurrentWorkspace = async () => {
-    return FolderEventReadCurrentWorkspace();
-  };
-
-  getChildPages = async (workspaceId: string) => {
-    const payload = new WorkspaceIdPB({
-      value: workspaceId,
-    });
-
-    return FolderEventReadWorkspaceViews(payload);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_controller.ts
deleted file mode 100644
index 56b7003c42..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_controller.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { WorkspaceBackendService } from '$app/stores/effects/workspace/workspace_bd_svc';
-import { WorkspaceObserver } from '$app/stores/effects/workspace/workspace_observer';
-import { CreateViewPayloadPB, RepeatedViewPB } from '@/services/backend';
-import { PageBackendService } from '$app/stores/effects/workspace/page/page_bd_svc';
-import { Page, parserViewPBToPage } from '$app_reducers/pages/slice';
-
-export class WorkspaceController {
-  private readonly observer: WorkspaceObserver = new WorkspaceObserver();
-  private readonly pageBackendService: PageBackendService;
-  private readonly backendService: WorkspaceBackendService;
-  constructor(private readonly workspaceId: string) {
-    this.pageBackendService = new PageBackendService();
-    this.backendService = new WorkspaceBackendService();
-  }
-
-  dispose = async () => {
-    await this.observer.unsubscribe();
-  };
-
-  open = async () => {
-    const result = await this.backendService.openWorkspace(this.workspaceId);
-
-    if (result.ok) {
-      return result.val;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  delete = async () => {
-    const result = await this.backendService.deleteWorkspace(this.workspaceId);
-
-    if (result.ok) {
-      return result.val;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  subscribe = async (callbacks: { onChildPagesChanged?: (childPages: Page[]) => void }) => {
-    const didUpdateWorkspace = (payload: Uint8Array) => {
-      const res = RepeatedViewPB.deserializeBinary(payload).items;
-
-      callbacks.onChildPagesChanged?.(res.map(parserViewPBToPage));
-    };
-
-    await this.observer.subscribeWorkspace(this.workspaceId, {
-      didUpdateWorkspace,
-    });
-  };
-
-  createView = async (params: ReturnType<typeof CreateViewPayloadPB.prototype.toObject>) => {
-    const result = await this.pageBackendService.createPage(params);
-
-    if (result.ok) {
-      const view = result.val;
-
-      return view;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  getChildPages = async (): Promise<Page[]> => {
-    const result = await this.backendService.getChildPages(this.workspaceId);
-
-    if (result.ok) {
-      return result.val.items.map(parserViewPBToPage);
-    }
-
-    return [];
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_manager_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_manager_controller.ts
deleted file mode 100644
index 67bfdd92ee..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_manager_controller.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { WorkspaceBackendService } from './workspace_bd_svc';
-import { CreateWorkspacePayloadPB } from '@/services/backend';
-import { WorkspaceItem } from '$app_reducers/workspace/slice';
-import { WorkspaceObserver } from '$app/stores/effects/workspace/workspace_observer';
-
-export class WorkspaceManagerController {
-  private readonly observer: WorkspaceObserver;
-  private readonly backendService: WorkspaceBackendService = new WorkspaceBackendService();
-  private onWorkspacesChanged?: (data: { workspaces: WorkspaceItem[]; currentWorkspace: WorkspaceItem }) => void;
-
-  constructor() {
-    this.observer = new WorkspaceObserver();
-  }
-
-  subscribe = async (callbacks: {
-    onWorkspacesChanged?: (data: { workspaces: WorkspaceItem[]; currentWorkspace: WorkspaceItem }) => void;
-  }) => {
-    // this.observer.subscribeWorkspaces(this.didCreateWorkspace);
-    this.onWorkspacesChanged = callbacks.onWorkspacesChanged;
-  };
-
-  createWorkspace = async (params: ReturnType<typeof CreateWorkspacePayloadPB.prototype.toObject>) => {
-    const result = await this.backendService.createWorkspace(params);
-
-    if (result.ok) {
-      return result.val;
-    }
-
-    return Promise.reject(result.err);
-  };
-
-  getWorkspaces = async (): Promise<WorkspaceItem[]> => {
-    const result = await this.backendService.getWorkspaces();
-
-    if (result.ok) {
-      const item = result.val;
-
-      return [
-        {
-          id: item.id,
-          name: item.name,
-        },
-      ];
-    }
-
-    return [];
-  };
-
-  getCurrentWorkspace = async (): Promise<WorkspaceItem | null> => {
-    const result = await this.backendService.getCurrentWorkspace();
-
-    if (result.ok) {
-      const workspace = result.val;
-
-      return {
-        id: workspace.id,
-        name: workspace.name,
-      };
-    }
-
-    return null;
-  };
-
-  dispose = async () => {
-    await this.observer.unsubscribe();
-  };
-
-  private didCreateWorkspace = () => {
-    // const data = RepeatedWorkspacePB.deserializeBinary(payload);
-    // onWorkspacesChanged(data.toObject().items);
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_observer.ts
deleted file mode 100644
index 97f27b585c..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/workspace/workspace_observer.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import { FolderNotification } from '@/services/backend';
-import { WorkspaceNotificationObserver } from '$app/stores/effects/workspace/notifications/observer';
-
-export class WorkspaceObserver {
-  private listener?: WorkspaceNotificationObserver;
-  constructor() {
-    //
-  }
-
-  subscribeWorkspaces = async (callback: (payload: Uint8Array) => void) => {
-    this.listener = new WorkspaceNotificationObserver({
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case FolderNotification.DidCreateWorkspace:
-            if (!result.ok) break;
-            callback(result.val);
-            break;
-          default:
-            break;
-        }
-      },
-    });
-    await this.listener.start();
-  };
-
-  subscribeWorkspace = async (
-    workspaceId: string,
-    callbacks: {
-      didUpdateChildViews?: (payload: Uint8Array) => void;
-      didUpdateWorkspace?: (payload: Uint8Array) => void;
-      didDeleteWorkspace?: (payload: Uint8Array) => void;
-    }
-  ) => {
-    this.listener = new WorkspaceNotificationObserver({
-      id: workspaceId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case FolderNotification.DidUpdateWorkspaceViews:
-            if (!result.ok) break;
-            callbacks.didUpdateWorkspace?.(result.val);
-            break;
-          case FolderNotification.DidUpdateChildViews:
-            if (!result.ok) break;
-            callbacks.didUpdateChildViews?.(result.val);
-            break;
-          // case FolderNotification.DidDeleteWorkspace:
-          //   if (!result.ok) break;
-          //   callbacks.didDeleteWorkspace(result.val);
-          //   break;
-          default:
-            break;
-        }
-      },
-    });
-    await this.listener.start();
-  };
-
-  subscribeView = async (
-    viewId: string,
-    callbacks: {
-      didUpdateChildViews?: (payload: Uint8Array) => void;
-      didUpdateView?: (payload: Uint8Array) => void;
-    }
-  ) => {
-    this.listener = new WorkspaceNotificationObserver({
-      id: viewId,
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case FolderNotification.DidUpdateChildViews:
-            if (!result.ok) break;
-            callbacks.didUpdateChildViews?.(result.val);
-            break;
-          case FolderNotification.DidUpdateView:
-            if (!result.ok) break;
-            callbacks.didUpdateView?.(result.val);
-            break;
-          default:
-            break;
-        }
-      },
-    });
-    await this.listener.start();
-  };
-
-  subscribeTrash = async (callbacks: { didUpdateTrash: (payload: Uint8Array) => void }) => {
-    this.listener = new WorkspaceNotificationObserver({
-      parserHandler: (notification, result) => {
-        switch (notification) {
-          case FolderNotification.DidUpdateTrash:
-            if (!result.ok) break;
-            callbacks.didUpdateTrash(result.val);
-            break;
-          default:
-            break;
-        }
-      },
-    });
-    await this.listener.start();
-  };
-
-  unsubscribe = async () => {
-    await this.listener?.stop();
-  };
-}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/board/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/board/slice.ts
deleted file mode 100644
index dff96c6a31..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/board/slice.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-
-const initialState = '';
-
-export const boardSlice = createSlice({
-  name: 'board',
-  initialState: initialState as string,
-  reducers: {
-    setGroupingFieldId: (state, action: PayloadAction<{ fieldId: string }>) => {
-      return action.payload.fieldId;
-    },
-  },
-});
-
-export const boardActions = boardSlice.actions;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts
deleted file mode 100644
index 26525d23b0..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-import { FieldType } from '@/services/backend/models/flowy-database2/field_entities';
-import { DateFormatPB, NumberFormatPB, SelectOptionColorPB, SortConditionPB, TimeFormatPB } from '@/services/backend';
-
-export interface ISelectOption {
-  selectOptionId: string;
-  title: string;
-  color: SelectOptionColorPB;
-}
-
-export interface ISelectOptionType {
-  selectOptions: ISelectOption[];
-}
-
-export interface IDateType {
-  dateFormat: DateFormatPB;
-  timeFormat: TimeFormatPB;
-  // includeTime: boolean;
-}
-
-export interface INumberType {
-  numberFormat: NumberFormatPB;
-}
-
-export interface IDatabaseField {
-  fieldId: string;
-  title: string;
-  visible: boolean;
-  width: number;
-  fieldType: FieldType;
-  fieldOptions?: ISelectOptionType | IDateType | INumberType;
-}
-
-export interface IDatabaseColumn {
-  fieldId: string;
-  sort: 'none' | 'asc' | 'desc';
-  visible: boolean;
-}
-
-export interface IDatabaseRow {
-  rowId: string;
-}
-
-export type DatabaseFieldMap = { [keys: string]: IDatabaseField };
-
-export type TDatabaseOperators =
-  | 'contains'
-  | 'doesNotContain'
-  | 'endsWith'
-  | 'startWith'
-  | 'is'
-  | 'isNot'
-  | 'isEmpty'
-  | 'isNotEmpty'
-  | 'isComplete'
-  | 'isIncomplted';
-
-export type TSupportedOperatorsByType = { [keys: number]: TDatabaseOperators[] };
-
-export const SupportedOperatorsByType: TSupportedOperatorsByType = {
-  [FieldType.RichText]: ['contains', 'doesNotContain', 'endsWith', 'startWith', 'is', 'isNot', 'isEmpty', 'isNotEmpty'],
-  [FieldType.SingleSelect]: ['is', 'isNot', 'isEmpty', 'isNotEmpty'],
-  [FieldType.MultiSelect]: ['contains', 'doesNotContain', 'isEmpty', 'isNotEmpty'],
-  [FieldType.Checkbox]: ['is'],
-  [FieldType.Checklist]: ['isComplete', 'isIncomplted'],
-};
-
-export interface IDatabaseFilter {
-  id?: string;
-  fieldId: string;
-  fieldType: FieldType;
-  logicalOperator: 'and' | 'or';
-  operator: TDatabaseOperators;
-  value: string[] | string | boolean;
-}
-
-export interface IDatabaseSort {
-  id?: string;
-  fieldId: string;
-  fieldType: FieldType;
-  order: SortConditionPB;
-}
-
-export interface IDatabase {
-  title: string;
-  fields: DatabaseFieldMap;
-  rows: IDatabaseRow[];
-  columns: IDatabaseColumn[];
-  filters: IDatabaseFilter[];
-  sort: IDatabaseSort[];
-}
-
-const initialState: IDatabase = {
-  title: 'Database One',
-  columns: [],
-  fields: {},
-  rows: [],
-  filters: [],
-  sort: [],
-};
-
-export const databaseSlice = createSlice({
-  name: 'database',
-  initialState: initialState,
-  reducers: {
-    clear: () => {
-      return initialState;
-    },
-
-    updateRows: (state, action: PayloadAction<{ rows: IDatabaseRow[] }>) => {
-      return {
-        ...state,
-        rows: action.payload.rows,
-      };
-    },
-
-    updateFields: (state, action: PayloadAction<{ fields: DatabaseFieldMap }>) => {
-      return {
-        ...state,
-        fields: action.payload.fields,
-      };
-    },
-
-    updateColumns: (state, action: PayloadAction<{ columns: IDatabaseColumn[] }>) => {
-      return {
-        ...state,
-        columns: action.payload.columns,
-      };
-    },
-
-    updateTitle: (state, action: PayloadAction<{ title: string }>) => {
-      state.title = action.payload.title;
-    },
-
-    updateField: (state, action: PayloadAction<{ field: IDatabaseField }>) => {
-      const { field } = action.payload;
-
-      state.fields[field.fieldId] = field;
-    },
-
-    changeWidth: (state, action: PayloadAction<{ fieldId: string; width: number }>) => {
-      const { fieldId, width } = action.payload;
-
-      state.fields[fieldId].width = width;
-    },
-
-    updateFilters: (state, action: PayloadAction<{ filters: IDatabaseFilter[] }>) => {
-      state.filters = action.payload.filters;
-    },
-
-    updateSorts: (state, action: PayloadAction<{ sorts: IDatabaseSort[] }>) => {
-      state.sort = action.payload.sorts;
-    },
-  },
-});
-
-export const databaseActions = databaseSlice.actions;
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/async_actions.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/async_actions.ts
index d647bcf934..0e8c9cc9ea 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/async_actions.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/async_actions.ts
@@ -1,7 +1,7 @@
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { RootState } from '$app/stores/store';
-import { PageController } from '$app/stores/effects/workspace/page/page_controller';
-import { PageIcon, pagesActions } from '$app_reducers/pages/slice';
+import { pagesActions } from '$app_reducers/pages/slice';
+import { movePage, updatePage } from '$app/application/folder/page.service';
 
 export const movePageThunk = createAsyncThunk(
   'pages/movePage',
@@ -51,16 +51,17 @@ export const movePageThunk = createAsyncThunk(
       }
     }
 
-    const controller = new PageController(sourceId);
-
-    await controller.movePage({ parentId, prevId });
+    await movePage({
+      view_id: sourceId,
+      new_parent_id: parentId,
+      prev_view_id: prevId,
+    });
   }
 );
 
 export const updatePageName = createAsyncThunk(
   'pages/updateName',
   async (payload: { id: string; name: string }, thunkAPI) => {
-    const controller = new PageController(payload.id);
     const { dispatch, getState } = thunkAPI;
     const { pageMap } = (getState() as RootState).pages;
     const { id, name } = payload;
@@ -74,15 +75,9 @@ export const updatePageName = createAsyncThunk(
         name,
       })
     );
-    await controller.updatePage({
-      id: payload.id,
-      name: payload.name,
+    await updatePage({
+      id,
+      name,
     });
   }
 );
-
-export const updatePageIcon = createAsyncThunk('pages/updateIcon', async (payload: { id: string; icon?: PageIcon }) => {
-  const controller = new PageController(payload.id);
-
-  await controller.updatePageIcon(payload.icon);
-});
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/workspace/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/workspace/slice.ts
index a9e0df8252..090382de70 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/workspace/slice.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/workspace/slice.ts
@@ -28,34 +28,6 @@ export const workspaceSlice = createSlice({
     ) => {
       return action.payload;
     },
-
-    onWorkspacesChanged: (
-      state,
-      action: PayloadAction<{
-        workspaces: WorkspaceItem[];
-        currentWorkspace: WorkspaceItem | null;
-      }>
-    ) => {
-      return action.payload;
-    },
-
-    onWorkspaceChanged: (state, action: PayloadAction<WorkspaceItem>) => {
-      const { id } = action.payload;
-      const index = state.workspaces.findIndex((workspace) => workspace.id === id);
-
-      if (index !== -1) {
-        state.workspaces[index] = action.payload;
-      }
-    },
-
-    onWorkspaceDeleted: (state, action: PayloadAction<string>) => {
-      const id = action.payload;
-      const index = state.workspaces.findIndex((workspace) => workspace.id === id);
-
-      if (index !== -1) {
-        state.workspaces.splice(index, 1);
-      }
-    },
   },
 });
 
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts
index 6ee441ad33..269f46884c 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts
@@ -10,8 +10,6 @@ import {
 import { pagesSlice } from './reducers/pages/slice';
 import { currentUserSlice } from './reducers/current-user/slice';
 import { workspaceSlice } from './reducers/workspace/slice';
-import { databaseSlice } from './reducers/database/slice';
-import { boardSlice } from './reducers/board/slice';
 import { errorSlice } from './reducers/error/slice';
 import { sidebarSlice } from '$app_reducers/sidebar/slice';
 import { trashSlice } from '$app_reducers/trash/slice';
@@ -24,8 +22,6 @@ const store = configureStore({
   reducer: {
     [pagesSlice.name]: pagesSlice.reducer,
     [currentUserSlice.name]: currentUserSlice.reducer,
-    [databaseSlice.name]: databaseSlice.reducer,
-    [boardSlice.name]: boardSlice.reducer,
     [workspaceSlice.name]: workspaceSlice.reducer,
     [errorSlice.name]: errorSlice.reducer,
     [sidebarSlice.name]: sidebarSlice.reducer,
diff --git a/frontend/appflowy_tauri/src/appflowy_app/utils/mui.ts b/frontend/appflowy_tauri/src/appflowy_app/utils/mui.ts
index 41ce9c7294..78a0308a1b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/utils/mui.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/utils/mui.ts
@@ -42,7 +42,7 @@ export const getDesignTokens = (mode: ThemeMode): ThemeOptions => {
         defaultProps: {
           sx: {
             '&.Mui-selected:hover': {
-              backgroundColor: 'var(--fill-list-active)',
+              backgroundColor: 'var(--fill-list-hover)',
             },
           },
         },
@@ -52,7 +52,7 @@ export const getDesignTokens = (mode: ThemeMode): ThemeOptions => {
               backgroundColor: 'var(--fill-list-hover)',
             },
             '&:active': {
-              backgroundColor: 'var(--fill-list-active)',
+              backgroundColor: 'var(--fill-list-hover)',
             },
             borderRadius: '4px',
             padding: '2px',
diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/BoardPage.tsx b/frontend/appflowy_tauri/src/appflowy_app/views/BoardPage.tsx
deleted file mode 100644
index 6066b00e7a..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/views/BoardPage.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useParams } from 'react-router-dom';
-import { useEffect, useState } from 'react';
-import { Board } from '../components/board/Board';
-import { useAppSelector } from '$app/stores/store';
-
-export const BoardPage = () => {
-  const params = useParams();
-  const [viewId, setViewId] = useState('');
-  const pagesStore = useAppSelector((state) => state.pages);
-  const page = useAppSelector((state) => (params.id ? state.pages.pageMap[params.id] : undefined));
-  const [title, setTitle] = useState('');
-
-  useEffect(() => {
-    if (page) {
-      setViewId(page.id);
-      setTitle(page.name);
-    }
-  }, [params, pagesStore, page]);
-
-  return (
-    <div className='flex h-full flex-col gap-8 px-8 pt-8'>
-      {viewId?.length && <Board viewId={viewId} title={title} />}
-    </div>
-  );
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/ConfirmAccountPage.tsx b/frontend/appflowy_tauri/src/appflowy_app/views/ConfirmAccountPage.tsx
deleted file mode 100644
index d06645b75c..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/views/ConfirmAccountPage.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { ConfirmAccount } from '../components/auth/ConfirmAccount/ConfirmAccount';
-
-export const ConfirmAccountPage = () => {
-  return <ConfirmAccount />;
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/LoginPage.tsx b/frontend/appflowy_tauri/src/appflowy_app/views/LoginPage.tsx
deleted file mode 100644
index 72f38dc5ad..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/views/LoginPage.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { Login } from '../components/auth/Login/Login';
-
-export const LoginPage = () => {
-  return <Login />;
-};
diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/SignUpPage.tsx b/frontend/appflowy_tauri/src/appflowy_app/views/SignUpPage.tsx
deleted file mode 100644
index e213d57d24..0000000000
--- a/frontend/appflowy_tauri/src/appflowy_app/views/SignUpPage.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { SignUp } from '../components/auth/SignUp/SignUp';
-
-export const SignUpPage = () => {
-  return <SignUp />;
-};
diff --git a/frontend/appflowy_tauri/src/main.tsx b/frontend/appflowy_tauri/src/main.tsx
index 30b86f2d40..e53dc96c43 100644
--- a/frontend/appflowy_tauri/src/main.tsx
+++ b/frontend/appflowy_tauri/src/main.tsx
@@ -4,7 +4,5 @@ import App from './appflowy_app/App';
 import './styles/tailwind.css';
 import './styles/font.css';
 import './styles/template.css';
-import './styles/Calendar.css';
-import './styles/switch.css';
 
 ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />);
diff --git a/frontend/appflowy_tauri/src/styles/Calendar.css b/frontend/appflowy_tauri/src/styles/Calendar.css
deleted file mode 100644
index 0ac995ed51..0000000000
--- a/frontend/appflowy_tauri/src/styles/Calendar.css
+++ /dev/null
@@ -1,141 +0,0 @@
-.react-calendar {
-  width: 250px;
-  max-width: 100%;
-  background: white;
-  line-height: 1.125em;
-}
-
-.react-calendar--doubleView {
-  width: 700px;
-}
-
-.react-calendar--doubleView .react-calendar__viewContainer {
-  display: flex;
-  margin: -0.5em;
-}
-
-.react-calendar--doubleView .react-calendar__viewContainer > * {
-  width: 50%;
-  margin: 0.5em;
-}
-
-.react-calendar,
-.react-calendar *,
-.react-calendar *:before,
-.react-calendar *:after {
-  -moz-box-sizing: border-box;
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-}
-
-.react-calendar button {
-  margin: 0;
-  border: 0;
-  outline: none;
-}
-
-.react-calendar button:enabled:hover {
-  cursor: pointer;
-}
-
-.react-calendar__navigation {
-  display: flex;
-  height: 44px;
-  margin-bottom: 1em;
-}
-
-.react-calendar__navigation button {
-  min-width: 44px;
-  background: none;
-}
-
-.react-calendar__navigation button:disabled {
-  background-color: #f0f0f0;
-}
-
-.react-calendar__navigation button:enabled:hover,
-.react-calendar__navigation button:enabled:focus {
-  background-color: #e6e6e6;
-}
-
-.react-calendar__month-view__weekdays {
-  @apply mb-2 text-center text-xs uppercase text-text-caption;
-}
-
-.react-calendar__month-view__weekdays abbr {
-  @apply no-underline;
-}
-
-.react-calendar__month-view__weekdays__weekday {
-  padding: 0.5em;
-}
-
-.react-calendar__month-view__weekNumbers .react-calendar__tile {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 0.75em;
-  font-weight: 400;
-}
-
-.react-calendar__month-view__days__day--weekend {
-  @apply text-text-link-default;
-}
-
-.react-calendar__month-view__days__day--neighboringMonth {
-  @apply text-text-caption;
-}
-
-.react-calendar__year-view .react-calendar__tile,
-.react-calendar__decade-view .react-calendar__tile,
-.react-calendar__century-view .react-calendar__tile {
-  padding: 2em 0.5em;
-}
-
-.react-calendar__tile {
-  max-width: 100%;
-  background: none;
-  text-align: center;
-  line-height: 16px;
-  @apply rounded py-2;
-}
-
-.react-calendar__tile:disabled {
-  background-color: #f0f0f0;
-}
-
-.react-calendar__tile:enabled:hover,
-.react-calendar__tile:enabled:focus {
-  background-color: #e6e6e6;
-}
-
-.react-calendar__tile--now {
-  @apply bg-bg-base;
-}
-
-.react-calendar__tile--now:enabled:hover,
-.react-calendar__tile--now:enabled:focus {
-  @apply bg-bg-base;
-}
-
-.react-calendar__tile--hasActive {
-  background: #76baff;
-}
-
-.react-calendar__tile--hasActive:enabled:hover,
-.react-calendar__tile--hasActive:enabled:focus {
-  background: #a9d4ff;
-}
-
-.react-calendar__tile--active {
-  @apply bg-fill-default text-text-title;
-}
-
-.react-calendar__tile--active:enabled:hover,
-.react-calendar__tile--active:enabled:focus {
-  @apply bg-fill-list-hover;
-}
-
-.react-calendar--selectRange .react-calendar__tile--hover {
-  @apply bg-bg-base;
-}
diff --git a/frontend/appflowy_tauri/src/styles/switch.css b/frontend/appflowy_tauri/src/styles/switch.css
deleted file mode 100644
index 7af7142fe7..0000000000
--- a/frontend/appflowy_tauri/src/styles/switch.css
+++ /dev/null
@@ -1,58 +0,0 @@
-.form-switch {
-  display: inline-block;
-  cursor: pointer;
-  -webkit-tap-highlight-color: transparent;
-}
-.form-switch i {
-  position: relative;
-  display: inline-block;
-  margin-right: 0.5rem;
-  width: 46px;
-  height: 26px;
-  @apply bg-bg-base;
-  border-radius: 23px;
-  vertical-align: text-bottom;
-  transition: all 0.3s linear;
-}
-.form-switch i::before {
-  content: '';
-  position: absolute;
-  left: 0;
-  width: 42px;
-  height: 22px;
-  background-color: #fff;
-  border-radius: 11px;
-  transform: translate3d(2px, 2px, 0) scale3d(1, 1, 1);
-  transition: all 0.25s linear;
-}
-.form-switch i::after {
-  content: '';
-  position: absolute;
-  left: 0;
-  width: 22px;
-  height: 22px;
-  background-color: #fff;
-  border-radius: 11px;
-  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.24);
-  transform: translate3d(2px, 2px, 0);
-  transition: all 0.2s ease-in-out;
-}
-.form-switch:active i::after {
-  width: 28px;
-  transform: translate3d(2px, 2px, 0);
-}
-.form-switch:active input:checked + i::after {
-  transform: translate3d(16px, 2px, 0);
-}
-.form-switch input {
-  display: none;
-}
-.form-switch input:checked + i {
-  @apply bg-fill-default;
-}
-.form-switch input:checked + i::before {
-  transform: translate3d(18px, 2px, 0) scale3d(0, 0, 0);
-}
-.form-switch input:checked + i::after {
-  transform: translate3d(22px, 2px, 0);
-}