diff --git a/src/client/workflow/models/WorkflowIn.ts b/src/client/workflow/models/WorkflowIn.ts
index 544b0e3d50e28167d433cf1dda6a1bfaef7d54f6..9367556e9ffa26da9b64044efbd577d24dc145f7 100644
--- a/src/client/workflow/models/WorkflowIn.ts
+++ b/src/client/workflow/models/WorkflowIn.ts
@@ -33,6 +33,6 @@ export type WorkflowIn = {
     /**
      * List of modes with alternative entrypoint the new workflow has
      */
-    modes?: (Array<WorkflowModeIn> | null);
+    modes?: Array<WorkflowModeIn>;
 };
 
diff --git a/src/client/workflow/models/WorkflowUpdate.ts b/src/client/workflow/models/WorkflowUpdate.ts
index 97c2577769795b6fc537326f61b7772fc98ab668..6aa6f1874344aff94967d05ddd3958cd86726d71 100644
--- a/src/client/workflow/models/WorkflowUpdate.ts
+++ b/src/client/workflow/models/WorkflowUpdate.ts
@@ -17,10 +17,10 @@ export type WorkflowUpdate = {
     /**
      * Add modes to the new workflow version
      */
-    append_modes?: (Array<WorkflowModeIn> | null);
+    append_modes?: Array<WorkflowModeIn>;
     /**
      * Delete modes for the new workflow version.
      */
-    delete_modes?: (Array<string> | null);
+    delete_modes?: Array<string>;
 };
 
