diff --git a/src/assets/main.css b/src/assets/main.css
index 8237a72ed8cd830c4dfca825a3cc69eb7ed07564..30edd8d3f5626056cc2b2d22a7310ba56a3b0457 100644
--- a/src/assets/main.css
+++ b/src/assets/main.css
@@ -3,6 +3,10 @@ body {
     background: #181818;
 }
 
+.fs-0 {
+    font-size: 3.5rem;
+}
+
 .top-toast {
     top: 4rem;
 }
diff --git a/src/components/parameter-schema/ParameterSchemaFormComponent.vue b/src/components/parameter-schema/ParameterSchemaFormComponent.vue
index b80fd1eb59bcedf639a898f81065ad497ae78be6..29ebd83f608caf4cf899159fd0380ce9a6301494 100644
--- a/src/components/parameter-schema/ParameterSchemaFormComponent.vue
+++ b/src/components/parameter-schema/ParameterSchemaFormComponent.vue
@@ -14,7 +14,6 @@ import { Toast } from "bootstrap";
 const props = defineProps({
   schema: {
     type: Object,
-    required: true,
   },
   workflowVersionId: {
     type: String,
@@ -66,7 +65,7 @@ const formState = reactive<{
 // Computed Properties
 // =============================================================================
 const parameterGroups = computed<Record<string, never>>(
-  () => props.schema["definitions"]
+  () => props.schema?.["definitions"]
 );
 
 // Create a list with the names of all parameter groups
@@ -94,7 +93,9 @@ const navParameterGroups = computed<ParameterGroup[]>(() =>
 watch(
   () => props.schema,
   (newValue) => {
-    updateSchema(newValue);
+    if (newValue) {
+      updateSchema(newValue);
+    }
   }
 );
 
@@ -102,7 +103,7 @@ watch(
 // =============================================================================
 /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/ban-ts-comment, @typescript-eslint/no-unused-vars */
 function updateSchema(schema: Record<string, any>) {
-  validateSchema = schemaCompiler.compile(props.schema);
+  validateSchema = schemaCompiler.compile(schema);
   const b = Object.keys(schema["definitions"]).map((groupName) => [
     groupName,
     Object.fromEntries(
@@ -122,6 +123,7 @@ function updateSchema(schema: Record<string, any>) {
 
 function startWorkflow() {
   formState.validated = true;
+  formState.errorType = undefined;
   if (launchForm.value?.checkValidity()) {
     const realInput = Object.values(formState.formInput).reduce((acc, val) => {
       return { ...acc, ...val };
@@ -132,7 +134,6 @@ function startWorkflow() {
       console.error(validateSchema.errors);
       errorToast?.show();
     } else {
-      formState.errorType = undefined;
       formState.loading = true;
       WorkflowExecutionService.workflowExecutionStartWorkflow({
         workflow_version_id: props.workflowVersionId,
@@ -154,13 +155,16 @@ function startWorkflow() {
           formState.loading = false;
         });
     }
+  } else {
+    formState.errorType = "form";
+    errorToast?.show();
   }
 }
 
 // Lifecycle Events
 // =============================================================================
 onMounted(() => {
-  updateSchema(props.schema);
+  if (props.schema) updateSchema(props.schema);
   errorToast = new Toast("#workflowExecutionErrorToast");
 });
 </script>
@@ -175,17 +179,22 @@ onMounted(() => {
       data-bs-autohide="true"
       id="workflowExecutionErrorToast"
     >
-      <div class="d-flex p-2">
-        <div v-if="formState.errorType === 'limit'" class="toast-body">
-          You have too many active workflow executions to start a new one
-        </div>
-        <div v-else>
-          There was an error with starting the workflow execution. Look in the
-          console for more information
+      <div class="d-flex p-2 justify-content-between align-items-center">
+        <div class="toast-body">
+          <template v-if="formState.errorType === 'limit'">
+            You have too many active workflow executions to start a new one.
+          </template>
+          <template v-else-if="formState.errorType === 'form'">
+            Some inputs are not valid.
+          </template>
+          <template v-else>
+            There was an error with starting the workflow execution. Look in the
+            console for more information.
+          </template>
         </div>
         <button
           type="button"
-          class="btn-close btn-close-white m-auto"
+          class="btn-close btn-close-white"
           data-bs-dismiss="toast"
           aria-label="Close"
         ></button>
@@ -194,10 +203,13 @@ onMounted(() => {
   </div>
   <div class="row mb-5 align-items-start">
     <form
+      v-if="props.schema"
       class="col-9"
       id="launchWorkflowForm"
       ref="launchForm"
       :class="{ 'was-validated': formState.validated }"
+      @submit.prevent="startWorkflow"
+      novalidate
     >
       <div class="card bg-dark mb-3">
         <h2 class="card-header" id="pipelineGeneralOptions">
@@ -218,7 +230,7 @@ onMounted(() => {
             </span>
             <textarea
               class="form-control"
-              rows="2"
+              rows="1"
               v-model="formState.pipelineNotes"
             />
           </div>
@@ -260,6 +272,27 @@ onMounted(() => {
         />
       </template>
     </form>
+    <!-- Loading card -->
+    <div v-else class="col-9">
+      <div class="card bg-dark mb-3">
+        <h2 class="card-header placeholder-glow">
+          <span class="placeholder col-6"></span>
+        </h2>
+        <div class="card-body">
+          <h5 class="card-title placeholder-glow">
+            <span class="placeholder col-5"> </span>
+          </h5>
+          <template v-for="n in 4" :key="n">
+            <div class="placeholder-glow fs-5">
+              <span class="placeholder w-100"> </span>
+            </div>
+            <div class="mb-3 placeholder-glow">
+              <span class="placeholder col-3"> </span>
+            </div>
+          </template>
+        </div>
+      </div>
+    </div>
     <div
       class="col-3 sticky-top bg-dark rounded-1 px-0"
       style="top: 70px !important; max-height: calc(100vh - 150px)"
@@ -268,9 +301,8 @@ onMounted(() => {
         <button
           type="submit"
           form="launchWorkflowForm"
-          @click.prevent="startWorkflow"
           class="btn btn-success w-50 mx-2"
-          :disabled="formState.loading"
+          :disabled="formState.loading || !props.schema"
         >
           <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" />
           Launch
@@ -286,7 +318,7 @@ onMounted(() => {
         </router-link>
       </div>
       <nav class="h-100">
-        <nav class="nav">
+        <nav v-if="props.schema" class="nav">
           <ul class="ps-0">
             <li class="nav-link">
               <a href="#pipelineGeneralOptions"
@@ -309,6 +341,14 @@ onMounted(() => {
             </li>
           </ul>
         </nav>
+        <!-- Loading nav links -->
+        <div v-else class="placeholder-glow ps-3 pt-3">
+          <span
+            v-for="n in 5"
+            :key="n"
+            class="placeholder col-8 mt-2 mb-3"
+          ></span>
+        </div>
       </nav>
     </div>
   </div>
diff --git a/src/router/index.ts b/src/router/index.ts
index 3460872612edae5a193e4d2e6a3767e637c5ce47..c52fe14c0f359ba4979f022292602f2ead1aab12 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -46,7 +46,7 @@ const router = createRouter({
           meta: { requiresReviewerRole: true },
         },
         {
-          path: "workflows/:workflowId/",
+          path: "workflows/:workflowId",
           name: "workflow",
           component: () => import("../views/workflows/WorkflowView.vue"),
           props: true,
@@ -62,6 +62,13 @@ const router = createRouter({
                 activeTab: route.query.tab ?? "description",
               }),
             },
+            {
+              path: "version/:versionId/start",
+              name: "workflow-start",
+              component: () =>
+                import("../views/workflows/StartWorkflowView.vue"),
+              props: true,
+            },
           ],
         },
       ],
diff --git a/src/views/workflows/StartWorkflowView.vue b/src/views/workflows/StartWorkflowView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b539b33e5d26394231004855e6b80b61a6e54a28
--- /dev/null
+++ b/src/views/workflows/StartWorkflowView.vue
@@ -0,0 +1,55 @@
+<script setup lang="ts">
+import ParameterSchemaFormComponent from "@/components/parameter-schema/ParameterSchemaFormComponent.vue";
+import type { WorkflowVersionFull } from "@/client/workflow";
+import { WorkflowVersionService } from "@/client/workflow";
+import axios from "axios";
+import { onMounted, ref, reactive } from "vue";
+import type { JSONSchemaType } from "ajv";
+
+const props = defineProps<{
+  versionId: string;
+  workflowId: string;
+}>();
+
+const parameterSchema = ref(undefined);
+
+const versionState = reactive<{
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  parameterSchema?: JSONSchemaType<any>;
+  workflowVersion?: WorkflowVersionFull;
+}>({
+  parameterSchema: undefined,
+  workflowVersion: undefined,
+});
+
+function downloadVersion() {
+  WorkflowVersionService.workflowVersionGetWorkflowVersion(
+    props.versionId,
+    props.workflowId
+  )
+    .then((version) => {
+      versionState.workflowVersion = version;
+      return version;
+    })
+    .then(downloadVersionFiles);
+}
+
+function downloadVersionFiles(version: WorkflowVersionFull) {
+  axios.get(version.parameter_schema_url).then((response) => {
+    parameterSchema.value = response.data;
+  });
+}
+
+onMounted(() => {
+  downloadVersion();
+});
+</script>
+
+<template>
+  <parameter-schema-form-component
+    :workflow-version-id="versionId"
+    :schema="parameterSchema"
+  />
+</template>
+
+<style scoped></style>
diff --git a/src/views/workflows/WorkflowView.vue b/src/views/workflows/WorkflowView.vue
index 9a5b54fc2778d4531c8f134cfc42095633b0e40d..efff5466d9dd065f3d1e049bad9927dade635bbb 100644
--- a/src/views/workflows/WorkflowView.vue
+++ b/src/views/workflows/WorkflowView.vue
@@ -57,7 +57,11 @@ watch(
 watch(
   () => workflowState.activeVersionId,
   (newVersionId, oldVersionId) => {
-    if (newVersionId !== oldVersionId) {
+    if (
+      newVersionId &&
+      newVersionId !== oldVersionId &&
+      route.name !== "workflow-start"
+    ) {
       router.push({
         name: "workflow-version",
         params: { versionId: newVersionId },
@@ -101,7 +105,7 @@ function updateWorkflow(workflowId: string) {
   WorkflowService.workflowGetWorkflow(workflowId)
     .then((workflow) => {
       workflowState.workflow = workflow;
-      if (!workflowState.initialOpen || route.params.versionId == null) {
+      if (!workflowState.initialOpen || !route.params.versionId) {
         workflowState.activeVersionId =
           workflow.versions[workflow.versions.length - 1].git_commit_hash;
       } else {
@@ -145,7 +149,10 @@ onMounted(() => {
   </div>
   <div v-else-if="workflowState.workflow != null">
     <div class="d-flex justify-content-between align-items-center">
-      <span class="fs-0 w-fit">{{ workflowState.workflow.name }}</span>
+      <div class="fs-0 w-fit text-light">
+        {{ workflowState.workflow.name }}
+        <span v-if="activeVersionString">@{{ activeVersionString }}</span>
+      </div>
       <a :href="workflowState.workflow.repository_url" target="_blank">
         <img
           v-if="activeVersionIcon != null"
@@ -155,70 +162,80 @@ onMounted(() => {
       /></a>
     </div>
     <p class="fs-4 mb-5 mt-3">{{ workflowState.workflow.short_description }}</p>
-    <div
-      v-if="!versionLaunchable"
-      class="alert alert-warning w-fit mx-auto"
-      role="alert"
-    >
-      This version can not be used.
-      <router-link
-        v-if="latestVersion != null"
-        class="alert-link"
-        :to="{
-          name: 'workflow-version',
-          params: {
-            versionId: latestVersion.git_commit_hash,
-          },
-          query: { tab: route.query.tab },
-        }"
-        >Try the latest version {{ latestVersion?.version }}.</router-link
-      >
-    </div>
-    <div class="row align-items-center">
-      <a
-        role="button"
-        class="btn btn-success btn-lg w-fit mx-auto"
-        :class="{ disabled: !versionLaunchable }"
-        href="#"
-      >
-        <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" />
-        <span class="align-middle">Launch {{ activeVersionString }}</span>
-      </a>
+    <template v-if="route.name !== 'workflow-start'">
       <div
-        v-if="latestVersion != null"
-        class="input-group w-fit position-absolute end-0"
+        v-if="!versionLaunchable"
+        class="alert alert-warning w-fit mx-auto"
+        role="alert"
       >
-        <span class="input-group-text px-2" id="workflow-version-wrapping"
-          ><font-awesome-icon icon="fa-solid fa-tags" class="text-secondary"
-        /></span>
-        <select
-          class="form-select form-select-sm"
-          aria-label="Workflow version selection"
-          aria-describedby="workflow-version-wrapping"
-          v-model="workflowState.activeVersionId"
+        This version can not be used.
+        <router-link
+          v-if="latestVersion != null"
+          class="alert-link"
+          :to="{
+            name: 'workflow-version',
+            params: {
+              versionId: latestVersion.git_commit_hash,
+            },
+            query: { tab: route.query.tab },
+          }"
+          >Try the latest version {{ latestVersion?.version }}.</router-link
+        >
+      </div>
+      <div class="row align-items-center">
+        <router-link
+          role="button"
+          class="btn btn-success btn-lg w-fit mx-auto"
+          :class="{ disabled: !versionLaunchable }"
+          :to="{
+            name: 'workflow-start',
+            params: {
+              versionId: props.versionId,
+              workflowId: props.workflowId,
+            },
+          }"
+        >
+          <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" />
+          <span class="align-middle">Launch {{ activeVersionString }}</span>
+        </router-link>
+        <div
+          v-if="latestVersion != null"
+          class="input-group w-fit position-absolute end-0"
         >
-          <option
-            v-for="version in sortedVersions(workflowState.workflow?.versions)"
-            :key="version.git_commit_hash"
-            :value="version.git_commit_hash"
+          <span class="input-group-text px-2" id="workflow-version-wrapping"
+            ><font-awesome-icon icon="fa-solid fa-tags" class="text-secondary"
+          /></span>
+          <select
+            class="form-select form-select-sm"
+            aria-label="Workflow version selection"
+            aria-describedby="workflow-version-wrapping"
+            v-model="workflowState.activeVersionId"
           >
-            {{ version.version }}
-          </option>
-        </select>
+            <option
+              v-for="version in sortedVersions(
+                workflowState.workflow?.versions
+              )"
+              :key="version.git_commit_hash"
+              :value="version.git_commit_hash"
+            >
+              {{ version.version }}
+            </option>
+          </select>
+        </div>
       </div>
-    </div>
-    <div class="row w-100 mb-4 mt-2 mx-0">
-      <a
-        :href="workflowState.workflow.repository_url"
-        target="_blank"
-        class="text-secondary text-decoration-none mx-auto w-fit p-0"
-      >
-        <font-awesome-icon :icon="gitIcon" class="me-1" />
-        <span class="align-middle">
-          {{ workflowState.workflow.repository_url }}</span
-        ></a
-      >
-    </div>
+      <div class="row w-100 mb-4 mt-2 mx-0">
+        <a
+          :href="workflowState.workflow.repository_url"
+          target="_blank"
+          class="text-secondary text-decoration-none mx-auto w-fit p-0"
+        >
+          <font-awesome-icon :icon="gitIcon" class="me-1" />
+          <span class="align-middle">
+            {{ workflowState.workflow.repository_url }}</span
+          ></a
+        >
+      </div>
+    </template>
   </div>
   <router-view v-if="workflowState.loading || workflowState.workflow != null" />
   <div v-else class="text-center fs-1 mt-5">
@@ -235,10 +252,6 @@ onMounted(() => {
 </template>
 
 <style scoped>
-.fs-0 {
-  font-size: 4em;
-}
-
 .icon:hover {
   opacity: 0.8;
 }