diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index 527a86bf..07698886 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -16,6 +16,7 @@ jobs:
       product: opensearch-dashboards
 
   build-and-test-linux:
+    if: ${{ github.event.label.name != 'rapid' }}
     needs: Get-CI-Image-Tag
     name: Build & test
     strategy:
@@ -49,7 +50,8 @@ jobs:
 
   # TODO: once github actions supports windows and macos docker containers, we can
   # merge these in to the above step's matrix, including adding windows support
-  build-and-test-windows-macos:
+  build-and-test-macos:
+    if: ${{ github.event.label.name != 'rapid' }}
     name: Build & test
     strategy:
       matrix:
diff --git a/common/constants.ts b/common/constants.ts
index 0903f38c..77d1cf52 100644
--- a/common/constants.ts
+++ b/common/constants.ts
@@ -29,3 +29,10 @@ export const SEARCH_WORKFLOWS_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/se
 export const GET_WORKFLOW_STATE_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/state`;
 export const CREATE_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/create`;
 export const DELETE_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/delete`;
+
+/**
+ * MISCELLANEOUS
+ */
+export const NEW_WORKFLOW_ID_URL = 'new';
+export const START_FROM_SCRATCH_WORKFLOW_NAME = 'Start From Scratch';
+export const DEFAULT_NEW_WORKFLOW_NAME = 'new_workflow';
diff --git a/common/interfaces.ts b/common/interfaces.ts
index a493d650..a927f0e8 100644
--- a/common/interfaces.ts
+++ b/common/interfaces.ts
@@ -69,16 +69,20 @@ export type UseCaseTemplate = {
 };
 
 export type Workflow = {
-  id: string;
+  // won't exist until created in backend
+  id?: string;
   name: string;
   useCase: string;
+  template: UseCaseTemplate;
   description?: string;
   // ReactFlow state may not exist if a workflow is created via API/backend-only.
   workspaceFlowState?: WorkspaceFlowState;
-  template: UseCaseTemplate;
-  lastUpdated: number;
-  lastLaunched: number;
-  state: WORKFLOW_STATE;
+  // won't exist until created in backend
+  lastUpdated?: number;
+  // won't exist until launched/provisioned in backend
+  lastLaunched?: number;
+  // won't exist until launched/provisioned in backend
+  state?: WORKFLOW_STATE;
 };
 
 export enum USE_CASE {
diff --git a/public/pages/workflow_detail/components/header.tsx b/public/pages/workflow_detail/components/header.tsx
index 987baeb5..2b99e57e 100644
--- a/public/pages/workflow_detail/components/header.tsx
+++ b/public/pages/workflow_detail/components/header.tsx
@@ -5,13 +5,14 @@
 
 import React, { useContext } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
-import { EuiPageHeader, EuiButton } from '@elastic/eui';
-import { Workflow } from '../../../../common';
+import { EuiPageHeader, EuiButton, EuiLoadingSpinner } from '@elastic/eui';
+import { DEFAULT_NEW_WORKFLOW_NAME, Workflow } from '../../../../common';
 import { saveWorkflow } from '../utils';
 import { rfContext, AppState, removeDirty } from '../../../store';
 
 interface WorkflowDetailHeaderProps {
   tabs: any[];
+  isNewWorkflow: boolean;
   workflow?: Workflow;
 }
 
@@ -22,14 +23,24 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
 
   return (
     <EuiPageHeader
-      pageTitle={props.workflow ? props.workflow.name : ''}
+      pageTitle={
+        props.workflow ? (
+          props.workflow.name
+        ) : props.isNewWorkflow && !props.workflow ? (
+          DEFAULT_NEW_WORKFLOW_NAME
+        ) : (
+          <EuiLoadingSpinner size="xl" />
+        )
+      }
       rightSideItems={[
+        // TODO: add launch logic
         <EuiButton fill={false} onClick={() => {}}>
-          Prototype
+          Launch
         </EuiButton>,
         <EuiButton
           fill={false}
           disabled={!props.workflow || !isDirty}
+          // TODO: if isNewWorkflow is true, clear the workflow cache if saving is successful.
           onClick={() => {
             // @ts-ignore
             saveWorkflow(props.workflow, reactFlowInstance);
diff --git a/public/pages/workflow_detail/workflow_detail.tsx b/public/pages/workflow_detail/workflow_detail.tsx
index e57bcc83..53f23372 100644
--- a/public/pages/workflow_detail/workflow_detail.tsx
+++ b/public/pages/workflow_detail/workflow_detail.tsx
@@ -5,17 +5,21 @@
 
 import React, { useEffect, useState } from 'react';
 import { RouteComponentProps, useLocation } from 'react-router-dom';
-import { useSelector } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
 import { ReactFlowProvider } from 'reactflow';
 import queryString from 'query-string';
 import { EuiPage, EuiPageBody } from '@elastic/eui';
 import { BREADCRUMBS } from '../../utils';
 import { getCore } from '../../services';
 import { WorkflowDetailHeader } from './components';
-import { AppState } from '../../store';
+import { AppState, searchWorkflows } from '../../store';
 import { ResizableWorkspace } from './workspace';
 import { Launches } from './launches';
 import { Prototype } from './prototype';
+import {
+  DEFAULT_NEW_WORKFLOW_NAME,
+  NEW_WORKFLOW_ID_URL,
+} from '../../../common';
 
 export interface WorkflowDetailRouterProps {
   workflowId: string;
@@ -45,13 +49,27 @@ function replaceActiveTab(activeTab: string, props: WorkflowDetailProps) {
  * The workflow details page. This is where users will configure, create, and
  * test their created workflows. Additionally, can be used to load existing workflows
  * to view details and/or make changes to them.
+ * New, unsaved workflows are cached in the redux store and displayed here.
  */
+
 export function WorkflowDetail(props: WorkflowDetailProps) {
-  const { workflows } = useSelector((state: AppState) => state.workflows);
+  const dispatch = useDispatch();
+  const { workflows, cachedWorkflow } = useSelector(
+    (state: AppState) => state.workflows
+  );
+  const { isDirty } = useSelector((state: AppState) => state.workspace);
 
-  const workflow = workflows[props.match?.params?.workflowId];
-  const workflowName = workflow ? workflow.name : '';
+  // selected workflow state
+  const workflowId = props.match?.params?.workflowId;
+  const isNewWorkflow = workflowId === NEW_WORKFLOW_ID_URL;
+  const workflow = isNewWorkflow ? cachedWorkflow : workflows[workflowId];
+  const workflowName = workflow
+    ? workflow.name
+    : isNewWorkflow && !workflow
+    ? DEFAULT_NEW_WORKFLOW_NAME
+    : '';
 
+  // tab state
   const tabFromUrl = queryString.parse(useLocation().search)[
     ACTIVE_TAB_PARAM
   ] as WORKFLOW_DETAILS_TAB;
@@ -78,6 +96,19 @@ export function WorkflowDetail(props: WorkflowDetailProps) {
     ]);
   });
 
+  // On initial load:
+  // - fetch workflow, if there is an existing workflow ID
+  // - add a window listener to warn users if they exit/refresh
+  //   without saving latest changes
+  useEffect(() => {
+    if (!isNewWorkflow) {
+      // TODO: can optimize to only fetch a single workflow
+      dispatch(searchWorkflows({ query: { match_all: {} } }));
+    }
+    window.onbeforeunload = (e) =>
+      isDirty || isNewWorkflow ? true : undefined;
+  }, []);
+
   const tabs = [
     {
       id: WORKFLOW_DETAILS_TAB.EDITOR,
@@ -112,7 +143,11 @@ export function WorkflowDetail(props: WorkflowDetailProps) {
     <ReactFlowProvider>
       <EuiPage>
         <EuiPageBody>
-          <WorkflowDetailHeader workflow={workflow} tabs={tabs} />
+          <WorkflowDetailHeader
+            workflow={workflow}
+            isNewWorkflow={isNewWorkflow}
+            tabs={tabs}
+          />
           {selectedTabId === WORKFLOW_DETAILS_TAB.EDITOR && (
             <ResizableWorkspace workflow={workflow} />
           )}
diff --git a/public/pages/workflows/new_workflow/new_workflow.tsx b/public/pages/workflows/new_workflow/new_workflow.tsx
index ce87c443..c255fd50 100644
--- a/public/pages/workflows/new_workflow/new_workflow.tsx
+++ b/public/pages/workflows/new_workflow/new_workflow.tsx
@@ -3,10 +3,23 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import React from 'react';
-import { EuiFlexItem, EuiFlexGrid } from '@elastic/eui';
-
+import React, { useState, useEffect } from 'react';
+import { debounce } from 'lodash';
+import {
+  EuiFlexItem,
+  EuiFlexGrid,
+  EuiFlexGroup,
+  EuiFieldSearch,
+} from '@elastic/eui';
+import { useDispatch } from 'react-redux';
 import { UseCase } from './use_case';
+import { getPresetWorkflows } from './presets';
+import {
+  DEFAULT_NEW_WORKFLOW_NAME,
+  START_FROM_SCRATCH_WORKFLOW_NAME,
+  Workflow,
+} from '../../../../common';
+import { cacheWorkflow } from '../../../store';
 
 interface NewWorkflowProps {}
 
@@ -18,26 +31,84 @@ interface NewWorkflowProps {}
  * workflow for users to start with.
  */
 export function NewWorkflow(props: NewWorkflowProps) {
+  const dispatch = useDispatch();
+  // preset workflow state
+  const presetWorkflows = getPresetWorkflows();
+  const [filteredWorkflows, setFilteredWorkflows] = useState<Workflow[]>(
+    getPresetWorkflows()
+  );
+
+  // search bar state
+  const [searchQuery, setSearchQuery] = useState<string>('');
+  const debounceSearchQuery = debounce((query: string) => {
+    setSearchQuery(query);
+  }, 200);
+
+  // When search query updated, re-filter preset list
+  useEffect(() => {
+    setFilteredWorkflows(fetchFilteredWorkflows(presetWorkflows, searchQuery));
+  }, [searchQuery]);
+
   return (
-    <EuiFlexGrid columns={3} gutterSize="l">
-      <EuiFlexItem>
-        <UseCase
-          title="Semantic Search"
-          description="Semantic search description..."
-        />
-      </EuiFlexItem>
-      <EuiFlexItem>
-        <UseCase
-          title="Multi-modal Search"
-          description="Multi-modal search description..."
+    <EuiFlexGroup direction="column">
+      <EuiFlexItem grow={true}>
+        <EuiFieldSearch
+          fullWidth={true}
+          placeholder="Search"
+          onChange={(e) => debounceSearchQuery(e.target.value)}
         />
       </EuiFlexItem>
       <EuiFlexItem>
-        <UseCase
-          title="Search Summarization"
-          description="Search summarization description..."
-        />
+        <EuiFlexGrid columns={3} gutterSize="l">
+          {filteredWorkflows.map((workflow: Workflow, index) => {
+            return (
+              <EuiFlexItem key={index}>
+                <UseCase
+                  title={workflow.name}
+                  description={workflow.description || ''}
+                  onClick={() =>
+                    dispatch(
+                      cacheWorkflow({
+                        ...workflow,
+                        name: processWorkflowName(workflow.name),
+                      })
+                    )
+                  }
+                />
+              </EuiFlexItem>
+            );
+          })}
+        </EuiFlexGrid>
       </EuiFlexItem>
-    </EuiFlexGrid>
+    </EuiFlexGroup>
   );
 }
+
+// Collect the final preset workflow list after applying all filters
+function fetchFilteredWorkflows(
+  allWorkflows: Workflow[],
+  searchQuery: string
+): Workflow[] {
+  return searchQuery.length === 0
+    ? allWorkflows
+    : allWorkflows.filter((workflow) =>
+        workflow.name.toLowerCase().includes(searchQuery.toLowerCase())
+      );
+}
+
+// Utility fn to process workflow names from their presentable/readable titles
+// on the UI, to a valid name format.
+// This leads to less friction if users decide to save the name later on.
+function processWorkflowName(workflowName: string): string {
+  return workflowName === START_FROM_SCRATCH_WORKFLOW_NAME
+    ? DEFAULT_NEW_WORKFLOW_NAME
+    : toSnakeCase(workflowName);
+}
+
+function toSnakeCase(text: string): string {
+  return text
+    .replace(/\W+/g, ' ')
+    .split(/ |\B(?=[A-Z])/)
+    .map((word) => word.toLowerCase())
+    .join('_');
+}
diff --git a/public/pages/workflows/new_workflow/presets.tsx b/public/pages/workflows/new_workflow/presets.tsx
new file mode 100644
index 00000000..0cf7d382
--- /dev/null
+++ b/public/pages/workflows/new_workflow/presets.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import {
+  START_FROM_SCRATCH_WORKFLOW_NAME,
+  Workflow,
+  WorkspaceFlowState,
+} from '../../../../common';
+
+// TODO: fetch from the backend when the workflow library is complete.
+/**
+ * Used to fetch the library of preset workflows to provide to users.
+ */
+export function getPresetWorkflows(): Workflow[] {
+  return [
+    {
+      name: 'Semantic Search',
+      description:
+        'This semantic search workflow includes the essential ingestion and search pipelines that covers the most common search use cases.',
+      useCase: 'SEMANTIC_SEARCH',
+      template: {},
+      workspaceFlowState: {
+        nodes: [],
+        edges: [],
+      } as WorkspaceFlowState,
+    },
+    {
+      name: 'Semantic Search with Reranking',
+      description:
+        'This semantic search workflow variation includes an ML processor to rerank fetched results.',
+      useCase: 'SEMANTIC_SEARCH_WITH_RERANK',
+      template: {},
+      workspaceFlowState: {
+        nodes: [],
+        edges: [],
+      } as WorkspaceFlowState,
+    },
+    {
+      name: START_FROM_SCRATCH_WORKFLOW_NAME,
+      description:
+        'Build your workflow from scratch according to your specific use cases. Start by adding components for your ingest or query needs.',
+      useCase: '',
+      template: {},
+      workspaceFlowState: {
+        nodes: [],
+        edges: [],
+      } as WorkspaceFlowState,
+    },
+    {
+      name: 'Visual Search',
+      description:
+        'Build an application that will return results based on images.',
+      useCase: 'SEMANTIC_SEARCH',
+      template: {},
+      workspaceFlowState: {
+        nodes: [],
+        edges: [],
+      } as WorkspaceFlowState,
+    },
+  ] as Workflow[];
+}
diff --git a/public/pages/workflows/new_workflow/use_case.tsx b/public/pages/workflows/new_workflow/use_case.tsx
index c7094c9a..111c4f7c 100644
--- a/public/pages/workflows/new_workflow/use_case.tsx
+++ b/public/pages/workflows/new_workflow/use_case.tsx
@@ -13,9 +13,12 @@ import {
   EuiHorizontalRule,
   EuiButton,
 } from '@elastic/eui';
+import { NEW_WORKFLOW_ID_URL, PLUGIN_ID } from '../../../../common';
+
 interface UseCaseProps {
   title: string;
   description: string;
+  onClick: () => {};
 }
 
 export function UseCase(props: UseCaseProps) {
@@ -28,6 +31,7 @@ export function UseCase(props: UseCaseProps) {
       }
       titleSize="s"
       paddingSize="l"
+      layout="horizontal"
     >
       <EuiFlexGroup direction="column" gutterSize="l">
         <EuiHorizontalRule size="full" margin="m" />
@@ -39,9 +43,8 @@ export function UseCase(props: UseCaseProps) {
             <EuiButton
               disabled={false}
               isLoading={false}
-              onClick={() => {
-                // TODO: possibly link to the workflow details with a pre-configured flow
-              }}
+              onClick={props.onClick}
+              href={`${PLUGIN_ID}#/workflows/${NEW_WORKFLOW_ID_URL}`}
             >
               Go
             </EuiButton>