diff --git a/src/client/workflow/models/WorkflowVersion.ts b/src/client/workflow/models/WorkflowVersion.ts
index 563cdc6e4db57e903736c8896b28ca734511f12d..a4248ce4db3ba9fdb32e70dfc800e6b71a7f42ca 100644
--- a/src/client/workflow/models/WorkflowVersion.ts
+++ b/src/client/workflow/models/WorkflowVersion.ts
@@ -33,6 +33,6 @@ export type WorkflowVersion = {
     /**
      * Optional modes his workflow version has
      */
-    modes: (Array<string> | null);
+    modes: Array<string>;
 };
 
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/object-storage/modals/CreateBucketModal.vue b/src/components/object-storage/modals/CreateBucketModal.vue
index 94fe7288e46131437e33d981575aa6696f423f6e..8922b13083d06c926298a6def9b78eb64a2caf9c 100644
--- a/src/components/object-storage/modals/CreateBucketModal.vue
+++ b/src/components/object-storage/modals/CreateBucketModal.vue
@@ -97,7 +97,7 @@ function modalClosed() {
               required
               minlength="3"
               maxlength="63"
-              pattern="(?!(^((2(5[0-5]|[0-4]\d)|[01]?\d{1,2})\.){3}(2(5[0-5]|[0-4]\d)|[01]?\d{1,2})$))^[a-z\d][a-z\d.-]{1,61}[a-z\d]$"
+              pattern="(?!(^((2(5[0-5]|[0-4]\d)|[01]?\d{1,2})\.){3}(2(5[0-5]|[0-4]\d)|[01]?\d{1,2})$))^[a-z\d][a-z\d.\-]{1,61}[a-z\d]$"
               v-model="bucket.name"
             />
             <div class="invalid-feedback">
diff --git a/src/components/parameter-schema/ParameterSchemaDescriptionComponent.vue b/src/components/parameter-schema/ParameterSchemaDescriptionComponent.vue
index df8d127eafb60b82640405358fbe5a08ffd2429b..79063a1285586e9679ba55d776e8a4510be72423 100644
--- a/src/components/parameter-schema/ParameterSchemaDescriptionComponent.vue
+++ b/src/components/parameter-schema/ParameterSchemaDescriptionComponent.vue
@@ -17,22 +17,13 @@ type ParameterGroup = {
 };
 
 const navParameterGroups = computed<ParameterGroup[]>(() =>
-  Object.keys(parameterGroups.value)
-    .map((group) => {
-      return {
-        group: group,
-        title: parameterGroups.value[group]["title"],
-        icon: parameterGroups.value[group]["fa_icon"],
-      };
-    })
-    .filter(
-      // filter all groups that have only hidden parameters
-      (group) =>
-        Object.keys(parameterGroups.value[group.group]["properties"]).filter(
-          (key) =>
-            !parameterGroups.value[group.group]["properties"][key]["hidden"],
-        ).length > 0,
-    ),
+  Object.keys(parameterGroups.value).map((group) => {
+    return {
+      group: group,
+      title: parameterGroups.value[group]["title"],
+      icon: parameterGroups.value[group]["fa_icon"],
+    };
+  }),
 );
 
 const parameterGroups = computed<Record<string, never>>(
diff --git a/src/components/parameter-schema/ParameterSchemaFormComponent.vue b/src/components/parameter-schema/ParameterSchemaFormComponent.vue
index d59dd130a49818b67eef8848ae94754fa04ac6cf..4dd82b93caac988eaa925c201c61d335546fad13 100644
--- a/src/components/parameter-schema/ParameterSchemaFormComponent.vue
+++ b/src/components/parameter-schema/ParameterSchemaFormComponent.vue
@@ -78,22 +78,13 @@ const parameterGroups = computed<Record<string, never>>(
 
 // Create a list with the names of all parameter groups
 const navParameterGroups = computed<ParameterGroup[]>(() =>
-  Object.keys(parameterGroups.value)
-    .map((group) => {
-      return {
-        group: group,
-        title: parameterGroups.value[group]["title"],
-        icon: parameterGroups.value[group]["fa_icon"],
-      };
-    })
-    .filter(
-      // filter all groups that have only hidden parameters
-      (group) =>
-        Object.keys(parameterGroups.value[group.group]["properties"]).filter(
-          (key) =>
-            !parameterGroups.value[group.group]["properties"][key]["hidden"],
-        ).length > 0,
-    ),
+  Object.keys(parameterGroups.value).map((group) => {
+    return {
+      group: group,
+      title: parameterGroups.value[group]["title"],
+      icon: parameterGroups.value[group]["fa_icon"],
+    };
+  }),
 );
 
 // Watchers
@@ -115,14 +106,13 @@ function updateSchema(schema: Record<string, any>) {
   const b = Object.keys(schema["definitions"]).map((groupName) => [
     groupName,
     Object.fromEntries(
-      Object.entries(schema["definitions"][groupName]["properties"])
-        // @ts-ignore
-        .filter(([_, parameter]) => !parameter["hidden"])
-        .map(([parameterName, parameter]) => [
+      Object.entries(schema["definitions"][groupName]["properties"]).map(
+        ([parameterName, parameter]) => [
           parameterName,
           // @ts-ignore
           parameter["default"],
-        ]),
+        ],
+      ),
     ),
   ]);
   formState.formInput = Object.fromEntries(b);
diff --git a/src/components/parameter-schema/description-mode/ParameterDescription.vue b/src/components/parameter-schema/description-mode/ParameterDescription.vue
index cd7a63ef1c7ac3b2acfb8f780220663e6c3ebc00..bace4110ccb3454541deb450e061f2161c353ebc 100644
--- a/src/components/parameter-schema/description-mode/ParameterDescription.vue
+++ b/src/components/parameter-schema/description-mode/ParameterDescription.vue
@@ -32,7 +32,7 @@ const defaultValue = computed<string | undefined>(
 const enumValues = computed<string[] | undefined>(
   () => props.parameter["enum"]?.map((val: string) => val.toString()),
 );
-const hidden = computed<boolean>(() => props.parameter["hidden"] ?? false);
+// const hidden = computed<boolean>(() => props.parameter["hidden"] ?? false);
 const parameterPattern = computed<string | undefined>(
   () => props.parameter["pattern"],
 );
@@ -48,7 +48,6 @@ const showRightColum = computed<boolean>(
 <template>
   <div
     class="row border-top border-bottom border-secondary align-items-start py-2"
-    v-if="!hidden"
   >
     <div class="fs-6 col-3">
       <font-awesome-icon :icon="icon" v-if="icon" class="me-2" />
diff --git a/src/components/parameter-schema/description-mode/ParameterGroupDescription.vue b/src/components/parameter-schema/description-mode/ParameterGroupDescription.vue
index 93b8b9416f0f5379d7a69808a71d98c4129cdf4b..6ced29b2ce7be8ed1ab88d209acc12eca02c9e92 100644
--- a/src/components/parameter-schema/description-mode/ParameterGroupDescription.vue
+++ b/src/components/parameter-schema/description-mode/ParameterGroupDescription.vue
@@ -20,19 +20,22 @@ const props = defineProps({
 const title = computed<string>(() => props.parameterGroup["title"]);
 const icon = computed<string>(() => props.parameterGroup["fa_icon"]);
 const description = computed<string>(() => props.parameterGroup["description"]);
+/*
 const groupHidden = computed<boolean>(() =>
   Object.keys(parameters.value).reduce(
     (acc: boolean, val: string) => acc && parameters.value[val]["hidden"],
     true,
   ),
 );
+
+ */
 const parameters = computed<Record<string, never>>(
   () => props.parameterGroup["properties"],
 );
 </script>
 
 <template>
-  <div class="mb-5" v-if="!groupHidden">
+  <div class="mb-5">
     <div class="row">
       <h2 :id="props.parameterGroupName">
         <font-awesome-icon :icon="icon" class="me-3" v-if="icon" />{{ title }}
diff --git a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue
index f84a78da9d0b2b993fa901f47ac6a6eede04327f..4dae916a8f6d301e1b52adcafd4d31f558c99c36 100644
--- a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue
+++ b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue
@@ -71,7 +71,7 @@ watch(
 </script>
 
 <template>
-  <div class="card mb-3" v-if="!groupHidden">
+  <div class="card mb-3" :hidden="groupHidden">
     <h2 class="card-header" :id="props.parameterGroupName">
       <font-awesome-icon :icon="icon" class="me-2" v-if="icon" />
       {{ title }}
@@ -82,7 +82,7 @@ watch(
         v-for="(parameter, parameterName) in parameters"
         :key="parameterName"
       >
-        <template v-if="!parameter['hidden']">
+        <div :hidden="parameter['hidden']">
           <div class="input-group">
             <span class="input-group-text" :id="parameterName + '-help'">
               <font-awesome-icon
@@ -170,7 +170,7 @@ watch(
               </p>
             </div>
           </div>
-        </template>
+        </div>
       </template>
     </div>
   </div>
diff --git a/src/components/transitions/WorkflowModeTransitionGroup.vue b/src/components/transitions/WorkflowModeTransitionGroup.vue
new file mode 100644
index 0000000000000000000000000000000000000000..13d5944c31065e17b099cae95787750e4d284ccb
--- /dev/null
+++ b/src/components/transitions/WorkflowModeTransitionGroup.vue
@@ -0,0 +1,31 @@
+<script setup lang="ts"></script>
+
+<template>
+  <transition-group name="modelist" tag="div">
+    <slot></slot>
+  </transition-group>
+</template>
+
+<style>
+.modelist-move, /* apply transition to moving elements */
+.modelist-enter-active,
+.modelist-leave-active {
+  transition: all 0.5s ease;
+}
+
+.modelist-enter-from {
+  opacity: 0;
+  transform: translateX(50%);
+}
+
+.modelist-leave-to {
+  opacity: 0;
+  transform: translateX(-50%);
+}
+
+/* ensure leaving items are taken out of layout flow so that moving
+   animations can be calculated correctly. */
+.modelist-leave-active {
+  position: absolute;
+}
+</style>
diff --git a/src/components/workflows/WorkflowCard.vue b/src/components/workflows/WorkflowCard.vue
index 61f2beb88232deac2326c7a36efedb60c38f3074..50c8ddc00ff1848343aaed427b788496ee3dcabe 100644
--- a/src/components/workflows/WorkflowCard.vue
+++ b/src/components/workflows/WorkflowCard.vue
@@ -42,6 +42,9 @@ onMounted(() => {
               workflowId: workflow.workflow_id,
               versionId: latestVersion?.git_commit_hash,
             },
+            query: {
+              workflowModeId: latestVersion?.modes?.[0] ?? undefined,
+            },
           }"
           >{{ props.workflow.name }}
         </router-link>
@@ -77,6 +80,9 @@ onMounted(() => {
               workflowId: workflow.workflow_id,
               versionId: latestVersion?.git_commit_hash,
             },
+            query: {
+              workflowModeId: latestVersion?.modes?.[0] ?? undefined,
+            },
           }"
           class="btn btn-outline-success"
           role="button"
diff --git a/src/components/workflows/WorkflowWithVersionsCard.vue b/src/components/workflows/WorkflowWithVersionsCard.vue
index 0e72ccb8b29d9f807d5b2fc914dc1ca03d005460..d43ce26bb4024457da84b853064cbf880ee29317 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"
@@ -169,6 +178,10 @@ onMounted(() => {
                         workflowId: props.workflow.workflow_id,
                         versionId: version.git_commit_hash,
                       },
+                      query: {
+                        workflowModeId: version.modes?.[0] ?? undefined,
+                        developerView: 'true',
+                      },
                     }"
                     >View
                   </router-link>
@@ -207,4 +220,8 @@ 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..5d85f01f1f61b54bfbbe113863e0a5c015ed9fdc 100644
--- a/src/components/workflows/modals/ArbitraryWorkflowModal.vue
+++ b/src/components/workflows/modals/ArbitraryWorkflowModal.vue
@@ -9,6 +9,8 @@ import {
   determineGitIcon,
 } from "@/utils/GitRepository";
 import { Collapse, Modal } from "bootstrap";
+import { useArbitraryWorkflowStore } from "@/stores/devWorkflow";
+import type { WorkflowModeOut } from "@/client/workflow";
 
 const props = defineProps<{
   modalID: string;
@@ -17,9 +19,11 @@ const props = defineProps<{
 let createWorkflowModal: Modal | null = null;
 let privateRepositoryCollapse: Collapse | null = null;
 let tokenHelpCollapse: Collapse | null = null;
+let workflowModeCollapse: Collapse | null = null;
 const arbitraryWorkflowForm = ref<HTMLFormElement | undefined>(undefined);
 const workflowRepositoryElement = ref<HTMLInputElement | undefined>(undefined);
 const router = useRouter();
+const workflowStore = useArbitraryWorkflowStore();
 
 const workflow = reactive<{
   repository_url: string;
@@ -37,6 +41,19 @@ const repositoryCredentials = reactive<{
   privateRepo: false,
 });
 
+const workflowMode = reactive<{
+  mode: WorkflowModeOut;
+  modeEnabled: boolean;
+}>({
+  mode: {
+    entrypoint: "",
+    schema_path: "",
+    name: "",
+    mode_id: crypto.randomUUID(),
+  },
+  modeEnabled: false,
+});
+
 const formState = reactive<{
   loading: boolean;
   checkRepoLoading: boolean;
@@ -65,6 +82,17 @@ watch(
   },
 );
 
+watch(
+  () => workflowMode.modeEnabled,
+  (show) => {
+    if (show) {
+      workflowModeCollapse?.show();
+    } else {
+      workflowModeCollapse?.hide();
+    }
+  },
+);
+
 function modalClosed() {
   formState.validated = false;
   tokenHelpCollapse?.hide();
@@ -72,15 +100,20 @@ function modalClosed() {
 
 function viewWorkflow() {
   createWorkflowModal?.hide();
+  const wid = workflowStore.setWorkflow({
+    ...workflow,
+    name: "",
+    short_description: "",
+    modes: workflowMode.modeEnabled ? [workflowMode.mode] : [],
+    token:
+      repositoryCredentials.token.length > 0
+        ? repositoryCredentials.token
+        : undefined,
+  });
   router.push({
     name: "arbitrary-workflow",
     query: {
-      repository: encodeURI(workflow.repository_url),
-      commit_hash: workflow.git_commit_hash,
-      token:
-        repositoryCredentials.token.length > 0
-          ? encodeURIComponent(repositoryCredentials.token)
-          : undefined,
+      wid: wid,
     },
   });
 }
@@ -100,7 +133,12 @@ function checkRepository() {
           : undefined,
       );
       repo
-        .checkFilesExist(requiredRepositoryFiles, true)
+        .checkFilesExist(
+          requiredRepositoryFiles(
+            workflowMode.modeEnabled ? [workflowMode.mode] : [],
+          ),
+          true,
+        )
         .then(() => {
           formState.allowUpload = true;
         })
@@ -133,6 +171,9 @@ onMounted(() => {
   privateRepositoryCollapse = new Collapse("#privateRepositoryCollapse", {
     toggle: false,
   });
+  workflowModeCollapse = new Collapse("#workflowModeCollapse", {
+    toggle: false,
+  });
   tokenHelpCollapse = new Collapse("#tokenHelpCollapse", {
     toggle: false,
   });
@@ -224,7 +265,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">
@@ -280,6 +321,64 @@ onMounted(() => {
             </div>
           </div>
         </div>
+        <div class="mb-3">
+          <div class="form-check fs-5">
+            <input
+              class="form-check-input"
+              type="checkbox"
+              v-model="workflowMode.modeEnabled"
+              id="workflowModeCheckbox"
+              @change="formState.allowUpload = false"
+              aria-controls="#workflowModeCollapse"
+            />
+            <label class="form-check-label" for="workflowModeCheckbox">
+              Enable Workflow Mode
+            </label>
+          </div>
+          <div class="collapse" id="workflowModeCollapse">
+            <div class="row">
+              <div class="col-6 mb-2">
+                <label for="modeEntryInput-" 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"
+                    maxlength="128"
+                    v-model="workflowMode.mode.entrypoint"
+                    :required="workflowMode.modeEnabled"
+                    @change="formState.allowUpload = false"
+                  />
+                </div>
+              </div>
+              <div class="col-6">
+                <label for="modeSchemaInput-" 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-"
+                    maxlength="128"
+                    pattern=".*\.json$"
+                    v-model="workflowMode.mode.schema_path"
+                    :required="workflowMode.modeEnabled"
+                    @change="formState.allowUpload = false"
+                  />
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
       </form>
     </template>
     <template v-slot:footer>
diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue
index 3971a16223b875c5fb295d56bcaf601f7b02c631..308b83a47ee870e7dc85581127fbfe6f0cbd5561 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";
@@ -11,6 +15,7 @@ import {
   determineGitIcon,
 } from "@/utils/GitRepository";
 import { valid } from "semver";
+import WorkflowModeTransitionGroup from "@/components/transitions/WorkflowModeTransitionGroup.vue";
 
 // Emitted Events
 // =============================================================================
@@ -30,6 +35,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 +87,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 +120,17 @@ watch(
   },
 );
 
+watch(
+  () => workflowModes.hasModes,
+  (show) => {
+    if (show) {
+      workflowModesCollapse?.show();
+    } else {
+      workflowModesCollapse?.hide();
+    }
+  },
+);
+
 // Functions
 // =============================================================================
 function modalClosed() {
@@ -130,6 +162,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 +205,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 +238,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 +274,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 +306,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 +501,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 +561,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">
+          <WorkflowModeTransitionGroup>
+            <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-turn-down" />
+                  </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>
+          </WorkflowModeTransitionGroup>
+        </div>
       </form>
     </template>
     <template v-slot:footer>
diff --git a/src/components/workflows/modals/UpdateWorkflowModal.vue b/src/components/workflows/modals/UpdateWorkflowModal.vue
index 4ce43dc0026daf6c66241584f25372d8601187d1..14cea75f652be8cdf1181f35d6b938ad60bce32a 100644
--- a/src/components/workflows/modals/UpdateWorkflowModal.vue
+++ b/src/components/workflows/modals/UpdateWorkflowModal.vue
@@ -1,15 +1,21 @@
 <script setup lang="ts">
 import { computed, onMounted, reactive, ref, watch } from "vue";
-import { Modal, Toast } from "bootstrap";
+import { Collapse, Modal, Toast } from "bootstrap";
 import type {
   WorkflowUpdate,
   WorkflowOut,
+  WorkflowModeIn,
+  WorkflowModeOut,
   WorkflowVersion,
   ApiError,
 } from "@/client/workflow";
 import BootstrapModal from "@/components/modals/BootstrapModal.vue";
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
-import { WorkflowService, WorkflowCredentialsService } from "@/client/workflow";
+import {
+  WorkflowService,
+  WorkflowCredentialsService,
+  WorkflowModeService,
+} from "@/client/workflow";
 import {
   GitRepository,
   requiredRepositoryFiles,
@@ -17,11 +23,13 @@ import {
 } from "@/utils/GitRepository";
 import { valid, lte, inc } from "semver";
 import { latestVersion as calculateLatestVersion } from "@/utils/Workflow";
+import WorkflowModeTransitionGroup from "@/components/transitions/WorkflowModeTransitionGroup.vue";
 
 // Bootstrap Elements
 // =============================================================================
 let updateWorkflowModal: Modal | null = null;
 let successToast: Toast | null = null;
+let workflowModesCollapse: Collapse | null = null;
 
 // Form Elements
 // =============================================================================
@@ -53,6 +61,14 @@ const workflowUpdate = reactive<WorkflowUpdate>({
   append_modes: [],
 });
 
+const workflowModes = reactive<{
+  deleteModes: string[];
+  addModes: WorkflowModeOut[];
+}>({
+  deleteModes: [],
+  addModes: [],
+});
+
 const formState = reactive<{
   validated: boolean;
   missingFiles: string[];
@@ -61,6 +77,8 @@ const formState = reactive<{
   allowUpload: boolean;
   loadCredentials: boolean;
   workflowToken?: string;
+  modeMapping: Record<string, WorkflowModeOut>;
+  modesEnabled: boolean;
 }>({
   loading: false,
   checkRepoLoading: false,
@@ -69,12 +87,16 @@ const formState = reactive<{
   missingFiles: [],
   loadCredentials: false,
   workflowToken: undefined,
+  modeMapping: {},
+  modesEnabled: false,
 });
 
 watch(
   () => props.workflow,
   () => {
     resetForm();
+    updateModeMapping();
+    formState.modesEnabled = latestVersion.value.modes.length > 0;
     if (props.workflow.private) {
       formState.loadCredentials = true;
       WorkflowCredentialsService.workflowCredentialsGetWorkflowCredentials(
@@ -95,6 +117,23 @@ watch(
   },
 );
 
+watch(
+  () => formState.modesEnabled,
+  (show) => {
+    if (show) {
+      workflowModesCollapse?.show();
+      if (
+        latestVersion.value.modes.length + workflowModes.addModes.length ===
+        0
+      ) {
+        addMode();
+      }
+    } else {
+      workflowModesCollapse?.hide();
+    }
+  },
+);
+
 // Computed Properties
 // =============================================================================
 const latestVersion = computed<WorkflowVersion>(() => {
@@ -148,8 +187,16 @@ function checkRepository() {
       workflowUpdate.git_commit_hash,
       formState.workflowToken,
     );
+    const oldModes = latestVersion.value.modes
+      .filter((mode_id) => !workflowModes.deleteModes.includes(mode_id)) // filter all old modes that should be deleted
+      .map((mode_id) => formState.modeMapping[mode_id]) // map mode id to mode object
+      .filter((mode) => mode != undefined); // filter all mode objects that are undefined
+    const newModes = formState.modesEnabled ? workflowModes.addModes : [];
     repo
-      .checkFilesExist(requiredRepositoryFiles, true)
+      .checkFilesExist(
+        requiredRepositoryFiles([...oldModes, ...newModes]),
+        true,
+      )
       .then(() => {
         formState.allowUpload = true;
       })
@@ -168,6 +215,10 @@ function resetForm() {
   workflowIconElement.value!.src = latestVersion.value.icon_url ?? "";
   workflowUpdate.version = "";
   workflowUpdate.git_commit_hash = "";
+  workflowUpdate.delete_modes = [];
+  workflowUpdate.append_modes = [];
+  workflowModes.addModes = [];
+  workflowModes.deleteModes = [];
   if (workflowIconInputElement.value != undefined) {
     workflowIconInputElement.value.value = "";
   }
@@ -179,6 +230,16 @@ function updateWorkflow() {
   if (workflowUpdateForm.value?.checkValidity() && formState.allowUpload) {
     formState.loading = true;
     workflowGitCommitHashElement.value?.setCustomValidity("");
+    if (formState.modesEnabled) {
+      workflowUpdate.append_modes = workflowModes.addModes.map((mode) => {
+        return {
+          schema_path: mode.schema_path,
+          entrypoint: mode.entrypoint,
+          name: mode.name,
+        } as WorkflowModeIn;
+      });
+      workflowUpdate.delete_modes = workflowModes.deleteModes;
+    }
     WorkflowService.workflowUpdateWorkflow(
       props.workflow.workflow_id,
       workflowUpdate,
@@ -196,6 +257,8 @@ function updateWorkflow() {
             "Git commit is already used by a workflow",
           );
         }
+        workflowUpdate.delete_modes = [];
+        workflowUpdate.append_modes = [];
       })
       .finally(() => {
         formState.loading = false;
@@ -203,11 +266,67 @@ function updateWorkflow() {
   }
 }
 
+function updateModeMapping() {
+  const modeIds = latestVersion.value.modes.filter(
+    (modeId) => !formState.modeMapping[modeId],
+  );
+  Promise.all(
+    modeIds.map((modeId) =>
+      WorkflowModeService.workflowModeGetWorkflowMode(modeId),
+    ),
+  ).then((modes) => {
+    for (const mode of modes) {
+      formState.modeMapping[mode.mode_id] = mode;
+    }
+  });
+}
+
+function addMode() {
+  workflowModes.addModes.push({
+    mode_id: crypto.randomUUID(),
+    name: "",
+    schema_path: "",
+    entrypoint: "",
+  });
+  formState.allowUpload = false;
+}
+
+function addOldMode(mode_id: string) {
+  if (
+    latestVersion.value.modes.length +
+      workflowModes.addModes.length -
+      workflowModes.deleteModes.length <
+    10
+  ) {
+    workflowModes.deleteModes = workflowModes.deleteModes.filter(
+      (mode) => mode != mode_id,
+    );
+    formState.allowUpload = false;
+  }
+}
+
+function removeNewMode(mode_id: string) {
+  if (latestVersion.value.modes.length + workflowModes.addModes.length > 1) {
+    workflowModes.addModes = workflowModes.addModes.filter(
+      (mode) => mode.mode_id != mode_id,
+    );
+    formState.allowUpload = false;
+  }
+}
+
+function removeOldMode(mode_id: string) {
+  workflowModes.deleteModes.push(mode_id);
+  formState.allowUpload = false;
+}
+
 // Lifecycle Events
 // =============================================================================
 onMounted(() => {
   updateWorkflowModal = new Modal("#" + props.modalID);
   successToast = new Toast("#successToast-" + randomIDSuffix);
+  workflowModesCollapse = new Collapse("#updateWorkflowModesCollapse", {
+    toggle: false,
+  });
 });
 </script>
 
@@ -269,7 +388,7 @@ onMounted(() => {
             :hidden="!showIcon"
           />
         </div>
-        <div class="row">
+        <div class="row mb-3">
           <div class="col-8">
             <label for="workflowGitCommitInput" class="form-label"
               >Git Commit Hash</label
@@ -324,6 +443,216 @@ onMounted(() => {
             </div>
           </div>
         </div>
+        <div class="mb-3">
+          <div class="form-check fs-5">
+            <input
+              class="form-check-input"
+              type="checkbox"
+              v-model="formState.modesEnabled"
+              id="updateWorkflowModesCheckbox"
+              @change="formState.allowUpload = false"
+              aria-controls="#updateWorkflowModesCollapse"
+              :disabled="latestVersion.modes.length > 0"
+            />
+            <label class="form-check-label" for="updateWorkflowModesCheckbox">
+              Enable Workflow Modes
+            </label>
+            <button
+              v-if="formState.modesEnabled"
+              class="btn btn-primary float-end"
+              @click="addMode"
+              :disabled="
+                latestVersion.modes.length +
+                  workflowModes.addModes.length -
+                  workflowModes.deleteModes.length >=
+                10
+              "
+            >
+              Add Mode
+            </button>
+          </div>
+        </div>
+        <div class="collapse" id="updateWorkflowModesCollapse">
+          <WorkflowModeTransitionGroup>
+            <div
+              v-for="(mode_id, index) in latestVersion.modes"
+              :key="mode_id"
+              class="row mb-3"
+            >
+              <template v-if="formState.modeMapping[mode_id]">
+                <h6>
+                  <font-awesome-icon
+                    v-if="workflowModes.deleteModes.includes(mode_id)"
+                    icon="fa-solid fa-plus"
+                    class="text-success me-1 fs-6 cursor-pointer"
+                    @click="addOldMode(mode_id)"
+                  />
+                  <font-awesome-icon
+                    v-else
+                    icon="fa-solid fa-minus"
+                    class="text-danger me-1 fs-6 cursor-pointer"
+                    @click="removeOldMode(mode_id)"
+                  />
+                  <span
+                    :class="{
+                      'opacity-75': workflowModes.deleteModes.includes(mode_id),
+                    }"
+                    >Previous Mode {{ index + 1 }}</span
+                  >
+                </h6>
+                <div class="col-6">
+                  <label
+                    :for="'modeNameInput-' + mode_id"
+                    class="form-label"
+                    :class="{
+                      'opacity-75': workflowModes.deleteModes.includes(mode_id),
+                    }"
+                    >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-' + mode_id"
+                      maxlength="128"
+                      readonly
+                      :disabled="workflowModes.deleteModes.includes(mode_id)"
+                      v-model="formState.modeMapping[mode_id].name"
+                      :required="
+                        formState.modesEnabled &&
+                        !workflowModes.deleteModes.includes(mode_id)
+                      "
+                    />
+                  </div>
+                </div>
+                <div class="col-6 mb-2">
+                  <label
+                    :for="'modeEntryInput-' + mode_id"
+                    class="form-label"
+                    :class="{
+                      'opacity-75': workflowModes.deleteModes.includes(mode_id),
+                    }"
+                    >Entrypoint</label
+                  >
+                  <div class="input-group">
+                    <div class="input-group-text">
+                      <font-awesome-icon icon="fa-solid fa-turn-down" />
+                    </div>
+                    <input
+                      type="text"
+                      class="form-control"
+                      :id="'modeEntryInput-' + mode_id"
+                      readonly
+                      :disabled="workflowModes.deleteModes.includes(mode_id)"
+                      v-model="formState.modeMapping[mode_id].entrypoint"
+                      :required="
+                        formState.modesEnabled &&
+                        !workflowModes.deleteModes.includes(mode_id)
+                      "
+                    />
+                  </div>
+                </div>
+                <label
+                  :for="'modeSchemaInput-' + index"
+                  class="form-label"
+                  :class="{
+                    'opacity-75': workflowModes.deleteModes.includes(mode_id),
+                  }"
+                  >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-' + mode_id"
+                    readonly
+                    :disabled="workflowModes.deleteModes.includes(mode_id)"
+                    v-model="formState.modeMapping[mode_id].schema_path"
+                    :required="
+                      formState.modesEnabled &&
+                      !workflowModes.deleteModes.includes(mode_id)
+                    "
+                  />
+                </div>
+              </template>
+            </div>
+
+            <div
+              v-for="(mode, index) in workflowModes.addModes"
+              :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="removeNewMode(mode.mode_id)"
+                />
+                New Mode {{ latestVersion.modes.length + 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="formState.modesEnabled"
+                  />
+                </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-turn-down" />
+                  </div>
+                  <input
+                    type="text"
+                    class="form-control"
+                    :id="'modeEntryInput-' + index"
+                    maxlength="128"
+                    v-model="mode.entrypoint"
+                    :required="formState.modesEnabled"
+                  />
+                </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="formState.modesEnabled"
+                />
+              </div>
+            </div>
+          </WorkflowModeTransitionGroup>
+        </div>
       </form>
     </template>
     <template v-slot:footer>
diff --git a/src/router/index.ts b/src/router/index.ts
index cd6d25646eb4b2ff556af43ba1b667106b4e973a..817d3f059e3cd40841a2cf475af6601bb32ac7d3 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -58,16 +58,19 @@ const router = createRouter({
             import("../views/workflows/ArbitraryWorkflowView.vue"),
           meta: { requiresDeveloperRole: true },
           props: (route) => ({
-            repository: route.query.repository,
-            commit_hash: route.query.commit_hash,
-            token: route.query.token,
+            wid: route.query.wid,
           }),
         },
         {
           path: "workflows/:workflowId",
           name: "workflow",
           component: () => import("../views/workflows/WorkflowView.vue"),
-          props: true,
+          props: (route) => ({
+            versionId: route.params.versionId ?? undefined,
+            workflowId: route.params.workflowId,
+            workflowModeId: route.query.workflowModeId ?? undefined,
+            developerView: route.query.developerView == "true" ?? false,
+          }),
           children: [
             {
               path: "version/:versionId",
@@ -78,6 +81,7 @@ const router = createRouter({
                 versionId: route.params.versionId,
                 workflowId: route.params.workflowId,
                 activeTab: route.query.tab ?? "description",
+                workflowModeId: route.query.workflowModeId ?? undefined,
               }),
             },
             {
@@ -85,7 +89,11 @@ const router = createRouter({
               name: "workflow-start",
               component: () =>
                 import("../views/workflows/StartWorkflowView.vue"),
-              props: true,
+              props: (route) => ({
+                versionId: route.params.versionId,
+                workflowId: route.params.workflowId,
+                workflowModeId: route.query.workflowModeId ?? undefined,
+              }),
             },
           ],
         },
diff --git a/src/stores/devWorkflow.ts b/src/stores/devWorkflow.ts
new file mode 100644
index 0000000000000000000000000000000000000000..38d625c301186e460250f23e5fd08b4a0deb12fb
--- /dev/null
+++ b/src/stores/devWorkflow.ts
@@ -0,0 +1,18 @@
+import { defineStore } from "pinia";
+import type { WorkflowIn } from "@/client/workflow";
+
+export const useArbitraryWorkflowStore = defineStore({
+  id: "arbitraryWorkflows",
+  state: () => {
+    return {
+      arbitraryWorkflows: {} as Record<string, WorkflowIn>,
+    } as { arbitraryWorkflows: Record<string, WorkflowIn> };
+  },
+  actions: {
+    setWorkflow(workflow: WorkflowIn): string {
+      const wid = crypto.randomUUID();
+      this.arbitraryWorkflows[wid] = workflow;
+      return wid;
+    },
+  },
+});
diff --git a/src/utils/GitRepository.ts b/src/utils/GitRepository.ts
index 68004e6c06e19000f3710ff2db33f8430c200301..648010ce8ffda08bc69539d393a7520cd303a67a 100644
--- a/src/utils/GitRepository.ts
+++ b/src/utils/GitRepository.ts
@@ -1,14 +1,24 @@
 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, WorkflowModeIn } from "@/client/workflow";
+
+export function requiredRepositoryFiles(
+  modes?: WorkflowModeIn[] | WorkflowModeOut[],
+): string[] {
+  const list = [
+    "main.nf",
+    "CHANGELOG.md",
+    "README.md",
+    "docs/usage.md",
+    "docs/output.md",
+  ];
+  if (modes && 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";
@@ -109,16 +119,20 @@ class GithubRepository extends GitRepository {
     this.repoName = pathParts[1];
     if (token) {
       this.httpClient.interceptors.request.use((req) => {
-        req.auth = {
-          password: this.token,
-          username: this.account,
-        } as AxiosBasicCredentials;
+        if (!req.url?.includes("raw")) {
+          req.auth = {
+            password: this.token,
+            username: this.account,
+          } as AxiosBasicCredentials;
+        }
         return req;
       });
     }
     this.httpClient.interceptors.request.use((req) => {
-      req.headers.setAccept("application/vnd.github.object+json");
-      req.headers["X-GitHub-Api-Version"] = "2022-11-28";
+      if (!req.url?.includes("raw")) {
+        req.headers["X-GitHub-Api-Version"] = "2022-11-28";
+        req.headers.setAccept("application/vnd.github.object+json");
+      }
       return req;
     });
   }
@@ -132,7 +146,7 @@ class GithubRepository extends GitRepository {
   }
 
   protected async downloadFileUrl(filepath: string): Promise<string> {
-    if (this.token != undefined) {
+    if (this.token == undefined) {
       return Promise.resolve(
         `https://raw.githubusercontent.com/${this.account}/${this.repoName}/${this.gitCommitHash}/${filepath}`,
       );
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..ee5f05c9328b76a811aa141e7ba8ea7143c90125 100644
--- a/src/views/workflows/ArbitraryWorkflowView.vue
+++ b/src/views/workflows/ArbitraryWorkflowView.vue
@@ -1,30 +1,38 @@
 <script setup lang="ts">
 import WorkflowDocumentationTabs from "@/components/workflows/WorkflowDocumentationTabs.vue";
-import { onMounted, reactive, ref } from "vue";
+import { onMounted, reactive, ref, watch } from "vue";
 import { GitRepository, requiredRepositoryFiles } from "@/utils/GitRepository";
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 import ParameterSchemaFormComponent from "@/components/parameter-schema/ParameterSchemaFormComponent.vue";
 import { WorkflowExecutionService } from "@/client/workflow";
 import { useRouter } from "vue-router";
 import { Toast } from "bootstrap";
+import { useArbitraryWorkflowStore } from "@/stores/devWorkflow";
+import type { WorkflowIn } from "@/client/workflow";
 
 const props = defineProps<{
-  repository?: string;
-  commit_hash?: string;
-  token?: string;
+  wid: string;
 }>();
 
 const router = useRouter();
+const workflowStore = useArbitraryWorkflowStore();
 
 const workflowState = reactive<{
+  workflow?: WorkflowIn;
   loading: boolean;
   changelogMarkdown?: string;
   descriptionMarkdown?: string;
   usageMarkdown?: string;
   outputMarkdown?: string;
   parameterSchema?: Record<string, never>;
+  repo: GitRepository;
 }>({
   loading: true,
+  workflow: undefined,
+  repo: GitRepository.buildRepository(
+    "https://github.de/eample/example",
+    "0123456789abcdef",
+  ),
 });
 
 const workflowExecutionState = reactive<{
@@ -38,49 +46,63 @@ const workflowExecutionState = reactive<{
 const showDocumentation = ref<boolean>(true);
 let errorToast: Toast | null = null;
 
-function downloadVersionFiles(
-  repository: string,
-  commit_hash: string,
-  token?: string,
-) {
-  workflowState.loading = true;
-  const repo = GitRepository.buildRepository(repository, commit_hash, token);
-  Promise.all(
-    requiredRepositoryFiles.map((file) =>
-      repo.downloadFile(file).then((response) => {
-        if (file.includes("README")) {
-          workflowState.descriptionMarkdown = response.data;
-        } else if (file.includes("CHANGELOG")) {
-          workflowState.changelogMarkdown = response.data;
-        } else if (file.includes("schema")) {
-          workflowState.parameterSchema = response.data;
-        } else if (file.includes("usage")) {
-          workflowState.usageMarkdown = response.data;
-        } else if (file.includes("output")) {
-          workflowState.outputMarkdown = response.data;
-        }
-      }),
-    ),
-  ).finally(() => {
-    workflowState.loading = false;
-  });
+function downloadVersionFiles() {
+  if (workflowState.workflow) {
+    workflowState.loading = true;
+    Promise.all(
+      requiredRepositoryFiles(workflowState.workflow.modes).map((file) =>
+        workflowState.repo.downloadFile(file).then((response) => {
+          if (file.includes("README")) {
+            workflowState.descriptionMarkdown = response.data;
+          } else if (file.includes("CHANGELOG")) {
+            workflowState.changelogMarkdown = response.data;
+          } else if (file.includes("usage")) {
+            workflowState.usageMarkdown = response.data;
+          } else if (file.includes("output")) {
+            workflowState.outputMarkdown = response.data;
+          } else {
+            workflowState.parameterSchema = response.data;
+          }
+        }),
+      ),
+    ).finally(() => {
+      workflowState.loading = false;
+    });
+  }
 }
 
+watch(
+  () => workflowState.workflow,
+  (newWorkflow, oldWorkflow) => {
+    if (
+      newWorkflow &&
+      newWorkflow?.git_commit_hash !== oldWorkflow?.git_commit_hash
+    ) {
+      workflowState.repo = GitRepository.buildRepository(
+        newWorkflow.repository_url,
+        newWorkflow.git_commit_hash,
+        newWorkflow.token ?? undefined,
+      );
+      downloadVersionFiles();
+    }
+  },
+);
+
 function startWorkflow(
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
   parameters: Record<string, any>,
   notes?: string,
   report_output_bucket?: string,
 ) {
-  if (props.repository && props.commit_hash) {
+  if (workflowState.workflow) {
     errorToast?.hide();
     workflowExecutionState.loading = true;
     WorkflowExecutionService.workflowExecutionStartArbitraryWorkflow({
-      git_commit_hash: props.commit_hash,
+      git_commit_hash: workflowState.workflow.git_commit_hash,
       parameters: parameters,
       report_output_bucket: report_output_bucket,
-      repository_url: props.repository,
-      token: props.token,
+      repository_url: workflowState.workflow.repository_url,
+      token: workflowState.workflow.token ?? undefined,
     })
       .then(() => {
         router.push({
@@ -102,9 +124,7 @@ function startWorkflow(
 
 onMounted(() => {
   errorToast = new Toast("#arbitraryWorkflowExecutionViewErrorToast");
-  if (props.commit_hash && props.repository) {
-    downloadVersionFiles(props.repository, props.commit_hash, props.token);
-  }
+  workflowState.workflow = workflowStore.arbitraryWorkflows[props.wid];
 });
 </script>
 
@@ -137,26 +157,38 @@ onMounted(() => {
       </div>
     </div>
   </div>
-  <div class="row m-1 border-bottom mb-4">
-    <h1 class="mb-2">Arbitrary Workflow</h1>
-  </div>
-  <h4>
-    Git Repository: <a target="_blank" :href="repository">{{ repository }}</a>
-  </h4>
-  <h4 class="mb-5">Git Commit Hash: {{ commit_hash }}</h4>
-  <div class="d-flex justify-content-center mb-5" v-if="showDocumentation">
-    <a
-      role="button"
-      href="#"
-      class="btn btn-success btn-lg mx-auto fs-4"
-      :class="{ disabled: !workflowState.parameterSchema }"
-      @click="showDocumentation = false"
-    >
-      <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" />
-      <span class="align-middle">Launch</span>
-    </a>
-  </div>
-  <template v-if="repository && commit_hash">
+  <template v-if="workflowState.workflow">
+    <div class="row m-1 border-bottom mb-4">
+      <h1 class="mb-2">Arbitrary Workflow</h1>
+    </div>
+    <h4>
+      Git Repository:
+      <a target="_blank" :href="workflowState.workflow?.repository_url">{{
+        workflowState.workflow?.repository_url
+      }}</a>
+    </h4>
+    <h4 :class="{ 'mb-5': workflowState.workflow.modes!.length < 1 }">
+      Git Commit Hash: {{ workflowState.workflow?.git_commit_hash }}
+    </h4>
+    <template v-if="workflowState.workflow.modes!.length > 0">
+      <h5>Entrypoint: {{ workflowState.workflow?.modes?.[0].entrypoint }}</h5>
+      <h5 class="mb-5">
+        Schema File:
+        {{ workflowState.workflow?.modes?.[0].schema_path }}
+      </h5>
+    </template>
+    <div class="d-flex justify-content-center mb-5" v-if="showDocumentation">
+      <a
+        role="button"
+        href="#"
+        class="btn btn-success btn-lg mx-auto fs-4"
+        :class="{ disabled: !workflowState.parameterSchema }"
+        @click="showDocumentation = false"
+      >
+        <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" />
+        <span class="align-middle">Launch</span>
+      </a>
+    </div>
     <workflow-documentation-tabs
       v-if="showDocumentation"
       :loading="workflowState.loading"
@@ -173,7 +205,17 @@ onMounted(() => {
       @start-workflow="startWorkflow"
     />
   </template>
-  <p v-else>Nope</p>
+  <template v-else>
+    <div class="text-center fs-1 mt-5">
+      <font-awesome-icon
+        icon="fa-solid fa-magnifying-glass"
+        class="my-5 fs-0"
+        style="color: var(--bs-secondary)"
+      />
+      <p class="my-5">Could not find your workflow.<br />Please re-enter it.</p>
+      <router-link :to="{ name: 'workflows' }" class="mt-5">Back</router-link>
+    </div>
+  </template>
 </template>
 
 <style scoped></style>
diff --git a/src/views/workflows/MyWorkflowsView.vue b/src/views/workflows/MyWorkflowsView.vue
index 882df7869b1feb2b2c6338b46e4f8a0604d3a6de..de39691f3a6ccf2e2520040edef187b9107691bd 100644
--- a/src/views/workflows/MyWorkflowsView.vue
+++ b/src/views/workflows/MyWorkflowsView.vue
@@ -45,7 +45,7 @@ const workflowsState = reactive<{
     version: "",
     workflow_id: "",
     git_commit_hash: "",
-    modes: null,
+    modes: [],
     icon_url: null,
     created_at: 0,
     status: Status.CREATED,
@@ -64,6 +64,25 @@ function workflowUpdated(version: WorkflowVersion) {
   workflowsState.workflows
     .find((w) => w.workflow_id == version.workflow_id)
     ?.versions.push(version);
+  workflowsState.updateWorkflow = {
+    short_description: "",
+    name: "",
+    versions: [
+      {
+        version: "1.0.0",
+        created_at: 0,
+        git_commit_hash: "",
+        status: Status.CREATED,
+        workflow_id: "",
+        icon_url: "",
+        modes: [],
+      },
+    ],
+    repository_url: "",
+    workflow_id: "",
+    developer_id: "",
+    private: false,
+  };
 }
 
 function workflowDeleteClicked(workflow: WorkflowOut) {
diff --git a/src/views/workflows/ReviewWorkflowsView.vue b/src/views/workflows/ReviewWorkflowsView.vue
index fd121ea16ac775d9c0c96742781fe7cac805bf46..3e34f2098262994918ba1f16ea90d9257d9c1461 100644
--- a/src/views/workflows/ReviewWorkflowsView.vue
+++ b/src/views/workflows/ReviewWorkflowsView.vue
@@ -165,15 +165,19 @@ onMounted(() => {
                       {{ version.git_commit_hash }}
                     </a>
                   </td>
+                  <td>#Modes: {{ version.modes.length }}</td>
                   <td>
                     <router-link
-                      target="_blank"
                       :to="{
                         name: 'workflow-version',
                         params: {
                           workflowId: workflow.workflow_id,
                           versionId: version.git_commit_hash,
                         },
+                        query: {
+                          developerView: 'true',
+                          workflowModeId: version.modes[0],
+                        },
                       }"
                     >
                       View
diff --git a/src/views/workflows/StartWorkflowView.vue b/src/views/workflows/StartWorkflowView.vue
index 6a6dba2545d4b2bbb27f325e2c5d124932f2ec46..608163089902ec91729ba4ed91f2f13486dd3dcf 100644
--- a/src/views/workflows/StartWorkflowView.vue
+++ b/src/views/workflows/StartWorkflowView.vue
@@ -7,13 +7,14 @@ import {
   WorkflowExecutionService,
   WorkflowVersionService,
 } from "@/client/workflow";
-import { onMounted, ref, reactive } from "vue";
+import { onMounted, ref, reactive, watch } from "vue";
 import { useRouter } from "vue-router";
 import { Toast } from "bootstrap";
 
 const props = defineProps<{
   versionId: string;
   workflowId: string;
+  workflowModeId?: string;
 }>();
 
 const parameterSchema = ref(undefined);
@@ -33,26 +34,29 @@ const versionState = reactive<{
   workflowExecutionError: undefined,
 });
 
-function downloadVersion() {
-  WorkflowVersionService.workflowVersionGetWorkflowVersion(
-    props.versionId,
-    props.workflowId,
-  )
-    .then((version) => {
-      versionState.workflowVersion = version;
-      return version;
-    })
-    .then(downloadVersionFiles);
-}
+watch(
+  () => props.workflowModeId,
+  (newModeId, oldModeId) => {
+    if (newModeId !== oldModeId) {
+      downloadVersionFiles();
+    }
+  },
+);
 
-function downloadVersionFiles(version: WorkflowVersion) {
+function downloadVersionFiles() {
+  versionState.loading = true;
   WorkflowVersionService.workflowVersionDownloadWorkflowDocumentation(
-    version.workflow_id,
-    version.git_commit_hash,
+    props.workflowId,
+    props.versionId,
     DocumentationEnum.PARAMETER_SCHEMA,
-  ).then((markdown) => {
-    parameterSchema.value = markdown;
-  });
+    props.workflowModeId,
+  )
+    .then((markdown) => {
+      parameterSchema.value = markdown;
+    })
+    .finally(() => {
+      versionState.loading = false;
+    });
 }
 
 function startWorkflow(
@@ -69,6 +73,7 @@ function startWorkflow(
       parameters: parameters,
       notes: notes,
       report_output_bucket: report_output_bucket,
+      mode: props.workflowModeId,
     })
       .then(() => {
         router.push({
@@ -90,7 +95,7 @@ function startWorkflow(
 
 onMounted(() => {
   errorToast = new Toast("#workflowExecutionViewErrorToast");
-  downloadVersion();
+  downloadVersionFiles();
 });
 </script>
 
diff --git a/src/views/workflows/WorkflowVersionView.vue b/src/views/workflows/WorkflowVersionView.vue
index 42de6e1fddad6a8e27da3cfbb69136abbc90b946..e815705d6df515463f850a4a7066a44f94978b6e 100644
--- a/src/views/workflows/WorkflowVersionView.vue
+++ b/src/views/workflows/WorkflowVersionView.vue
@@ -7,6 +7,7 @@ import WorkflowDocumentationTabs from "@/components/workflows/WorkflowDocumentat
 const props = defineProps<{
   versionId: string;
   workflowId: string;
+  workflowModeId?: string;
 }>();
 
 const versionState = reactive<{
@@ -41,6 +42,22 @@ watch(
   },
 );
 
+watch(
+  () => props.workflowModeId,
+  (newModeId, oldModeId) => {
+    if (newModeId !== oldModeId) {
+      WorkflowVersionService.workflowVersionDownloadWorkflowDocumentation(
+        props.workflowId,
+        props.versionId,
+        DocumentationEnum.PARAMETER_SCHEMA,
+        newModeId,
+      ).then((schema) => {
+        versionState.parameterSchema = schema;
+      });
+    }
+  },
+);
+
 function updateVersion(versionId: string, workflowId: string) {
   versionState.loading = true;
   versionState.fileLoading = true;
@@ -84,8 +101,9 @@ function downloadVersionFiles(version: WorkflowVersion) {
       version.workflow_id,
       version.git_commit_hash,
       DocumentationEnum.PARAMETER_SCHEMA,
-    ).then((markdown) => {
-      versionState.parameterSchema = markdown;
+      props.workflowModeId,
+    ).then((schema) => {
+      versionState.parameterSchema = schema;
     });
   const usagePromise =
     WorkflowVersionService.workflowVersionDownloadWorkflowDocumentation(
diff --git a/src/views/workflows/WorkflowView.vue b/src/views/workflows/WorkflowView.vue
index 05e3ee2cfe6507f6fc40e63604ab74e8071ba375..32e1dc3b5d252431a8b55e2b469d10f739573e67 100644
--- a/src/views/workflows/WorkflowView.vue
+++ b/src/views/workflows/WorkflowView.vue
@@ -1,16 +1,18 @@
 <script setup lang="ts">
 import { computed, onMounted, reactive, watch } from "vue";
 import type {
+  WorkflowModeOut,
   WorkflowOut,
   WorkflowStatistic,
   WorkflowVersion,
 } from "@/client/workflow";
-import WorkflowStatisticsChart from "@/components/workflows/WorkflowStatisticsChart.vue";
 import {
   Status,
+  WorkflowModeService,
   WorkflowService,
   WorkflowVersionService,
 } from "@/client/workflow";
+import WorkflowStatisticsChart from "@/components/workflows/WorkflowStatisticsChart.vue";
 import { useRoute, useRouter } from "vue-router";
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 import {
@@ -27,6 +29,8 @@ const userRepository = useAuthStore();
 const props = defineProps<{
   workflowId: string;
   versionId?: string;
+  workflowModeId?: string;
+  developerView: boolean;
 }>();
 
 // Constants
@@ -42,12 +46,16 @@ const workflowState = reactive<{
   activeVersionId: string;
   initialOpen: boolean;
   stats: WorkflowStatistic[];
+  modeMapping: Record<string, WorkflowModeOut>;
+  activeModeId?: string;
 }>({
   loading: true,
   workflow: undefined,
-  activeVersionId: "",
+  activeVersionId: props.versionId ?? "",
   initialOpen: true,
   stats: [],
+  modeMapping: {},
+  activeModeId: props.workflowModeId,
 });
 
 // Watchers
@@ -68,6 +76,15 @@ watch(
   },
 );
 
+watch(
+  () => props.workflowModeId,
+  (newModeId) => {
+    if (newModeId) {
+      workflowState.activeModeId = newModeId;
+    }
+  },
+);
+
 watch(
   () => workflowState.activeVersionId,
   (newVersionId, oldVersionId) => {
@@ -76,10 +93,38 @@ watch(
       newVersionId !== oldVersionId &&
       route.name !== "workflow-start"
     ) {
+      // If mode does not exist in other version, select another mode
+      if (
+        activeVersionModeIds.value.length > 0 &&
+        activeVersionModeIds.value.findIndex(
+          (modeId) => modeId === workflowState.activeModeId,
+        ) == -1
+      ) {
+        workflowState.activeModeId = activeVersionModeIds.value[0];
+      } else if (activeVersionModeIds.value.length == 0) {
+        // If new version does not has any modes, then set mode id to none
+        workflowState.activeModeId = undefined;
+      }
       router.push({
         name: "workflow-version",
         params: { versionId: newVersionId },
-        query: { tab: route.query.tab },
+        query: {
+          tab: route.query.tab,
+          workflowModeId: workflowState.activeModeId,
+        },
+      });
+    }
+  },
+);
+
+watch(
+  () => workflowState.activeModeId,
+  (newModeId, oldModeId) => {
+    if (newModeId != oldModeId) {
+      router.push({
+        name: route.name ?? undefined,
+        params: { versionId: workflowState.activeVersionId },
+        query: { tab: route.query.tab, workflowModeId: newModeId },
       });
     }
   },
@@ -101,6 +146,10 @@ const activeVersion = computed<WorkflowVersion | undefined>(
     ),
 );
 
+const activeVersionModeIds = computed<string[]>(
+  () => activeVersion.value?.modes ?? [],
+);
+
 const activeVersionString = computed<string>(
   () => activeVersion.value?.version ?? "",
 );
@@ -135,7 +184,10 @@ const allowVersionDeprecation = computed<boolean>(() => {
 // =============================================================================
 function updateWorkflow(workflowId: string) {
   workflowState.loading = true;
-  WorkflowService.workflowGetWorkflow(workflowId)
+  WorkflowService.workflowGetWorkflow(
+    workflowId,
+    props.developerView ? Object.values(Status) : undefined,
+  )
     .then((workflow) => {
       workflowState.workflow = workflow;
       if (!workflowState.initialOpen || !route.params.versionId) {
@@ -144,6 +196,43 @@ function updateWorkflow(workflowId: string) {
       } else {
         workflowState.activeVersionId = route.params.versionId as string;
       }
+      workflowState.activeModeId = activeVersionModeIds.value[0] ?? undefined;
+      return workflow;
+    })
+    .then(
+      (
+        workflow, // map to mode ids
+      ) => workflow.versions.map((version) => version.modes).flat(),
+    )
+    .then(
+      (
+        modeIds, // filter mode ids
+      ) =>
+        modeIds
+          .filter((modeId) => modeId != null) // filter null modes
+          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+          .filter((modeId) => !workflowState.modeMapping[modeId!])
+          .filter(
+            // filter unique workflow versions
+            (modeId, index, array) =>
+              array.findIndex((val) => val === modeId) === index,
+          ),
+    )
+    .then(
+      (
+        modeIds, // download workflow modes
+      ) =>
+        Promise.all(
+          modeIds.map((modeId) =>
+            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+            WorkflowModeService.workflowModeGetWorkflowMode(modeId!),
+          ),
+        ),
+    )
+    .then((modes) => {
+      for (const mode of modes) {
+        workflowState.modeMapping[mode.mode_id] = mode;
+      }
     })
     .catch(() => {
       workflowState.workflow = undefined;
@@ -214,7 +303,24 @@ onMounted(() => {
         alt="Workflow icon"
       />
     </div>
-    <p class="fs-4 mb-5 mt-3">{{ workflowState.workflow.short_description }}</p>
+    <p class="fs-4 mt-3">{{ workflowState.workflow.short_description }}</p>
+    <div
+      v-if="activeVersionModeIds.length > 0"
+      class="row align-items-center mb-3 fs-5"
+    >
+      <label class="col-sm-1 col-form-label">Mode:</label>
+      <div class="col-sm-11">
+        <select class="form-select w-fit" v-model="workflowState.activeModeId">
+          <option
+            v-for="modeId of activeVersionModeIds"
+            :key="modeId"
+            :value="modeId"
+          >
+            {{ workflowState.modeMapping[modeId].name }}
+          </option>
+        </select>
+      </div>
+    </div>
     <template v-if="route.name !== 'workflow-start'">
       <div
         v-if="!versionLaunchable"
@@ -256,6 +362,9 @@ onMounted(() => {
               versionId: props.versionId,
               workflowId: props.workflowId,
             },
+            query: {
+              workflowModeId: workflowState.activeModeId,
+            },
           }"
         >
           <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" />