Skip to main content

Node Creation API Integration

The studio app has been updated to integrate with the central backend API for creating and persisting process nodes. This document explains the implementation and API structure.

Overview

When users add nodes to the canvas in the studio app (via sidebar, drag-and-drop, or hover actions), the frontend now automatically saves them to the backend database using the central API.

Backend API

Endpoint

POST /v1/api/process/{processId}/node

Request Structure

{
nodeType: string; // e.g., "MANUAL_TRIGGER", "HUMAN_TASK"
name: string; // Display name for the node
description?: string; // Optional description
position: { // Canvas position
x: number;
y: number;
};
configuration?: Record<string, any>; // Node-specific config
metadata?: Record<string, any>; // Additional metadata
}

Response Structure

{
statusCode: number; // 201 for success
status: string; // "Success"
message: string; // Success/error message
data: {
id: string; // Generated database ID
processId: string; // Process this node belongs to
nodeType: string; // Node type
name: string; // Node name
description?: string; // Description
position: { x: number; y: number };
configuration: Record<string, any>;
metadata: Record<string, any>;
createdAt: string; // ISO timestamp
updatedAt: string; // ISO timestamp
};
error: string | null; // Error message if any
}

Frontend Implementation

API Proxy

The studio app uses a Next.js API route as a proxy to forward requests to the central backend:

// apps/studio/app/api/process/[processId]/node/route.ts
export async function POST(req: NextRequest, context: RouteContext) {
const { params } = routeContextSchema.parse(context);
const body = await req.json();

const response = await forwardRequestToCentralApp(
`/v1/api/process/${params.processId}/node`,
{
method: 'POST',
body: JSON.stringify(body),
}
);

return NextResponse.json(await response.json());
}

Node Creation Methods

The frontend supports three ways to create nodes, all of which integrate with the backend:

1. Sidebar Node Addition

const handleSidebarNodeAdd = useCallback((nodeType: string, position: { x: number; y: number }) => {
const newNode = {
id: `${nodeType}-${Date.now()}`,
type: nodeType,
position,
data: {
label: nodeType.replace('_', ' '),
nodeType: nodeType
},
};

// Add to React Flow immediately for responsiveness
setNodes((nds) => nds.concat(newNode));

// Save to backend
const payload = {
nodeType: newNode.type,
name: newNode.data.label,
description: `A ${newNode.type.replace('_', ' ').toLowerCase()} node`,
position: newNode.position,
configuration: {},
metadata: { id: newNode.id },
};

fetch(`/api/process/${processId}/node`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(res => res.json())
.then(body => {
if (body.statusCode === 201 && !body.error) {
// Update with backend-generated ID
setNodes((nds) =>
nds.map((node) => {
if (node.id === newNode.id) {
return {
...node,
id: body.data.id,
position: body.data.position,
data: {
...node.data,
label: body.data.name,
},
};
}
return node;
})
);
}
});
}, []);

2. Drag-and-Drop Node Addition

Similar to sidebar addition but triggered by dropping elements from the palette.

3. Hover-based Node Addition

Allows users to add nodes by hovering over existing nodes and selecting connection points.

Key Features

Real-time Sync

  • Nodes are added to the canvas immediately for responsiveness
  • Backend IDs replace temporary frontend IDs after successful save
  • Position and properties are synced with the backend response

Error Handling

  • Network errors are handled gracefully with user notifications
  • Backend validation errors are displayed to the user
  • Failed saves don't break the frontend state

Validation

  • DTO validation on the backend ensures data integrity
  • NodeFactory validation ensures node types are supported
  • Frontend validates start node uniqueness

Data Storage

  • Configuration and metadata are stored in the database data JSON field
  • Proper field mapping between frontend and backend structures
  • Support for future extension of node properties

Node Types Supported

The following node types are currently supported:

  • MANUAL_TRIGGER - Manual workflow triggers
  • HUMAN_TASK - Tasks requiring human intervention
  • USER_TASK - User-assigned tasks
  • EXCLUSIVE_GATEWAY - Decision points in workflows

Database Schema

Nodes are stored in the ProcessNode table with the following structure:

  • id (UUID) - Primary key
  • processId (UUID) - Foreign key to Process
  • nodeId (String) - Unique node identifier
  • type (NodeType enum) - Node type
  • name (String) - Display name
  • description (Text) - Optional description
  • position (JSON) - Canvas coordinates
  • data (JSON) - Configuration and metadata
  • createdAt/updatedAt - Timestamps

Error Scenarios

Common error scenarios and their handling:

  1. Invalid Node Type: Backend validates against supported node types
  2. Missing Required Fields: DTO validation ensures all required fields are present
  3. Network Failure: Frontend shows error toast and maintains local state
  4. Authentication Issues: Proper error messages guide user to re-authenticate
  5. Process Not Found: Backend validates process existence before creating nodes

Process ID Handling

Dynamic Process ID Resolution

The studio app now dynamically extracts process IDs from URL parameters:

// In /process/[id] routes
const params = useParams();
const processId = extractProcessId(params); // Validates UUID format

// Process validation with error handling
const result = await validateProcessAccess(processId);
if (!result.valid) {
// Show appropriate error message to user
}

Process Validation

Before creating nodes, the frontend validates:

  1. URL Format: Ensures process ID is a valid UUID
  2. Process Existence: Verifies the process exists in the database
  3. Access Permissions: Confirms user has permission to view/edit the process
  4. Foreign Key Constraints: Prevents database errors when creating nodes

Error Handling

Common scenarios and responses:

  • Invalid UUID: Shows "Invalid process ID format" message
  • Process Not Found: Shows "Process not found" with navigation options
  • Access Denied: Shows "Permission denied" message
  • Network Error: Shows "Connection error" with retry options

Future Enhancements

Planned improvements include:

  • Real-time collaboration with WebSocket updates
  • Undo/redo functionality with operation history
  • Advanced node validation rules
  • Bulk node operations
  • Node templates and presets
  • Automatic process creation for new workflows
  • Process sharing and collaboration features