diff --git a/public/pages/workflows/workflow_list/workflow_list.tsx b/public/pages/workflows/workflow_list/workflow_list.tsx
index 3e5b4484..f122a2e0 100644
--- a/public/pages/workflows/workflow_list/workflow_list.tsx
+++ b/public/pages/workflows/workflow_list/workflow_list.tsx
@@ -109,7 +109,7 @@ export function WorkflowList(props: WorkflowListProps) {
             <EuiFlexItem grow={true}>
               <EuiFieldSearch
                 fullWidth={true}
-                placeholder="Search workflows..."
+                placeholder="Search"
                 onChange={(e) => debounceSearchQuery(e.target.value)}
               />
             </EuiFlexItem>
diff --git a/public/store/reducers/workflows_reducer.ts b/public/store/reducers/workflows_reducer.ts
index 93f22e89..d06eac97 100644
--- a/public/store/reducers/workflows_reducer.ts
+++ b/public/store/reducers/workflows_reducer.ts
@@ -78,6 +78,7 @@ const initialState = {
   loading: false,
   errorMessage: '',
   workflows: {} as WorkflowDict,
+  cachedWorkflow: undefined as Workflow | undefined,
 };
 
 const WORKFLOWS_ACTION_PREFIX = 'workflows';
@@ -86,6 +87,8 @@ const SEARCH_WORKFLOWS_ACTION = `${WORKFLOWS_ACTION_PREFIX}/searchWorkflows`;
 const GET_WORKFLOW_STATE_ACTION = `${WORKFLOWS_ACTION_PREFIX}/getWorkflowState`;
 const CREATE_WORKFLOW_ACTION = `${WORKFLOWS_ACTION_PREFIX}/createWorkflow`;
 const DELETE_WORKFLOW_ACTION = `${WORKFLOWS_ACTION_PREFIX}/deleteWorkflow`;
+const CACHE_WORKFLOW_ACTION = `${WORKFLOWS_ACTION_PREFIX}/cacheWorkflow`;
+const CLEAR_CACHED_WORKFLOW_ACTION = `${WORKFLOWS_ACTION_PREFIX}/clearCachedWorkflow`;
 
 export const getWorkflow = createAsyncThunk(
   GET_WORKFLOW_ACTION,
@@ -167,6 +170,20 @@ export const deleteWorkflow = createAsyncThunk(
   }
 );
 
+export const cacheWorkflow = createAsyncThunk(
+  CACHE_WORKFLOW_ACTION,
+  async (workflow: Workflow) => {
+    return workflow;
+  }
+);
+
+// A no-op function to trigger a reducer case.
+// Will clear any stored workflow in the cachedWorkflow state
+export const clearCachedWorkflow = createAsyncThunk(
+  CLEAR_CACHED_WORKFLOW_ACTION,
+  async () => {}
+);
+
 const workflowsSlice = createSlice({
   name: 'workflows',
   initialState,
@@ -238,6 +255,13 @@ const workflowsSlice = createSlice({
         state.loading = false;
         state.errorMessage = '';
       })
+      .addCase(cacheWorkflow.fulfilled, (state, action) => {
+        const workflow = action.payload;
+        state.cachedWorkflow = workflow;
+      })
+      .addCase(clearCachedWorkflow.fulfilled, (state, action) => {
+        state.cachedWorkflow = undefined;
+      })
       // Rejected states: set state consistently across all actions
       .addCase(getWorkflow.rejected, (state, action) => {
         state.errorMessage = action.payload as string;