Flow Studio
Minimal Custom Renderer
The smallest possible custom node renderer extends BaseNode, implements renderBody(), and adds at least one CustomHandle. Here is the full minimum implementation.
Complete Minimal Example
// MyCustomNode.tsx
import { BaseNode, BaseNodeProps } from 'flow-studio-designer/Base/BaseNode';
import { CustomHandle } from 'flow-studio-designer/Handles/CustomHandle';
import { withNodeHooks } from 'flow-studio-designer/Base/withNodeHooks';
import { Position } from 'reactflow';
class MyCustomNodeClass extends BaseNode {
renderBody() {
const { data } = this.props;
return (
<>
{/* Target handle — data arrives here */}
<CustomHandle
type="target"
position={Position.Left}
id="main"
isRequired
/>
{/* Node visual */}
<div className="node-header" style={{ background: data.color }}>
<i className={data.icon} />
<span className="node-title">{data.label}</span>
</div>
<div className="node-body">
<span className="node-type-label">My Custom Node</span>
</div>
{/* Source handle — data flows out here */}
<CustomHandle
type="source"
position={Position.Right}
id="main"
isMain
/>
</>
);
}
}
// IMPORTANT: always export wrapped with withNodeHooks
export const MyCustomNode = withNodeHooks(MyCustomNodeClass);
Required CSS Classes
The node-wrapper class is applied by BaseNode.render(). Your renderBody() should use:
| Class | Purpose |
|---|---|
node-header | Coloured top bar with icon and title |
node-body | Content area below the header |
node-title | Title text in the header |
node-type-label | Small secondary label |
These classes are defined in the shared Flow Studio CSS included in the designer package.