A reusable React component for visualizing workflow pipelines. Built for Render demo projects with a dark brutalist design.
Install directly from GitHub:
pnpm add github:render-examples/workflow-visualizer
Or add to your package.json:
{
"dependencies": {
"workflow-visualizer": "github:render-examples/workflow-visualizer"
}
}- React 18+
- Framer Motion 11+
- Tailwind CSS (configured with dark theme colors)
"use client"; import { WorkflowVisualizer, WorkflowConfig } from "workflow-visualizer"; const myWorkflow: WorkflowConfig = { title: "My Workflow", subtitle: "How it works", nodes: [ { id: "trigger", label: "Cron Job", type: "trigger", description: "Runs daily at midnight", position: { x: 100, y: 50 }, }, { id: "task1", label: "processData", type: "task", description: "Processes incoming data", position: { x: 100, y: 180 }, }, ], edges: [ { id: "trigger-task1", from: "trigger", to: "task1", style: "solid" }, ], defaultTrigger: "trigger", triggerFlows: [ { triggerId: "trigger", nodes: ["trigger", "task1"], edges: ["trigger-task1"], animationSequence: [ { id: "step1", activeNodes: ["trigger"], activeEdges: [], duration: 1500, title: "Cron Fires", description: "The scheduled job triggers at midnight.", }, { id: "step2", activeNodes: ["trigger", "task1"], activeEdges: ["trigger-task1"], duration: 2000, title: "Processing", description: "Data is processed by the task.", }, ], }, ], }; export default function WorkflowPage() { return <WorkflowVisualizer config={myWorkflow} />; }
The top-level configuration object:
interface WorkflowConfig { title: string; // Page/section title subtitle: string; // Subtitle or description nodes: WorkflowNodeConfig[]; edges: WorkflowEdgeConfig[]; triggerFlows: TriggerFlow[]; defaultTrigger: string; // ID of trigger to show by default }
Nodes represent tasks, triggers, and orchestrators in your workflow:
type NodeType = "trigger" | "task" | "batch" | "orchestrator"; interface WorkflowNodeConfig { id: string; // Unique identifier (referenced by edges) label: string; // Display name shown on the node type: NodeType; // Determines visual styling description: string; // Shown in detail panel when clicked position: { x: number; y: number }; // Absolute canvas position details?: { label: string; value: string }[]; // Optional key-value pairs }
| Type | Purpose | Visual Style |
|---|---|---|
trigger |
Entry points (cron, API, UI) | Purple theme, clickable to switch flows |
orchestrator |
Coordinates other tasks | Green theme |
batch |
Runs multiple parallel instances | Red theme, stacked card effect |
task |
Single unit of work | Gray theme |
Edges connect nodes and show the flow direction:
interface WorkflowEdgeConfig { id: string; // Unique identifier from: string; // Source node ID to: string; // Target node ID label?: string; // Optional label (e.g., "step 1", "spawns") style?: "solid" | "dashed"; // Line style (default: solid) }
Each trigger can display a different subset of nodes and edges with its own animation sequence:
interface TriggerFlow { triggerId: string; // Must match a trigger node's ID nodes: string[]; // Node IDs visible when this trigger is selected edges: string[]; // Edge IDs visible when this trigger is selected animationSequence: AnimationStep[]; } interface AnimationStep { id: string; // Unique step identifier activeNodes: string[]; // Nodes to highlight in this step activeEdges: string[]; // Edges to animate in this step duration: number; // Milliseconds before auto-advancing title: string; // Step title shown above visualization description: string; // Step description }
Nodes use absolute pixel positioning on the canvas:
- Triggers: Top row, typically
y: 50 - Orchestrators: Second row, typically
y: 180 - Tasks: Third row, typically
y: 320 - Batch tasks: Fourth row, typically
y: 460
Horizontal spacing: ~200px between nodes for readability.
The canvas auto-sizes based on node positions (minimum 700x550).
y: 50 [Cron Job] [API Call] [Manual UI] <- triggers
|
y: 180 [dailyJob] <- orchestrator
/ | \
y: 320 [pingAll] [analyzeAll] [generateDigest] <- tasks
| |
y: 460 [pingLLM] [analyzeResponse] <- batch tasks
The component uses these Tailwind colors. Ensure your Tailwind config includes them:
// tailwind.config.js module.exports = { theme: { extend: { colors: { // These are the default dark theme colors used // No configuration needed if using standard Tailwind }, }, }, };
Key color values used:
- Background:
#0a0a0a,#111,#222 - Borders:
#333,#444 - Text:
#666,#888,#fff - Trigger:
#1a1a2e/#4a4a6a - Orchestrator:
#1a2e1a/#4a6a4a - Batch:
#2e1a1a/#6a4a4a
- Animated flow: Watch data flow through your pipeline with animated edges
- Interactive: Click triggers to switch between different flows
- Step-by-step: Play/pause, step forward/backward through the animation
- Detail panels: Click any node to see its details
- Auto-sizing canvas: Adapts to your node layout
- Dark brutalist design: Sharp corners, monospace fonts, minimal color
MIT