This page covers the user-facing flow management layer: the main flows listing page, the TemplatesModal for creating flows from starter projects, flow cards, folder/project organization, and the undo/redo history mechanism backed by flowsManagerStore.
For the visual canvas where a flow's nodes and edges are edited, see Visual Flow Builder. For Zustand state management across all stores, see State Management. For the modal foundation (BaseModal) used by TemplatesModal, see Modal System.
The flow management UI is the first screen a user encounters after logging in. It provides:
TemplatesModal) for bootstrapping new flows from starter projectsComponent tree for flow management UI:
Sources: src/frontend/src/modals/templatesModal/index.tsx src/frontend/src/modals/templatesModal/components/GetStartedComponent/index.tsx src/frontend/src/modals/templatesModal/components/TemplateContentComponent/index.tsx
TemplatesModal is the primary entry point for flow creation. It is opened when the user clicks New Flow on the main page.
| Property | Value |
|---|---|
BaseModal size | "templates" |
| Min-width | w-[97vw] max-w-[1200px] |
| Height | responsive: min-h-[500px] h-[90vh], capped at 620px on large screens |
| Padding | p-0 (layout fills the entire modal area) |
The size class mapping is defined in src/frontend/src/modals/baseModal/helpers/switch-case-size.ts58-62
The modal uses a SidebarProvider (from @/components/ui/sidebar) with fixed width 15rem and defaultOpen={false} for the nav panel. The main content area conditionally renders GetStartedComponent or TemplateContentComponent based on currentTab state.
Sources: src/frontend/src/modals/templatesModal/index.tsx81-136
The Nav component renders a sidebar of category groups with items. The structure is defined inline in TemplatesModal and passed as a categories prop:
| Group | Items (id) |
|---|---|
| Templates | get-started, all-templates |
| Use Cases | assistants, classification, coding, content-generation, q-a |
| Methodology | chatbots (Prompting), rag, agents |
Clicking a nav item calls setCurrentTab(link.id). The active item is highlighted via isActive={currentTab === link.id}. Each item also sets a data-testid of side_nav_options_<normalized-title> for E2E testing.
Sources: src/frontend/src/modals/templatesModal/index.tsx47-79 src/frontend/src/modals/templatesModal/components/navComponent/index.tsx
Shown when currentTab === "get-started". Renders three featured "get started" cards, one for each major use case: Prompting, RAG, and Agents.
The component reads examples from useFlowsManagerStore and uses Array.find to look up specific flows by name:
| Card | Target example.name | Icon |
|---|---|---|
| Memory Chatbot | "Basic Prompting" | MessagesSquare |
| Vector RAG | "Vector Store RAG" | Database |
| Multi-Agent | "Simple Agent" | Bot |
Each card renders TemplateGetStartedCardComponent, which on click:
updateIds(flow.data) to assign fresh node IDs (prevents ID collisions)addFlow({ flow }) (from useAddFlow hook)/flow/<id>/folder/<folderIdUrl>"New Flow Created" with { template: "<name> Template" }The ENABLE_KNOWLEDGE_BASES feature flag from @/customization/feature-flags gates whether examples containing "Knowledge" in their name are shown.
Sources: src/frontend/src/modals/templatesModal/components/GetStartedComponent/index.tsx src/frontend/src/modals/templatesModal/components/TemplateGetStartedCardComponent/index.tsx
Shown for all tabs except get-started. Provides a searchable, filterable grid of template cards.
Templates are filtered in two stages:
example.tags array includes currentTab, or keeps all if currentTab === "all-templates".["name", "description"] for fuzzy matching.Fuse is memoized via useMemo on examples, and results are re-computed in a useEffect when searchQuery or currentTab changes. The search input resets when the tab changes.
Sources: src/frontend/src/modals/templatesModal/components/TemplateContentComponent/index.tsx29-75
TemplateCategoryComponent renders filteredExamples in a responsive grid (grid-cols-1 lg:grid-cols-2) and delegates to TemplateCardComponent for each entry.
Sources: src/frontend/src/modals/templatesModal/components/TemplateCategoryComponent/index.tsx
Each template card shows:
swatchColors[swatchIndex], index computed via getNumberFromString(example.gradient ?? example.name))data-testid="template_<normalized-name>")Clicking a card delegates to the onClick handler passed from TemplateContentComponent, which calls addFlow({ flow: example }) and navigates to the new flow's URL.
Sources: src/frontend/src/modals/templatesModal/components/TemplateCardComponent/index.tsx
The TemplatesModal footer always shows a Blank Flow button. handleCreateBlankFlow in TemplatesModal calls addFlow() with no arguments, then navigates to /flow/<id> or /flow/<id>/folder/<folderId> if a folder context is active.
Sources: src/frontend/src/modals/templatesModal/index.tsx31-43
The undo/redo system is implemented in useFlowsManagerStore (src/frontend/src/stores/flowsManagerStore.ts). It stores history as module-level mutable objects (past and future), keyed by currentFlowId, so snapshots survive Zustand re-renders without triggering unnecessary store updates.
| Field | Type | Description |
|---|---|---|
flows | FlowType[] | undefined | All flows loaded for the current user |
currentFlow | FlowType | undefined | The actively displayed flow |
currentFlowId | string | ID of the active flow |
examples | FlowType[] | Starter/template flows from backend |
autoSaving | boolean | Whether debounced auto-save is enabled |
autoSavingInterval | number | Debounce delay in ms (default: SAVE_DEBOUNCE_TIME) |
searchFlowsComponents | string | Current search string for the flows listing |
selectedFlowsComponentsCards | string[] | IDs of multi-selected flow cards |
takeSnapshot() src/frontend/src/stores/flowsManagerStore.ts59-86:
flowStore.nodes and flowStore.edges via cloneDeepJSON.stringify)past[currentFlowId] to maxHistorySize - 1 (default: 99 entries) before appendingfuture[currentFlowId] on any new snapshotundo() src/frontend/src/stores/flowsManagerStore.ts87-104:
past[currentFlowId]future[currentFlowId]flowStore.setNodes(pastState.nodes) and flowStore.setEdges(pastState.edges)redo() src/frontend/src/stores/flowsManagerStore.ts106-124:
future[currentFlowId]past[currentFlowId]flowStoreThe maxHistorySize is hard-coded in defaultOptions:
const defaultOptions: UseUndoRedoOptions = {
maxHistorySize: 100,
enableShortcuts: true,
};
Sources: src/frontend/src/stores/flowsManagerStore.ts src/frontend/src/types/zustand/flowsManager/index.ts
Flows are organized into folders. The foldersStore (referenced in template components as useFolderStore) tracks the active folder via myCollectionId. The URL structure for a flow is:
/flow/<flowId>/folder/<folderId>
When TemplateContentComponent or TemplateGetStartedCardComponent navigates after creating a flow, it resolves the folder context:
flowsManagerStore provides getFlowById(id) for looking up flows by ID from the flows array, and setCurrentFlow(flow) which both updates currentFlow/currentFlowId in the manager store and calls useFlowStore.getState().resetFlow(flow) to reinitialize the canvas.
Sources: src/frontend/src/stores/flowsManagerStore.ts37-53 src/frontend/src/modals/templatesModal/components/TemplateContentComponent/index.tsx48-52
The following sequence summarizes the full path from user action to canvas open when creating from a template:
Sources: src/frontend/src/modals/templatesModal/components/TemplateContentComponent/index.tsx77-89 src/frontend/src/modals/templatesModal/components/TemplateGetStartedCardComponent/index.tsx33-51
flowsManagerStore.resetStore() resets the flows listing to a blank state (called on logout or workspace switch):
The searchFlowsComponents string and selectedFlowsComponentsCards string array support search and multi-select on the main flows listing page, allowing batch operations (e.g., bulk delete) across flow cards.
Sources: src/frontend/src/stores/flowsManagerStore.ts133-142 src/frontend/src/types/zustand/flowsManager/index.ts21-24
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.