React Workflow Builder: Triggers, Branches and AI Steps

You want your users to set up their own automations: when an invoice goes overdue, check the balance, have an AI draft a reminder, send it. The obvious start is React Flow, and an afternoon later you have boxes and lines on a canvas. Then the real work shows up. A React workflow builder needs a catalog of steps, a settings form per step, branches that cannot loop, undo, a way to show a run, and a layout someone can use on a phone. This tutorial builds that editor on React Flow with triggers, yes / no branches and AI steps, then builds a similar automation as a list-style rule builder for people who would rather not drag lines. The examples use Workflow Canvas and Rule Builder from Wingo UI, the library we build, so we are not neutral. The data model and the checks apply to any implementation.
What does a React workflow builder need on top of React Flow?
It needs seven layers of application code, because React Flow (@xyflow/react) only gives you the canvas: nodes, edges, handles, pan, zoom and a minimap. This is the list we worked from:
The value is plain JSON, { nodes, edges }, so you can save it, diff it and run it on the server with whatever engine you already have. The canvas never executes anything.
How do I install the workflow canvas?
Install it with the Wingo UI CLI, which copies the source into your project:
The CLI writes components/ui/workflow-canvas.tsx with its Wingo UI dependencies (button, textarea, drawer, alert dialog and others) and installs @xyflow/react, motion and lucide-react. The component imports the React Flow base CSS itself. It fills its parent, so give the parent a height. The settings form later in this post also uses a select, which is not one of those dependencies: run npx wingo-ui@latest add select too.
How do I define triggers, actions and AI steps?
Each step type is a WorkflowNodeDef with a kind: trigger, action, condition, ai, delay or end. The kind sets the icon tile and the rules (a trigger takes no incoming line, a condition gets two outputs). Keep the catalog at module scope so it keeps its identity between renders.
group becomes a heading in the add menu, and keywords let someone find the AI step by typing "llm". A condition gets Yes and No outputs unless you pass your own outputs, such as three tiers for a lead score.
How do I build a branch with yes and no outputs?
A branch is two edges from the same condition, each with a sourceHandle that names the output (yes or no). Steps can start at 0, 0, and layoutWorkflow places them in layers from the trigger, with the branches side by side in the order of the condition's outputs. The canvas would also lay out an all-zero graph once on mount, but calling layoutWorkflow yourself means the value you save already holds real positions.
Render it in a client component. AlertDialogProvider goes once near the root, because deleting a connected step asks for confirmation through it:
onValueChange fires once per committed change: a drop, a connection, an inserted step, an undo. A drag does not flood your state with positions, and a value that arrives mid-drag waits until the drop. The canvas also refuses bad connections while you drag: a line into a trigger, a line that would close a loop, or a second line from the same branch turns red and does not land.
$ npx wingo-ui@latest add workflow-canvasHover a line for its + button to insert a step in between, or drop a line on empty space to open the add menu there. Tidy rearranges the graph, and the move is one undo step.
How do I give each step its own settings?
Pass a renderInspector function: it returns the settings form for the selected step, which opens in a panel on the right. You get the step and an api with update (merges into the step's data), def (the step's catalog entry), fields (the default name, description and skip fields) and readOnly. Here the AI step gets a prompt and a tone, and the other steps keep the default fields:
update merges shallowly into data, so spread the old config or you lose the other settings. Typing in the prompt counts as one undo step per 500ms burst, so Ctrl+Z does not erase a paragraph one letter at a time. If your app already has a side panel, set inspector="none" and open your own from onSelectedIdChange.
How do I validate a workflow before saving?
Call validateWorkflow(value, nodeTypes): it returns the problems that stop an automation from running as { nodeId?, edgeId?, message } objects. It catches no trigger or more than one, a connection into a trigger, a loop, a condition branch that goes nowhere, an unknown step type and a connection to a missing step. The canvas already rings those steps in red. On save, select the first broken step so its settings open, and drop the run state before the graph leaves the browser:
Run the same checks on the server, because the client can be bypassed. One Next.js trap: workflow-canvas.tsx starts with "use client", so a route handler that imports validateWorkflow from it gets a client reference, and calling it throws "Attempted to call validateWorkflow() from the server". Copy the checks you need into a server-only module instead.
How do I show a run on the canvas?
Set running and write each step's data.status; the canvas draws the rest. onRun adds a Run button to the toolbar, running locks editing, and the status shows as a marker. The status type is the same one the AI agent tool call UI uses: pending, running, complete and error, plus canceled and awaiting-approval for an AI step that waits for a person to approve its output. The line into the running step flows, finished lines turn green, and the view follows the running step unless the person panned in the last 3 seconds. Your server runs the steps and streams their status:
A failed step shows its error in the inspector. AI steps fail in the most varied ways (a timeout, a refusal, a rate limit), so send the model's own error text so the person can tell them apart.
How do I wire save, settings and runs into one editor?
Hold the workflow, the selection and the run flag in the editor, and hand each helper what it needs. This replaces the first version of overdue-editor.tsx:
What is a simpler alternative to a node-based workflow editor?
A rule list is the simpler alternative: a When, If, Then stack of cards that reads like a sentence. Most automations are one trigger, a few conditions and a few actions, and a list says that more plainly than a graph. The Rule Builder adds a summary box that reads the whole rule back as one sentence.
multiple: false takes the AI step out of the action picker once the rule uses it. describeRule returns the same sentence as the summary box, which is handy for notification text and the automation list. The conditions are a lib/filters group, the same model the Filter Builder edits, so one evaluator can serve both. Apply saves an edit; Cancel or Escape throws the draft away, so onValueChange never sees an unapplied draft.
$ npx wingo-ui@latest add rule-builderCanvas or rule list: which one should I ship?
Ship the rule list when automations are linear and the canvas when they branch. Either way the React workflow builder UI only edits data, so the deciding questions are who builds the automations and how often one needs a second path.
The two do not share a value shape (RuleValue versus { nodes, edges }), so pick one per automation type instead of switching an existing automation between them.
How do I add an automations list, run history and logs?
Use the Automation Builder Page, a block with the rest of the screen a React automation builder needs around the editor. It has a list of automations with on and off switches and a bar of each one's last 14 runs, the Workflow Canvas as the editor, a cron picker for scheduled triggers, Run a test, and a History tab whose log uses the same viewer as our React log viewer guide. Without automations it shows its sample data, so pass your own list and wire the callbacks to your API:
Pass nodeTypes whenever your workflows use your own step catalog. Without it the block validates against its built-in CRM catalog, so every custom step counts as an unknown type: Save shows the problems instead of calling onSave, and switching the automation on is refused. The switch is optimistic: a rejected onToggle flips it back with a toast. A rejected onSave keeps the changes and shows a toast, which is why the handler throws on a failed response. A rejected onTest shows its message and opens the run's log. Inside an admin shell, use height="fill"; our Next.js admin dashboard tutorial shows that shell.
How do I make a workflow builder work on a phone?
Make every touch gesture mean one thing. On the canvas one finger pans and two fingers pinch. A step has to be tapped (selected) before it drags, so panning across a card never moves it. Long-press opens a step's menu, handles reach 44px out from the card, and the settings open in a sheet that stops at half height so the canvas stays visible above it. The Rule Builder opens every editor and picker as a bottom sheet below 768px, and only the grip drags, so the rest of a card scrolls the page. That grip pattern is the one from our dnd kit touch drag guide.
Keyboard users get the same reach: Tab moves through the toolbar, every step and every connection; arrows move the selected step; A adds a step after it; Delete removes it.
Should I build it myself or use a workflow builder SDK?
Build a React Flow workflow builder yourself if you want to own every layer and have the time; buy one when the editor is not your product. Facts as of October 2026, from each vendor's page:
If you want an xyflow example to study line by line, React Flow's own examples (opens in a new tab) are the best source. If your team already runs Temporal, the Workflow Builder SDK has the closer backend story.
What should I build next?
Install the canvas and wire onValueChange to your own save endpoint: npx wingo-ui@latest add workflow-canvas. More screens built this way live in the Build it category.
FAQ
Is React Flow free for building a workflow editor?
Yes. React Flow (@xyflow/react) is MIT licensed and free for commercial use. As of October 2026 its official Workflow Editor template is marked as a Pro example, and React Flow Pro starts at $169 per month on the Starter plan.
How do I add conditional branches in React Flow?
Give the condition node two source handles, such as yes and no, and store the handle id on each edge as sourceHandle. Your runner then follows only the edges whose sourceHandle matches the result of the condition.
How should I store a workflow built in React?
Store the graph as JSON: a nodes array with id, type, position and a data object for each step's settings, and an edges array with source, target and sourceHandle. Strip run state such as status and error before saving, and validate the graph again on the server.
Can I call validateWorkflow in a Next.js route handler?
Not from the component file. workflow-canvas.tsx starts with "use client", so on the server Next.js replaces its exports with client references and calling one throws. Keep your server checks in a server-only module.
Should I build a node canvas or a rule list for automations?
Use a rule list when most automations are one trigger, a few conditions and a few actions, because it reads as a sentence and works well on a phone. Use a canvas when people need branches that lead to different steps, waits and AI steps in the middle of a flow.
Are the Wingo UI workflow components free?
No. The Workflow Canvas, the Rule Builder and the Automation Builder Page are part of Wingo UI Pro, which costs $8 per month, $80 per year or $150 once as of October 2026. They install as source code with npx wingo-ui@latest add workflow-canvas, rule-builder or automation-builder-page.
- React Flow
- Workflow builder
- Automation
- AI agents
- Mobile UI


