diff --git a/src/App.vue b/src/App.vue
index 306e0d67f5bb8368dfa5251bf8a3638cfaa6da88..30e6887148b2cffac09f1b9dd14a71a5b549b457 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -11,10 +11,12 @@ import { OpenAPI as ResourceOpenAPI } from "@/client/resource";
 import { environment } from "@/environment";
 import FooterBottom from "@/components/FooterBottom.vue";
 import axios from "axios";
+import { useNameStore } from "@/stores/names";
 
 const { cookies } = useCookies();
 const store = useAuthStore();
 const router = useRouter();
+const nameRepository = useNameStore();
 
 onBeforeMount(() => {
   S3ProxyOpenAPI.BASE = environment.S3PROXY_API_BASE_URL;
@@ -58,11 +60,12 @@ onBeforeMount(() => {
       return { name: "dashboard" };
     } else if (
       to.meta.requiresReviewerRole &&
-      !(store.workflowReviewer || store.admin)
+      !(store.rewiewer || store.admin)
     ) {
       return { name: "dashboard" };
     }
   });
+  nameRepository.loadNameMapping();
 });
 </script>
 
diff --git a/src/components/NavbarTop.vue b/src/components/NavbarTop.vue
index 57d8e846ddc62029217a54bed5acde027c7ed9b7..20cad27ce06b4af13c5c6cc83fc880ba6005b955 100644
--- a/src/components/NavbarTop.vue
+++ b/src/components/NavbarTop.vue
@@ -28,6 +28,8 @@ const objectStorageActive = computed<boolean>(
 const workflowActive = computed<boolean>(
   () => activeRoute.value == "workflows",
 );
+const resourceActive = computed<boolean>(() => activeRoute.value == "resource");
+const adminActive = computed<boolean>(() => activeRoute.value == "admin");
 
 watch(
   () => route.name,
@@ -37,6 +39,10 @@ watch(
         activeRoute.value = "buckets";
       } else if (to.startsWith("workflow")) {
         activeRoute.value = "workflows";
+      } else if (to.startsWith("resource")) {
+        activeRoute.value = "resource";
+      } else if (to.startsWith("admin")) {
+        activeRoute.value = "admin";
       } else {
         activeRoute.value = to;
       }
@@ -126,11 +132,7 @@ watch(
                   >My Workflow Executions
                 </router-link>
               </li>
-              <li
-                v-if="
-                  store.workflowDev || store.workflowReviewer || store.admin
-                "
-              >
+              <li v-if="store.workflowDev || store.rewiewer || store.admin">
                 <hr class="dropdown-divider" />
               </li>
               <li v-if="store.workflowDev || store.admin">
@@ -140,7 +142,7 @@ watch(
                   >My Workflows
                 </router-link>
               </li>
-              <li v-if="store.workflowReviewer || store.admin">
+              <li v-if="store.rewiewer || store.admin">
                 <router-link
                   class="dropdown-item"
                   :to="{ name: 'workflows-reviewer' }"
@@ -152,7 +154,7 @@ watch(
           <li class="nav-item dropdown">
             <a
               class="nav-link dropdown-toggle"
-              :class="{ 'text-black': workflowActive }"
+              :class="{ 'text-black': resourceActive }"
               id="resourceDropdown"
               href="#"
               role="button"
@@ -171,7 +173,9 @@ watch(
                   >Available Resources
                 </router-link>
               </li>
-              <li v-if="store.resourceMaintainer || store.admin">
+              <li
+                v-if="store.resourceMaintainer || store.rewiewer || store.admin"
+              >
                 <hr class="dropdown-divider" />
               </li>
               <li v-if="store.resourceMaintainer || store.admin">
@@ -181,6 +185,36 @@ watch(
                   >My Resources
                 </router-link>
               </li>
+              <li v-if="store.rewiewer || store.admin">
+                <router-link
+                  class="dropdown-item"
+                  :to="{ name: 'resource-review' }"
+                  >Review
+                </router-link>
+              </li>
+            </ul>
+          </li>
+          <li v-if="store.admin">
+            <a
+              class="nav-link dropdown-toggle"
+              :class="{ 'text-black': adminActive }"
+              id="adminDropdown"
+              href="#"
+              role="button"
+              data-bs-toggle="dropdown"
+              aria-expanded="false"
+              data-bs-auto-close="true"
+            >
+              Admin
+            </a>
+            <ul
+              class="dropdown-menu shadow m-0"
+              aria-labelledby="adminDropdown"
+            >
+              <li><a class="dropdown-item disabled" href="#">User</a></li>
+              <li><a class="dropdown-item disabled" href="#">Bucket</a></li>
+              <li><a class="dropdown-item disabled" href="#">Workflow</a></li>
+              <li><a class="dropdown-item disabled" href="#">Resource</a></li>
             </ul>
           </li>
         </ul>
@@ -193,7 +227,7 @@ watch(
           data-bs-toggle="dropdown"
           aria-expanded="false"
         >
-          <strong class="me-2">{{ store.user.display_name }}</strong>
+          <strong class="me-2">{{ store.user?.display_name }}</strong>
           <font-awesome-icon icon="fa-solid fa-circle-user" class="fs-5" />
         </a>
         <ul
@@ -237,7 +271,6 @@ watch(
     </nav>
   </header>
   <bootstrap-modal
-    static-backdrop
     modal-i-d="advancedUsageModal"
     modal-label="Advanced Usage Modal"
     v-if="store.authenticated"
diff --git a/src/components/modals/SearchUserModal.vue b/src/components/modals/SearchUserModal.vue
index 85f24c3167c77a967f8288b128ef081f0499e235..56c269a501af76531de09aa60dd1553571f0f0f6 100644
--- a/src/components/modals/SearchUserModal.vue
+++ b/src/components/modals/SearchUserModal.vue
@@ -5,6 +5,7 @@ import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 import { UserService } from "@/client/auth";
 import type { User } from "@/client/auth";
 import { useAuthStore } from "@/stores/users";
+import { useNameStore } from "@/stores/names";
 
 const props = defineProps<{
   modalID: string;
@@ -13,6 +14,7 @@ const props = defineProps<{
 const randomIDSuffix = Math.random().toString(16).substring(2, 8);
 
 const store = useAuthStore();
+const nameStore = useNameStore();
 
 const formState = reactive<{
   searchString: string;
@@ -60,11 +62,9 @@ function searchUser(name: string) {
       formState.potentialUsers = userSuggestions.filter(
         (user) => store.currentUID != user.uid,
       );
-      const uidToName: Record<string, string> = {};
       for (const user of userSuggestions) {
-        uidToName[user.uid] = user.display_name;
+        nameStore.addNameToMapping(user.uid, user.display_name);
       }
-      store.addUidToNameMapping(uidToName);
     })
     .catch((err) => {
       formState.error = true;
@@ -106,7 +106,8 @@ function searchUser(name: string) {
           icon="fa-solid fa-x"
           class="mb-2"
           style="color: var(--bs-danger); font-size: 4em"
-        /><br />
+        />
+        <br />
         <span class="text-danger"
           >There seems to be an error<br />Try again later</span
         >
@@ -129,7 +130,8 @@ function searchUser(name: string) {
           icon="fa-solid fa-magnifying-glass"
           class="mb-2"
           style="color: var(--bs-secondary); font-size: 4em"
-        /><br />
+        />
+        <br />
         <span v-if="formState.searchString.length > 2"
           >Could not find any Users</span
         >
diff --git a/src/components/object-storage/BucketListItem.vue b/src/components/object-storage/BucketListItem.vue
index a1db0ae77fa2f80099523ab93c1dc26b94ccb542..04f5f4462fd8f1ff7f677e039a0a101b30ab6f81 100644
--- a/src/components/object-storage/BucketListItem.vue
+++ b/src/components/object-storage/BucketListItem.vue
@@ -12,6 +12,7 @@ import { useBucketStore } from "@/stores/buckets";
 import { useRouter } from "vue-router";
 import { useAuthStore } from "@/stores/users";
 import type { FolderTree } from "@/types/PseudoFolder";
+import { useNameStore } from "@/stores/names";
 
 const props = defineProps<{
   active: boolean;
@@ -23,6 +24,7 @@ const props = defineProps<{
 const randomIDSuffix = Math.random().toString(16).substring(2, 8);
 const permissionRepository = useBucketStore();
 const userRepository = useAuthStore();
+const nameRepository = useNameStore();
 const router = useRouter();
 
 const permission = computed<BucketPermissionOut | undefined>(
@@ -168,7 +170,7 @@ onMounted(() => {
             <tr v-if="permission">
               <th scope="row" class="fw-bold">Owner:</th>
               <td class="text-truncate">
-                {{ userRepository.userMapping[bucket.owner] }}
+                {{ nameRepository.getName(bucket.owner) }}
               </td>
             </tr>
             <tr
diff --git a/src/components/object-storage/modals/UploadObjectModal.vue b/src/components/object-storage/modals/UploadObjectModal.vue
index dfa6f4d75571593127f7b874031ef4fc87a9988e..a6ec1f38483c07d5132be7674cb7fc9de31705d9 100644
--- a/src/components/object-storage/modals/UploadObjectModal.vue
+++ b/src/components/object-storage/modals/UploadObjectModal.vue
@@ -189,15 +189,17 @@ onMounted(() => {
     </template>
     <template v-slot:footer>
       <div class="w-50 me-auto" v-if="formState.uploading">
-        <div class="progress">
+        <div
+          class="progress"
+          aria-valuemin="0"
+          aria-valuemax="100"
+          role="progressbar"
+          :aria-valuenow="uploadProgress"
+          aria-label="Upload Progressbar"
+        >
           <div
             class="progress-bar bg-info"
-            role="progressbar"
-            aria-label="Basic example"
             :style="{ width: uploadProgress + '%' }"
-            :aria-valuenow="uploadProgress"
-            aria-valuemin="0"
-            aria-valuemax="100"
           >
             {{ uploadProgress }}%
           </div>
diff --git a/src/components/resources/ResourceCard.vue b/src/components/resources/ResourceCard.vue
index c4bca17e035de691ed9ebbf8cd1b6725d6e9e6b4..821f041c74b821411f249200d0733352190f8074 100644
--- a/src/components/resources/ResourceCard.vue
+++ b/src/components/resources/ResourceCard.vue
@@ -6,17 +6,17 @@ import {
 } from "@/client/resource";
 import { computed, onMounted, ref } from "vue";
 import dayjs from "dayjs";
-import { useAuthStore } from "@/stores/users";
 import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue";
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 import { useS3ObjectStore } from "@/stores/s3objects";
 import { useResourceStore } from "@/stores/resources";
 import { Tooltip } from "bootstrap";
+import { useNameStore } from "@/stores/names";
 
 const randomIDSuffix: string = Math.random().toString(16).substring(2, 8);
-const userRepository = useAuthStore();
 const objectRepository = useS3ObjectStore();
 const resourceRepository = useResourceStore();
+const nameRepository = useNameStore();
 
 const props = defineProps<{
   resource: ResourceOut;
@@ -302,14 +302,12 @@ onMounted(() => {
         Maintainer:
         <span
           v-if="
-            props.loading || !userRepository.userMapping[resource.maintainer_id]
+            props.loading || !nameRepository.getName(resource.maintainer_id)
           "
           class="placeholder-glow"
           ><span class="placeholder col-2"></span
         ></span>
-        <span v-else>{{
-          userRepository.userMapping[resource.maintainer_id]
-        }}</span>
+        <span v-else>{{ nameRepository.getName(resource.maintainer_id) }}</span>
       </div>
     </div>
   </div>
diff --git a/src/components/workflows/modals/ParameterModal.vue b/src/components/workflows/modals/ParameterModal.vue
index 576746b44668556bf079f70a015d88b9bd1315c1..00dc11ee4c904b8988840e3480b4ed20b2dc7958 100644
--- a/src/components/workflows/modals/ParameterModal.vue
+++ b/src/components/workflows/modals/ParameterModal.vue
@@ -6,10 +6,10 @@ import type { RouteParamsRaw } from "vue-router";
 import { Modal } from "bootstrap";
 import { useRouter } from "vue-router";
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
-import { useWorkflowStore } from "@/stores/workflows";
 import type { WorkflowExecutionOut } from "@/client/workflow";
+import { useNameStore } from "@/stores/names";
 
-const workflowRepository = useWorkflowStore();
+const nameRepository = useNameStore();
 const executionRepository = useWorkflowExecutionStore();
 const router = useRouter();
 
@@ -71,9 +71,9 @@ const workflowName = computed<string>(() => {
       execution?.workflow_version_id != undefined
     ) {
       return (
-        workflowRepository.getName(execution.workflow_id) +
+        nameRepository.getName(execution.workflow_id) +
         "@" +
-        workflowRepository.getName(execution.workflow_version_id)
+        nameRepository.getName(execution.workflow_version_id)
       );
     }
   }
diff --git a/src/router/resourceRoutes.ts b/src/router/resourceRoutes.ts
index 24b7db150836690138f5637992354ad44dd12a67..6b2ed067d9693568979aa2670847191ba3d3297e 100644
--- a/src/router/resourceRoutes.ts
+++ b/src/router/resourceRoutes.ts
@@ -11,4 +11,9 @@ export const resourceRoutes: RouteRecordRaw[] = [
     name: "resource-maintainer",
     component: () => import("../views/resources/MyResourcesView.vue"),
   },
+  {
+    path: "reviewer/resources",
+    name: "resource-review",
+    component: () => import("../views/resources/ReviewResourceView.vue"),
+  },
 ];
diff --git a/src/stores/names.ts b/src/stores/names.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4dc30f76e0e34b41de204796741a41b5a5277eed
--- /dev/null
+++ b/src/stores/names.ts
@@ -0,0 +1,41 @@
+import { defineStore } from "pinia";
+
+export const useNameStore = defineStore({
+  id: "names",
+  state: () =>
+    ({
+      nameMapping: {},
+    }) as {
+      nameMapping: Record<string, string>;
+    },
+  getters: {
+    getName(): (objectID: string) => string | undefined {
+      return (objectID) =>
+        this.nameMapping[objectID] ?? localStorage.getItem(objectID);
+    },
+  },
+  actions: {
+    addNameToMapping(objectId: string, objectName: string) {
+      this.nameMapping[objectId] = objectName;
+      localStorage.setItem(objectId, objectName);
+    },
+    deleteNameFromMapping(objectId: string) {
+      delete this.nameMapping[objectId];
+      localStorage.removeItem(objectId);
+    },
+    loadNameMapping() {
+      if (Object.keys(this.nameMapping).length > 0) {
+        return;
+      }
+      for (let i = 0; i < localStorage.length; i++) {
+        const key = localStorage.key(i);
+        if (key != null) {
+          const value = localStorage.getItem(key);
+          if (value != null) {
+            this.nameMapping[key] = value;
+          }
+        }
+      }
+    },
+  },
+});
diff --git a/src/stores/resources.ts b/src/stores/resources.ts
index 40aa0cf843820abfe7f5977b9576d7d946d81a80..6e648731ee92345303510a247e845a6eae20c9ad 100644
--- a/src/stores/resources.ts
+++ b/src/stores/resources.ts
@@ -8,6 +8,7 @@ import type {
 import { ResourceService, ResourceVersionService } from "@/client/resource";
 import { useAuthStore } from "@/stores/users";
 import { Status } from "@/client/resource";
+import { useNameStore } from "@/stores/names";
 
 export const useResourceStore = defineStore({
   id: "resources",
@@ -28,15 +29,33 @@ export const useResourceStore = defineStore({
     },
   },
   actions: {
-    fetchResources(onFinally?: () => void): Promise<ResourceOut[]> {
+    __addNameToMapping(key: string, value: string) {
+      const nameStore = useNameStore();
+      nameStore.addNameToMapping(key, value);
+    },
+    fetchResources(
+      maintainerId?: string,
+      versionStatus?: Status[],
+    ): Promise<ResourceOut[]> {
+      return ResourceService.resourceListResources(maintainerId, versionStatus);
+    },
+    fetchPublicResources(onFinally?: () => void): Promise<ResourceOut[]> {
       if (Object.keys(this.resourceMapping).length > 0) {
         onFinally?.();
       }
-      return ResourceService.resourceListResources()
+      return this.fetchResources()
         .then((resources) => {
           const newMapping: Record<string, ResourceOut> = {};
+          const nameStore = useNameStore();
           for (const resource of resources) {
             newMapping[resource.resource_id] = resource;
+            nameStore.addNameToMapping(resource.resource_id, resource.name);
+            for (const version of resource.versions) {
+              nameStore.addNameToMapping(
+                version.resource_version_id,
+                version.release,
+              );
+            }
           }
           this.resourceMapping = newMapping;
           return resources;
@@ -56,6 +75,14 @@ export const useResourceStore = defineStore({
       )
         .then((resource) => {
           this.ownResourceMapping[resource.resource_id] = resource;
+          const nameStore = useNameStore();
+          nameStore.addNameToMapping(resource.resource_id, resource.name);
+          for (const version of resource.versions) {
+            nameStore.addNameToMapping(
+              version.resource_version_id,
+              version.release,
+            );
+          }
           return resource;
         })
         .finally(onFinally);
@@ -65,14 +92,19 @@ export const useResourceStore = defineStore({
       if (Object.keys(this.ownResourceMapping).length > 0) {
         onFinally?.();
       }
-      return ResourceService.resourceListResources(
-        authStore.currentUID,
-        Object.values(Status),
-      )
+      return this.fetchResources(authStore.currentUID, Object.values(Status))
         .then((resources) => {
           const newMapping: Record<string, ResourceOut> = {};
+          const nameStore = useNameStore();
           for (const resource of resources) {
             newMapping[resource.resource_id] = resource;
+            nameStore.addNameToMapping(resource.resource_id, resource.name);
+            for (const version of resource.versions) {
+              nameStore.addNameToMapping(
+                version.resource_version_id,
+                version.release,
+              );
+            }
           }
           this.ownResourceMapping = newMapping;
           return resources;
@@ -83,6 +115,16 @@ export const useResourceStore = defineStore({
       const createdResource =
         await ResourceService.resourceCreateResource(resource);
       this.ownResourceMapping[createdResource.resource_id] = createdResource;
+      const nameStore = useNameStore();
+      nameStore.addNameToMapping(
+        createdResource.resource_id,
+        createdResource.name,
+      );
+      nameStore.addNameToMapping(
+        createdResource.versions[0].resource_version_id,
+        createdResource.versions[0].release,
+      );
+
       return createdResource;
     },
     requestSynchronization(
@@ -130,6 +172,10 @@ export const useResourceStore = defineStore({
           this.fetchOwnResource(versionOut.resource_id);
           return versionOut;
         }
+        useNameStore().addNameToMapping(
+          versionOut.resource_version_id,
+          versionOut.release,
+        );
         this.ownResourceMapping[versionOut.resource_id].versions.push(
           versionOut,
         );
diff --git a/src/stores/users.ts b/src/stores/users.ts
index 4d7b524b0cc6ae75a69161be7d74716e82035127..928ed2956df6f5a9d322d219b329c4f0f1b59fe3 100644
--- a/src/stores/users.ts
+++ b/src/stores/users.ts
@@ -11,6 +11,7 @@ import { useWorkflowStore } from "@/stores/workflows";
 import { useS3KeyStore } from "@/stores/s3keys";
 import { useS3ObjectStore } from "@/stores/s3objects";
 import { clear as dbclear } from "idb-keyval";
+import { useNameStore } from "@/stores/names";
 
 type DecodedToken = {
   exp: number;
@@ -23,7 +24,6 @@ export type RootState = {
   token: string | null;
   decodedToken: DecodedToken | null;
   user: User | null;
-  userMapping: Record<string, string>;
 };
 
 function parseJwt(token: string): DecodedToken {
@@ -49,7 +49,6 @@ export const useAuthStore = defineStore({
       token: null,
       decodedToken: null,
       user: null,
-      userMapping: {},
     }) as RootState,
   getters: {
     roles(): string[] {
@@ -71,7 +70,7 @@ export const useAuthStore = defineStore({
       state.user?.roles?.includes(RoleEnum.USER) ??
       state.decodedToken?.roles.includes(RoleEnum.USER) ??
       false,
-    workflowReviewer: (state) =>
+    rewiewer: (state) =>
       state.user?.roles?.includes(RoleEnum.REVIEWER) ??
       state.decodedToken?.roles.includes(RoleEnum.REVIEWER) ??
       false,
@@ -110,8 +109,7 @@ export const useAuthStore = defineStore({
     },
     updateUser(user: User) {
       this.user = user;
-      this.userMapping[user.uid] = user.display_name;
-      localStorage.setItem(user.uid, user.display_name);
+      useNameStore().addNameToMapping(user.uid, user.display_name);
     },
     logout() {
       S3ProxyOpenAPI.TOKEN = undefined;
@@ -127,15 +125,10 @@ export const useAuthStore = defineStore({
       useS3KeyStore().$reset();
       useS3ObjectStore().$reset();
     },
-    async addUidToNameMapping(mapping: Record<string, string>): Promise<void> {
-      for (const uid of Object.keys(mapping)) {
-        this.userMapping[uid] = mapping[uid];
-        localStorage.setItem(uid, mapping[uid]);
-      }
-    },
     async fetchUsernames(uids: string[]): Promise<string[]> {
+      const nameStore = useNameStore();
       const filteredIds = uids
-        .filter((uid) => !this.userMapping[uid]) // filter already present UIDs
+        .filter((uid) => !nameStore.getName(uid)) // filter already present UIDs
         .filter(
           // filter unique UIDs
           (modeId, index, array) =>
@@ -143,7 +136,8 @@ export const useAuthStore = defineStore({
         );
       // If all uids are already in the store, then return them
       if (filteredIds.length === 0) {
-        return uids.map((uid) => this.userMapping[uid]);
+        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+        return uids.map((uid) => nameStore.getName(uid)!);
       }
       const missingIds: string[] = [];
       const storedNames = filteredIds.map((uid) => localStorage.getItem(uid));
@@ -154,23 +148,19 @@ export const useAuthStore = defineStore({
           missingIds.push(filteredIds[index]);
         } else {
           // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-          this.userMapping[filteredIds[index]] = storedNames[index]!;
+          nameStore.addNameToMapping(filteredIds[index], storedNames[index]!);
         }
       }
-      // If all uids could be resolved from cache, return them
-      if (missingIds.length === 0) {
-        return uids.map((uid) => this.userMapping[uid]);
-      }
       // fetch missing users from backend
       const fetchedUsers = await Promise.all(
         missingIds.map((uid) => UserService.userGetUser(uid)),
       );
       // Put users in store
       for (const user of fetchedUsers) {
-        this.userMapping[user.uid] = user.display_name;
-        localStorage.setItem(user.uid, user.display_name);
+        nameStore.addNameToMapping(user.uid, user.display_name);
       }
-      return uids.map((uid) => this.userMapping[uid]);
+      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+      return uids.map((uid) => nameStore.getName(uid)!);
     },
   },
 });
diff --git a/src/stores/workflows.ts b/src/stores/workflows.ts
index 6c7e04b3e2ba72d49ffed420cd41953e2a6e3b81..8b1bd2473e96e9b20d98fc0205edebe695a18af5 100644
--- a/src/stores/workflows.ts
+++ b/src/stores/workflows.ts
@@ -18,19 +18,17 @@ import {
 } from "@/client/workflow";
 import { useAuthStore } from "@/stores/users";
 import { set, get } from "idb-keyval";
+import { useNameStore } from "@/stores/names";
 
 export const useWorkflowStore = defineStore({
   id: "workflows",
   state: () =>
     ({
       workflowMapping: {},
-      nameMapping: {},
       comprehensiveWorkflowMapping: {},
       modeMapping: {},
-      modeNameMapping: {},
     }) as {
       workflowMapping: Record<string, WorkflowOut>;
-      nameMapping: Record<string, string>;
       comprehensiveWorkflowMapping: Record<string, WorkflowOut>;
       modeMapping: Record<string, WorkflowModeOut>;
     },
@@ -61,18 +59,13 @@ export const useWorkflowStore = defineStore({
       }
       return mapping;
     },
-    getName(): (objectID: string) => string | undefined {
-      return (objectID) =>
-        this.nameMapping[objectID] ?? localStorage.getItem(objectID);
-    },
     getArbitraryWorkflow(): (wid: string) => Promise<WorkflowIn | undefined> {
       return (wid: string) => get(wid);
     },
   },
   actions: {
     __addNameToMapping(key: string, value: string) {
-      this.nameMapping[key] = value;
-      localStorage.setItem(key, value);
+      useNameStore().addNameToMapping(key, value);
     },
     fetchWorkflows(onFinally?: () => void): Promise<WorkflowOut[]> {
       if (Object.keys(this.workflowMapping).length > 0) {
@@ -300,8 +293,7 @@ export const useWorkflowStore = defineStore({
     },
     deleteWorkflow(workflow_id: string): Promise<void> {
       return WorkflowService.workflowDeleteWorkflow(workflow_id).then(() => {
-        delete this.nameMapping[workflow_id];
-        localStorage.removeItem(workflow_id);
+        useNameStore().deleteNameFromMapping(workflow_id);
         delete this.workflowMapping[workflow_id];
         delete this.comprehensiveWorkflowMapping[workflow_id];
       });
diff --git a/src/views/resources/ListResourcesView.vue b/src/views/resources/ListResourcesView.vue
index db883daec9da9c50cc035da68053732ee012c99d..b615344d6aadb6e6602fd47a984953b9f3e6e8b7 100644
--- a/src/views/resources/ListResourcesView.vue
+++ b/src/views/resources/ListResourcesView.vue
@@ -43,7 +43,7 @@ const filteredSortedResources = computed<ResourceOut[]>(() => {
 
 onMounted(() => {
   resourceRepository
-    .fetchResources(() => {
+    .fetchPublicResources(() => {
       resourceState.loading = false;
     })
     .then((resources) => {
diff --git a/src/views/resources/ReviewResourceView.vue b/src/views/resources/ReviewResourceView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cb91f85b499515f2557f4d92bda43bce8cb03730
--- /dev/null
+++ b/src/views/resources/ReviewResourceView.vue
@@ -0,0 +1,120 @@
+<script setup lang="ts">
+import { useResourceStore } from "@/stores/resources";
+import { computed, onMounted, reactive } from "vue";
+import { type ResourceOut, Status } from "@/client/resource";
+import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue";
+
+const resourceRepository = useResourceStore();
+
+const resourceState = reactive<{
+  reviewableResources: ResourceOut[];
+  loading: boolean;
+}>({
+  reviewableResources: [],
+  loading: true,
+});
+
+const countItems = computed<number>(() =>
+  resourceState.reviewableResources.reduce(
+    (previousValue, currentValue) =>
+      previousValue + currentValue.versions.length,
+    0,
+  ),
+);
+
+onMounted(() => {
+  resourceRepository
+    .fetchResources(undefined, [Status.SYNC_REQUESTED, Status.SYNCHRONIZING])
+    .then((resources) => {
+      resourceState.reviewableResources = resources;
+    })
+    .finally(() => {
+      resourceState.loading = false;
+    });
+});
+</script>
+
+<template>
+  <div class="row m-2 border-bottom mb-4">
+    <h2 class="mb-2">Resource Requests</h2>
+  </div>
+  <div v-if="resourceState.loading" class="text-center mt-5">
+    <div class="spinner-border" style="width: 3rem; height: 3rem" role="status">
+      <span class="visually-hidden">Loading...</span>
+    </div>
+  </div>
+  <table class="table caption-top table-striped table-hover align-middle">
+    <caption>
+      Display
+      {{
+        countItems
+      }}
+      resource versions
+    </caption>
+    <thead>
+      <tr>
+        <th scope="col">Resource</th>
+        <th scope="col">Release</th>
+        <th scope="col">Status</th>
+        <th scope="col">S3 Path</th>
+        <th scope="col" class="text-end">Action</th>
+      </tr>
+    </thead>
+    <tbody>
+      <template
+        v-for="resource in resourceState.reviewableResources"
+        :key="resource.resource_id"
+      >
+        <tr
+          v-for="version in resource.versions"
+          :key="version.resource_version_id"
+        >
+          <th>{{ resource.name }}</th>
+          <th>{{ version.release }}</th>
+          <th>{{ version.status }}</th>
+          <th>
+            <div class="input-group">
+              <input
+                class="form-control form-control-sm"
+                type="text"
+                :value="version.s3_path"
+                aria-label="S3 Access Path"
+                readonly
+              />
+              <span class="input-group-text"
+                ><copy-to-clipboard-icon :text="version.s3_path"
+              /></span>
+            </div>
+          </th>
+          <th class="text-end">
+            <div
+              v-if="version.status === Status.SYNC_REQUESTED"
+              class="btn-group"
+            >
+              <button type="button" class="btn btn-success btn-sm">
+                Synchronize
+              </button>
+              <button type="button" class="btn btn-danger btn-sm">Deny</button>
+            </div>
+            <div
+              v-else-if="version.status === Status.SYNCHRONIZING"
+              class="progress"
+              role="progressbar"
+              aria-label="Animated striped example"
+              aria-valuenow="100"
+              aria-valuemin="0"
+              aria-valuemax="100"
+            >
+              <div
+                class="progress-bar progress-bar-striped progress-bar-animated"
+                style="width: 100%"
+              ></div>
+            </div>
+          </th>
+        </tr>
+      </template>
+    </tbody>
+  </table>
+</template>
+
+<style scoped></style>
diff --git a/src/views/workflows/ListWorkflowExecutionsView.vue b/src/views/workflows/ListWorkflowExecutionsView.vue
index cbf7b1f06fd45f9af5a399a853ea5a78e7f20db7..c3d87aa57e68ecc94186a639712d8e0cd45dd492 100644
--- a/src/views/workflows/ListWorkflowExecutionsView.vue
+++ b/src/views/workflows/ListWorkflowExecutionsView.vue
@@ -9,8 +9,10 @@ import { useWorkflowStore } from "@/stores/workflows";
 import { useWorkflowExecutionStore } from "@/stores/workflowExecutions";
 import ParameterModal from "@/components/workflows/modals/ParameterModal.vue";
 import { ExponentialBackoff } from "@/utils/BackoffStrategy";
+import { useNameStore } from "@/stores/names";
 
 const workflowRepository = useWorkflowStore();
+const nameRepository = useNameStore();
 const executionRepository = useWorkflowExecutionStore();
 const backoff = new ExponentialBackoff();
 
@@ -247,8 +249,8 @@ onUnmounted(() => {
                 },
               }"
             >
-              {{ workflowRepository.getName(execution.workflow_id) }}@{{
-                workflowRepository.getName(execution.workflow_version_id)
+              {{ nameRepository.getName(execution.workflow_id) }}@{{
+                nameRepository.getName(execution.workflow_version_id)
               }}
             </router-link>
           </td>
diff --git a/src/views/workflows/ReviewWorkflowsView.vue b/src/views/workflows/ReviewWorkflowsView.vue
index 63ed00942e6f2e04d7c57e76b4a3544de0e07dcd..80baa8d935ffa8908b784ec04f58f0e3aa024681 100644
--- a/src/views/workflows/ReviewWorkflowsView.vue
+++ b/src/views/workflows/ReviewWorkflowsView.vue
@@ -6,8 +6,10 @@ import { determineGitIcon } from "@/utils/GitRepository";
 import { sortedVersions } from "@/utils/Workflow";
 import { useWorkflowStore } from "@/stores/workflows";
 import { useAuthStore } from "@/stores/users";
+import { useNameStore } from "@/stores/names";
 
 const workflowRepository = useWorkflowStore();
+const nameRepository = useNameStore();
 const userRepository = useAuthStore();
 
 const workflowsState = reactive<{
@@ -78,8 +80,8 @@ onMounted(() => {
               {{ workflow.repository_url }}
             </a>
           </td>
-          <td v-if="userRepository.userMapping[workflow.developer_id]">
-            {{ userRepository.userMapping[workflow.developer_id] }}
+          <td v-if="nameRepository.getName(workflow.developer_id)">
+            {{ nameRepository.getName(workflow.developer_id) }}
           </td>
           <td v-else class="placeholder-glow">
             <div class="placeholder w-75"></div>
diff --git a/src/views/workflows/WorkflowView.vue b/src/views/workflows/WorkflowView.vue
index 01af1de7bc9f51bc266acb9537eaf915083809f7..08b1395de3189580cd1bc72484199c14f109f38f 100644
--- a/src/views/workflows/WorkflowView.vue
+++ b/src/views/workflows/WorkflowView.vue
@@ -166,7 +166,7 @@ const gitIcon = computed<string>(() =>
 
 const allowVersionDeprecation = computed<boolean>(() => {
   if (activeVersion.value?.status === Status.PUBLISHED) {
-    if (userRepository.workflowReviewer || userRepository.admin) {
+    if (userRepository.rewiewer || userRepository.admin) {
       return true;
     } else if (
       userRepository.workflowDev &&