diff --git a/src/components/NavbarTop.vue b/src/components/NavbarTop.vue
index 2c08939a0e2769614f48e6c99a829fa8469d8094..1116c0dbc77dcfb0dd6ed6ee8f3b2761a31dfdbb 100644
--- a/src/components/NavbarTop.vue
+++ b/src/components/NavbarTop.vue
@@ -9,6 +9,7 @@ import { OpenAPI as S3ProxyOpenAPI } from "@/client/s3proxy";
 import { OpenAPI as AuthOpenAPI } from "@/client/auth";
 import { OpenAPI as WorkflowOpenAPI } from "@/client/workflow";
 import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue";
+import dayjs from "dayjs";
 
 const store = useAuthStore();
 const { cookies } = useCookies();
@@ -200,6 +201,7 @@ watch(
     static-backdrop
     modal-i-d="advancedUsageModal"
     modal-label="Advanced Usage Modal"
+    v-if="store.authenticated"
   >
     <template v-slot:header>
       <h3>Advanced Usage</h3>
@@ -243,12 +245,17 @@ watch(
         </tbody>
       </table>
       <div class="mt-4">
-        <label for="clowm-jwt" class="form-label">JWT for Services</label>
+        <label for="clowm-jwt" class="form-label"
+          >JWT for Services (expires at
+          {{
+            dayjs.unix(store.decodedToken!.exp).format("DD.MM.YYYY HH:mm")
+          }})</label
+        >
         <div class="input-group">
           <input
             type="text"
             readonly
-            class="form-control"
+            class="form-control text-truncate"
             id="clowm-jwt"
             :value="store.token"
             aria-describedby="clowm-jwt-copy"
diff --git a/src/components/workflows/WorkflowWithVersionsCard.vue b/src/components/workflows/WorkflowWithVersionsCard.vue
index 0e72ccb8b29d9f807d5b2fc914dc1ca03d005460..6d814c88dc91846178375cc42d836c2d91257363 100644
--- a/src/components/workflows/WorkflowWithVersionsCard.vue
+++ b/src/components/workflows/WorkflowWithVersionsCard.vue
@@ -119,6 +119,15 @@ onMounted(() => {
         </div>
         <div v-else>
           <table class="table table-sm table-hover">
+            <thead>
+              <tr>
+                <th scope="col">Version</th>
+                <th scope="col">Status</th>
+                <th scope="col">Updated at</th>
+                <th scope="col" class="text-align-center">Icon</th>
+                <th scope="col">Link</th>
+              </tr>
+            </thead>
             <tbody>
               <tr
                 v-for="version in sortedVersions(props.workflow.versions)"
@@ -141,7 +150,7 @@ onMounted(() => {
                 <td>
                   {{ dayjs.unix(version.created_at).format("D MMMM YYYY") }}
                 </td>
-                <td class="w-fit">
+                <td class="text-align-center">
                   <img
                     v-if="version.icon_url != null"
                     :src="version.icon_url"
@@ -207,4 +216,7 @@ td > img {
 .add-icon-hover:hover {
   color: var(--bs-success) !important;
 }
+.text-align-center {
+  text-align: center;
+}
 </style>
diff --git a/src/components/workflows/modals/ArbitraryWorkflowModal.vue b/src/components/workflows/modals/ArbitraryWorkflowModal.vue
index 9abbaf2783fa0d6868361493de778f1114a70f86..df01d892735acabd6975cde1c26700709061ceb2 100644
--- a/src/components/workflows/modals/ArbitraryWorkflowModal.vue
+++ b/src/components/workflows/modals/ArbitraryWorkflowModal.vue
@@ -100,7 +100,7 @@ function checkRepository() {
           : undefined,
       );
       repo
-        .checkFilesExist(requiredRepositoryFiles, true)
+        .checkFilesExist(requiredRepositoryFiles([]), true)
         .then(() => {
           formState.allowUpload = true;
         })
diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue
index 3971a16223b875c5fb295d56bcaf601f7b02c631..fb63fbc47601861853088e2d3b3da77447fb32aa 100644
--- a/src/components/workflows/modals/CreateWorkflowModal.vue
+++ b/src/components/workflows/modals/CreateWorkflowModal.vue
@@ -1,7 +1,11 @@
 <script setup lang="ts">
 import { computed, onMounted, reactive, ref, watch } from "vue";
 import { Modal, Toast, Collapse, Tooltip } from "bootstrap";
-import type { WorkflowIn, WorkflowOut } from "@/client/workflow";
+import type {
+  WorkflowIn,
+  WorkflowOut,
+  WorkflowModeOut,
+} from "@/client/workflow";
 import BootstrapModal from "@/components/modals/BootstrapModal.vue";
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 import { ApiError, WorkflowService } from "@/client/workflow";
@@ -30,6 +34,7 @@ let createWorkflowModal: Modal | null = null;
 let successToast: Toast | null = null;
 let privateRepositoryCollapse: Collapse | null = null;
 let tokenHelpCollapse: Collapse | null = null;
+let workflowModesCollapse: Collapse | null = null;
 
 // HTML Form Elements
 // =============================================================================
@@ -81,6 +86,21 @@ const repositoryCredentials = reactive<{
   privateRepo: false,
 });
 
+const workflowModes = reactive<{
+  hasModes: boolean;
+  modes: WorkflowModeOut[];
+}>({
+  hasModes: false,
+  modes: [
+    {
+      mode_id: crypto.randomUUID(),
+      name: "",
+      schema_path: "",
+      entrypoint: "",
+    },
+  ],
+});
+
 // Computed Properties
 // =============================================================================
 const gitIcon = computed<string>(() =>
@@ -99,6 +119,17 @@ watch(
   },
 );
 
+watch(
+  () => workflowModes.hasModes,
+  (show) => {
+    if (show) {
+      workflowModesCollapse?.show();
+    } else {
+      workflowModesCollapse?.hide();
+    }
+  },
+);
+
 // Functions
 // =============================================================================
 function modalClosed() {
@@ -130,6 +161,15 @@ function createWorkflow() {
     ) {
       workflow.token = repositoryCredentials.token;
     }
+    if (workflowModes.hasModes) {
+      workflow.modes = workflowModes.modes.map((mode) => {
+        return {
+          name: mode.name,
+          schema_path: mode.schema_path,
+          entrypoint: mode.entrypoint,
+        };
+      });
+    }
     WorkflowService.workflowCreateWorkflow(workflow)
       .then((w) => {
         emit("workflow-created", w);
@@ -164,18 +204,21 @@ function resetForm() {
   workflow.git_commit_hash = "";
   workflow.initial_version = undefined;
   workflow.token = undefined;
+  workflow.modes = [];
+  workflowModes.modes = [
+    {
+      mode_id: crypto.randomUUID(),
+      name: "",
+      schema_path: "",
+      entrypoint: "",
+    },
+  ];
+  workflowModes.hasModes = false;
   repositoryCredentials.privateRepo = false;
   repositoryCredentials.token = "";
   privateRepositoryCollapse?.hide();
 }
 
-/**
- * Watcher function for the file upload in the form.
- */
-//function iconChanged() {
-//  workflow.icon = workflowIconInput.value?.files?.[0].slice();
-//}
-
 /**
  * Check the workflow repository for the necessary files.
  */
@@ -194,8 +237,11 @@ function checkRepository() {
           ? repositoryCredentials.token
           : undefined,
       );
+      const requiredFiles = requiredRepositoryFiles(
+        workflowModes.hasModes ? workflowModes.modes : [],
+      );
       repo
-        .checkFilesExist(requiredRepositoryFiles, true)
+        .checkFilesExist(requiredFiles, true)
         .then(() => {
           formState.allowUpload = true;
         })
@@ -227,6 +273,27 @@ function checkVersionValidity() {
   }
 }
 
+function addMode() {
+  if (workflowModes.modes.length < 11) {
+    workflowModes.modes.push({
+      mode_id: crypto.randomUUID(),
+      name: "",
+      schema_path: "",
+      entrypoint: "",
+    });
+  }
+}
+
+function removeMode(index: number) {
+  if (
+    workflowModes.modes.length > 1 &&
+    index > -1 &&
+    index < (workflowModes.modes.length ?? 0)
+  ) {
+    workflowModes.modes.splice(index, 1);
+  }
+}
+
 // Lifecycle Events
 // =============================================================================
 onMounted(() => {
@@ -238,6 +305,9 @@ onMounted(() => {
   tokenHelpCollapse = new Collapse("#tokenHelpCollapse", {
     toggle: false,
   });
+  workflowModesCollapse = new Collapse("#workflowModesCollapse", {
+    toggle: false,
+  });
   new Tooltip("#tooltip-version-" + randomIDSuffix);
   new Tooltip("#tooltip-commit-" + randomIDSuffix);
   new Tooltip("#tooltip-url-" + randomIDSuffix);
@@ -430,7 +500,7 @@ onMounted(() => {
               aria-controls="#privateRepositoryCollapse"
             />
             <label class="form-check-label" for="privateRepositoryCheckbox">
-              Private Git Repository
+              Enable private Git Repository
             </label>
           </div>
           <div class="collapse" id="privateRepositoryCollapse">
@@ -490,6 +560,101 @@ onMounted(() => {
             </div>
           </div>
         </div>
+        <div class="mb-3">
+          <div class="form-check fs-5">
+            <input
+              class="form-check-input"
+              type="checkbox"
+              v-model="workflowModes.hasModes"
+              id="workflowModesCheckbox"
+              @change="formState.allowUpload = false"
+              aria-controls="#workflowModesCollapse"
+            />
+            <label class="form-check-label" for="workflowModesCheckbox">
+              Enable Workflow Modes
+            </label>
+            <button
+              v-if="workflowModes.hasModes"
+              class="btn btn-primary float-end"
+              @click="addMode"
+              :disabled="workflow.modes!.length >= 10"
+            >
+              Add Mode
+            </button>
+          </div>
+        </div>
+        <div class="collapse" id="workflowModesCollapse">
+          <TransitionGroup name="list" tag="div">
+            <div
+              v-for="(mode, index) in workflowModes.modes"
+              :key="mode.mode_id"
+              class="row mb-3"
+            >
+              <h6>
+                <font-awesome-icon
+                  icon="fa-solid fa-minus"
+                  class="text-danger me-1 fs-6 cursor-pointer"
+                  @click="removeMode(index)"
+                />
+                Mode {{ index + 1 }}
+              </h6>
+              <div class="col-6">
+                <label :for="'modeNameInput-' + index" class="form-label"
+                  >Name</label
+                >
+                <div class="input-group">
+                  <div class="input-group-text">
+                    <font-awesome-icon icon="fa-solid fa-tag" />
+                  </div>
+                  <input
+                    type="text"
+                    class="form-control"
+                    :id="'modeNameInput-' + index"
+                    maxlength="128"
+                    v-model="mode.name"
+                    :required="workflowModes.hasModes"
+                  />
+                </div>
+              </div>
+              <div class="col-6 mb-2">
+                <label :for="'modeEntryInput-' + index" class="form-label"
+                  >Entrypoint</label
+                >
+                <div class="input-group">
+                  <div class="input-group-text">
+                    <font-awesome-icon icon="fa-solid fa-tag" />
+                  </div>
+                  <input
+                    type="text"
+                    class="form-control"
+                    :id="'modeEntryInput-' + index"
+                    maxlength="128"
+                    v-model="mode.entrypoint"
+                    :required="workflowModes.hasModes"
+                  />
+                </div>
+              </div>
+              <label :for="'modeSchemaInput-' + index" class="form-label"
+                >Schema File</label
+              >
+              <div class="input-group">
+                <div class="input-group-text">
+                  <font-awesome-icon icon="fa-solid fa-file-code" />
+                </div>
+                <input
+                  type="text"
+                  class="form-control"
+                  :id="'modeSchemaInput-' + index"
+                  maxlength="128"
+                  pattern=".*\.json$"
+                  v-model="mode.schema_path"
+                  @change="formState.allowUpload = false"
+                  :required="workflowModes.hasModes"
+                />
+              </div>
+            </div>
+          </TransitionGroup>
+        </div>
       </form>
     </template>
     <template v-slot:footer>
@@ -533,4 +698,26 @@ onMounted(() => {
 .hover-info:hover {
   color: var(--bs-info) !important;
 }
+
+.list-move, /* apply transition to moving elements */
+.list-enter-active,
+.list-leave-active {
+  transition: all 0.5s ease;
+}
+
+.list-enter-from {
+  opacity: 0;
+  transform: translateX(50%);
+}
+
+.list-leave-to {
+  opacity: 0;
+  transform: translateX(-50%);
+}
+
+/* ensure leaving items are taken out of layout flow so that moving
+   animations can be calculated correctly. */
+.list-leave-active {
+  position: absolute;
+}
 </style>
diff --git a/src/components/workflows/modals/UpdateWorkflowModal.vue b/src/components/workflows/modals/UpdateWorkflowModal.vue
index 4ce43dc0026daf6c66241584f25372d8601187d1..9664a5581d57766452dbb7a68083d795b36d45e8 100644
--- a/src/components/workflows/modals/UpdateWorkflowModal.vue
+++ b/src/components/workflows/modals/UpdateWorkflowModal.vue
@@ -149,7 +149,7 @@ function checkRepository() {
       formState.workflowToken,
     );
     repo
-      .checkFilesExist(requiredRepositoryFiles, true)
+      .checkFilesExist(requiredRepositoryFiles([]), true)
       .then(() => {
         formState.allowUpload = true;
       })
diff --git a/src/utils/GitRepository.ts b/src/utils/GitRepository.ts
index 68004e6c06e19000f3710ff2db33f8430c200301..4299afa536ef37a08b43227d447a7957353a3255 100644
--- a/src/utils/GitRepository.ts
+++ b/src/utils/GitRepository.ts
@@ -1,14 +1,22 @@
 import axios from "axios";
 import type { AxiosInstance, AxiosBasicCredentials } from "axios";
-
-export const requiredRepositoryFiles = [
-  "main.nf",
-  "CHANGELOG.md",
-  "README.md",
-  "nextflow_schema.json",
-  "docs/usage.md",
-  "docs/output.md",
-];
+import type { WorkflowModeOut } from "@/client/workflow";
+
+export function requiredRepositoryFiles(modes: WorkflowModeOut[]) {
+  const list = [
+    "main.nf",
+    "CHANGELOG.md",
+    "README.md",
+    "docs/usage.md",
+    "docs/output.md",
+  ];
+  if (modes.length > 0) {
+    list.push(...modes.map((mode) => mode.schema_path));
+  } else {
+    list.push("nextflow_schema.json");
+  }
+  return list;
+}
 
 export function determineGitIcon(repo_url?: string): string {
   let gitProvider = "git-alt";
diff --git a/src/utils/Workflow.ts b/src/utils/Workflow.ts
index 9257886a74986eebd6e7bd1da9ed3a3e17bc4fd2..e01237b68f4f3c5baaec652c5c10c5c3a36f6e2f 100644
--- a/src/utils/Workflow.ts
+++ b/src/utils/Workflow.ts
@@ -1,7 +1,5 @@
 import type { WorkflowVersion } from "@/client/workflow";
 
-export function sortedVersions(versions: WorkflowVersion[]): WorkflowVersion[];
-
 export function sortedVersions(
   versions: WorkflowVersion[],
   desc = true,
@@ -15,10 +13,6 @@ export function sortedVersions(
   return vs;
 }
 
-export function latestVersion(
-  versions: WorkflowVersion[],
-): WorkflowVersion | undefined;
-
 export function latestVersion(
   versions: WorkflowVersion[],
 ): WorkflowVersion | undefined {
diff --git a/src/views/workflows/ArbitraryWorkflowView.vue b/src/views/workflows/ArbitraryWorkflowView.vue
index cc1c87b0c28732dd69e14989523e1f7c01230f64..bc2559916b743cc0b72590fc29aaba898111a9f3 100644
--- a/src/views/workflows/ArbitraryWorkflowView.vue
+++ b/src/views/workflows/ArbitraryWorkflowView.vue
@@ -46,7 +46,7 @@ function downloadVersionFiles(
   workflowState.loading = true;
   const repo = GitRepository.buildRepository(repository, commit_hash, token);
   Promise.all(
-    requiredRepositoryFiles.map((file) =>
+    requiredRepositoryFiles([]).map((file) =>
       repo.downloadFile(file).then((response) => {
         if (file.includes("README")) {
           workflowState.descriptionMarkdown = response.data;