Har ek file ka role, flow mein kahan aata hai, aur kuch miss na ho β step-by-step.
- Kya karta hai: Saari pages ke around wrapper. ClerkProvider se auth context provide karta hai. Fonts (Inter, DM Sans, DM Mono) load. Dark theme by default (
className="dark"). - Flow: Har request pe yeh layout run hota hai β
children= current page (e.g./ya/dashboard).
- Kya karta hai: Clerk ka middleware. Har request pe check: agar route public nahi hai to user signed in hai ya nahi.
- Public routes:
/,/sign-in(.*),/sign-up(.*),/api/upload/params,/api/webhooks(.*),/api/process(.*). - Protected: Baaki sab. Agar
userIdnahi βredirectToSignIn(). - Flow: Request aate hi middleware chalta hai β public ho to aage; protected ho to auth check β fail = redirect sign-in.
- Kya karta hai: Home page. Server component.
auth()seuserIdnikalta hai. Agar userId hai βredirect("/dashboard"). Agar nahi β LandingHeader + LandingHero dikhata hai. - Flow: User
/pe aata hai β logged in hai to dashboard, nahi to landing.
- Kya karta hai: Clerk ke sign-in/sign-up routes. User yahan se login/signup karta hai.
- Flow: Middleware redirect yahan bhej sakta hai; login ke baad user dashboard/workflows pe jaata hai.
- Kya karta hai: Protected layout.
auth()seuserIdcheck. Agar nahi hai βredirect('/sign-in'). Agar hai βchildrenrender (dashboard ya workflow page). - Flow:
/dashboard,/workflows/...sab is layout ke andar; pehle auth, phir content.
- Kya karta hai: Client component. User ka workspace: workflow list, create new, sample load, search, grid/list view, context menu (open, duplicate, rename, delete).
- Important:
- useEffect:
fetchWorkflows()βGET /api/workflowsβ listworkflowsstate mein. - handleCreateNew:
POST /api/workflowswith{ name: 'untitled', nodes: [], edges: [] }β response seworkflow.idβrouter.push(\/workflows/${id}`)`. - handleLoadSample: Same POST with
PRODUCT_MARKETING_KITnodes/edges β then push to that workflow. - handleOpen:
router.push(\/workflows/${workflowId}`)`. - Rename:
PATCH /api/workflows/:idwith{ name }. Delete:DELETE /api/workflows/:id. Duplicate:POST /api/workflows/:id/duplicate.
- useEffect:
- Flow: Dashboard load β API se workflows β user create/open/rename/delete/duplicate β navigation to
/workflows/:id.
- Kya karta hai: Workflow editor page. Client component.
params.id= workflow id (yaundefinedfor/workflows).searchParams.template= optional template. - Store use:
useWorkflowStorese nodes, edges, workflowName, setWorkflow, loadWorkflow, saveWorkflow, setNodeStatus, updateNodeData. - Load:
useEffect: agarworkflowId && workflowId !== 'new'βloadWorkflow(workflowId)(store seGET /api/workflows/:idkarke nodes/edges set). - Save:
handleSaveβsaveWorkflow(). Auto-save: 2 sec debounce on nodes/edges/workflowName change. - Run:
handleRun(scope)yahan define hai β nodes to run kosetNodeStatus(..., 'running')βPOST /api/workflows/executewith workflowId, nodes, edges, scope, nodeIds β responseresultspe loop βsetNodeStatus+updateNodeData(output/response/error). - Layout: IconSidebar (left) β NodeSidebar (slide-out) β WorkflowHeader (name, save, share, tasks, import/export) + WorkflowCanvas β PropertiesSidebar (right). onRun =
handleRunβ WorkflowHeader ko pass nahi hota (header mein run button nahi), lekin WorkflowCanvas ke andar FloatingToolbar ko run milta hai (next file). - Flow: URL
/workflows/xyzβ load workflow β canvas + sidebars render β user edit/save/run from canvas toolbar.
- Structure: WorkflowCanvas =
ReactFlowProviderβ WorkflowCanvasInner (actual canvas). - Store: nodes, edges, onNodesChange, onEdgesChange, onConnect, addNode, deleteNode, setSelectedNodeIds, selectedNodeIds, selectedEdgeId, deleteEdge, undo, redo, updateNodeData. Tool:
useCanvasToolStoreβ activeTool (select / pan). - handleRun(scope):
setIsExecuting(true).- Scope ke hisaab se nodesToRun. Sab pe
updateNodeData(id, { status: 'running' }). POST /api/workflows/executewith workflowId, nodes, edges, scope, nodeIds.- Response
resultsβ har node peupdateNodeData(nodeId, { status, output, error }). - Error pe nodesToRun ko
status: 'error'. finallyβsetIsExecuting(false).
- Connections:
- handleConnect: source/target + handles pe
validateConnection(validation.ts) β valid ho to onConnect(connection) (store addEdge + history). - isValidConnectionCallback: drag ke time visual feedback ke liye same validation.
- handleConnect: source/target + handles pe
- onConnectEnd: Agar connection invalid (e.g. empty pane pe drop) β ContextConnectionMenu dikhata hai; user node type choose kare β handleContextSelect β
addNode(type, flow)+onConnectsource β new node (target handle type ke hisaab se). - Drag from sidebar: onDragOver allow, onDrop β
event.dataTransfer.getData('application/reactflow')= node type βscreenToFlowPositionβ addNode(type, position). - Keyboard: Delete/Backspace β selected edge delete ya selected nodes delete. Ctrl/Cmd+R β handleRun('full'). Ctrl+Z / Ctrl+Shift+Z β undo/redo.
- ReactFlow props: nodes, edges, onNodesChange, onEdgesChange, onConnect, nodeTypes, edgeTypes, connectionLineComponent, fitView, snapToGrid, Background, MiniMap, FloatingToolbar (Panel bottom-center) with onRun={handleRun}, isExecuting.
- Flow: Canvas = single source of truth (store). Run = FloatingToolbar se handleRun β execute API. Add node = sidebar drag ya connection menu. Connections = validation se allow/block.
- Kya karta hai: Bottom-center toolbar: Select / Pan tool, Undo / Redo, Run dropdown, node count, zoom.
- Run: Button click β dropdown: "Run Full Workflow (βR)", "Run Selected Nodes". handleRun(scope) =
onRun(scope)(parent se = WorkflowCanvas ka handleRun). Disabled whenisExecuting || nodes.length === 0. "Run Selected" disabled whenselectedNodeIds.length === 0. - Flow: User "Run" β full ya selected β parent handleRun β same execute API call.
- Kya karta hai: Top bar: workflow name input, HistorySidebar (Tasks), Save, Share, Export/Import JSON. onRun prop hai but header mein run button nahi dikh raha (run canvas toolbar se hi hai).
- Save:
onSave()(page se = saveWorkflow). Export: workflow name, nodes, edges β JSON download. Import: file pick β setNodes, setEdges, setWorkflowName.
- Kya karta hai: Left slide-out: workflow name edit, search, TOOLBOX_NODES (LLM, Text, Image Upload, Video Upload, Crop Image, Extract Frame). Har type ke liye NodeCard β onDragStart mein
event.dataTransfer.setData('application/reactflow', type). - Flow: User node type drag karke canvas pe drop β WorkflowCanvas onDrop β addNode(type, position).
- Kya karta hai: Left icon bar: sections (e.g. nodes) click β NodeSidebar open/close (activeSection).
- Kya karta hai: Right sidebar: selected node/edge ki properties. Run selected button β
handleRunSelectedβ directPOST /api/workflows/executewith scope PARTIAL and selected node ids (store se). Same flow: run β results β node status update.
- Kya karta hai: Tasks panel.
workflowIdpe GET /api/workflows/:id/runs (polling bhi) β runs list. Har run expand β nodeResults dikhate hain (nodeId, status, duration, etc.).
- Kya karta hai: Zustand store (persist + devtools + immer). State: workflowId, workflowName, nodes, edges, selectedNodeIds, selectedEdgeId, isExecuting, executingNodeIds, history (undo/redo), historyIndex.
- Actions:
- setWorkflow(id, name, nodes, edges) β load/set full workflow.
- addNode(type, position, initialData) β NODE_CONFIG se default data + newNode push; saveToHistory.
- updateNodeData(nodeId, data) β node.data merge.
- deleteNode(nodeId) β node + uske edges remove; saveToHistory.
- onNodesChange / onEdgesChange β React Flow changes apply.
- onConnect(connection) β edge add (with color from connector-colors); saveToHistory.
- deleteEdge(edgeId).
- setNodeStatus(nodeId, status, output?, error?) β node.data.status/output/error.
- saveToHistory β current nodes/edges history stack mein (max 50). undo/redo β historyIndex se restore.
- createNewWorkflow β POST /api/workflows β set new id, empty nodes/edges.
- saveWorkflow β workflowId nahi to POST, else PATCH /api/workflows/:id.
- loadWorkflow(id) β GET /api/workflows/:id β setWorkflow.
- duplicateWorkflow β POST create ya POST .../duplicate.
- Persist: workflowId, workflowName, nodes, edges β localStorage (key: weavy-workflow-store).
- Flow: Canvas + header + sidebars sab is store ko read/update karte hain; run ke time nodes/edges yahi se API ko bheje jaate hain.
- Kya karta hai: UI state (e.g. isHistoryOpen, toggleHistory) β Tasks panel open/close.
- Kya karta hai: activeTool = 'select' | 'pan'. setActiveTool. Canvas interaction (draggable, connectable, etc.) isi se derive.
- Kya karta hai: NodeType union, HandleType, NODE_CONFIG (har type ke liye label, color, icon, inputs [], outputs []). Data interfaces: TextNodeData, UploadImageNodeData, LLMNodeData, CropImageNodeData, ExtractFrameNodeData, etc.
- Flow: Validation and store addNode is config use karte hain (defaults + handle ids).
- isValidConnection(sourceNode, sourceHandle, targetNode, targetHandle, edges):
- Self-connect block.
- NODE_CONFIG se source output / target input handle.
- Type compatibility (text/image/video/any).
- Target handle pe pehle se connection (except LLM 'images').
- wouldCreateCycle β BFS from target to source; agar source reach ho to cycle = invalid.
- Return { valid, reason? }.
- topologicalSort(nodes, edges): Kahn's algorithm. In-degree compute β layers of node ids (layer 0 = no incoming; next layers = jinke sab predecessors previous layers mein). Return
string[][](har layer parallel run ho sakta hai). - getConnectedInputs(nodeId, nodes, edges): Incoming edges se source node ka
data.outputβ map by targetHandle. 'images' handle multiple values array mein. - getUpstreamNodes / getDownstreamNodes: BFS from nodeId backward/forward on edges.
- isValidDAG: topologicalSort ke baad saare nodes kisi layer mein hon (no cycle).
- Flow: Canvas connection allow/deny + execute route ko layers aur inputs dene ke liye use.
- Kya karta hai: PrismaClient singleton (dev mein globalThis pe cache). Saari API routes
import prisma from '@/lib/db'use karti hain.
- GET: auth β get/create User by clerkId (currentUser se email, name). prisma.workflow.findMany({ where: { userId } }) β list (id, name, description, dates, _count.runs). Return { workflows }.
- POST: auth β body validate (createWorkflowSchema: name, optional description, nodes, edges). Get/create user. prisma.workflow.create β return { workflow }.
- Flow: Dashboard list + create new workflow.
- GET: auth β user by clerkId. prisma.workflow.findFirst({ where: { id, userId } }) β return workflow (nodes, edges included).
- PATCH/PUT: auth β body (name?, nodes?, edges?) validate β ownership check β prisma.workflow.update.
- DELETE: auth β ownership β prisma.workflow.delete.
- Flow: Load one workflow, save (update), delete.
- POST: auth β get workflow (ownership) β create new workflow with same name (Copy), nodes, edges, new id β return { workflow }. Flow: Dashboard/sidebar duplicate.
- GET: auth β user β prisma.workflowRun.findMany({ where: { workflowId, userId }, orderBy, take: 50, include: { nodeResults } }). Flow: HistorySidebar runs list.
- POST only. Body: workflowId, nodes, edges, scope ('FULL'|'PARTIAL'|'SINGLE'), nodeIds? (for PARTIAL/SINGLE).
- Auth: Clerk userId β prisma user. Fail β 401/404.
- Scope:
- FULL β nodesToExecute = nodes.
- PARTIAL/SINGLE + nodeIds β nodeIds + (SINGLE pe BFS backward on edges se saare upstream bhi) β nodesToExecute = filter nodes by this set.
- DB: prisma.workflowRun.create (workflowId, userId, scope, status: RUNNING).
- Layers: topologicalSort(nodesToExecute, edges) β executionLayers (array of layers).
- nodeOutputs: Map. Pehle existing node.data.output se initialize.
- Loop: Har layer ke liye:
- Har nodeId in layer ke liye async function: find node β NodeResult create (RUNNING).
- Inputs: getConnectedInputs(nodeId, nodes, edges) + edges se nodeOutputs se overwrite (runtime outputs).
- Switch node.type:
- text: output = data.text.
- uploadImage: output = data.imageUrl (blob check β error).
- uploadVideo: output = data.output ?? data.videoUrl (blob check).
- llm: SKIP_TRIGGER_DEV ? executeLLM() : executeLLMViaTrigger() β poll.
- cropImage: same pattern β executeCropImage vs executeCropImageViaTrigger.
- extractFrame: same β executeExtractFrame vs executeExtractFrameViaTrigger.
- nodeOutputs.set(nodeId, output). NodeResult update (SUCCESS/FAILED, input, output, duration). results[] push.
- End: Run status (SUCCESS/PARTIAL/FAILED) + completedAt, duration β prisma.workflowRun.update. Return { runId, status, results, duration }.
- Trigger.dev: executeLLMViaTrigger etc. β tasks.trigger('llm-execution', payload) then runs.poll(handle.id) with timeout. Fail/Timeout β fallback direct executeLLM/executeCropImage/executeExtractFrame.
- Direct execution: executeLLM β Groq (model groq:...) ya Gemini; executeCropImage/executeExtractFrame β POST /api/process (Transloadit) with fileUrl + options.
- Flow: Client POST with nodes/edges/scope β auth β layers β layer-by-layer run β DB run + node results β response β client node status/output update.
- POST: body { type?: 'image' | 'video' }. Transloadit params (auth key, expiry 1hr, steps). Image:
:original+optimized(image/optimize). Video::original. Signature = HMAC SHA-384 with TRANSLOADIT_AUTH_SECRET. Return { params, signature, authKey }. - Flow: UploadImageNode/UploadVideoNode pehle yahan se signed params leta hai, phir client direct Transloadit assemblies ko POST karta hai (file + params + signature).
- POST: body: type ('crop' | 'frame'), fileUrl, options (crop: x,y,width,height; frame: timestamp). Transloadit assembly create: /http/import (url=fileUrl) β crop: /image/resize (crop, result:true) ya frame: /video/thumbs (offsets, result:true). Signature, POST to Transloadit, pollForCompletion β result URL. Return { success, resultUrl, assemblyId }.
- Flow: Execute route jab SKIP_TRIGGER_DEV ya fallback use kare to crop/frame ke liye yahi route call hota hai (server-side Transloadit).
- nodeTypes object: text β TextNode, uploadImage β UploadImageNode, uploadVideo β UploadVideoNode, llm β LLMNode, cropImage β CropImageNode, extractFrame β ExtractFrameNode. React Flow isi ko nodeTypes prop mein use karta hai.
- Upload flow: User file drop β POST /api/upload/params { type: 'image'|'video' } β params + signature. FormData: params, signature, file β POST https://api2.transloadit.com/assemblies β poll assembly_ssl_url until ASSEMBLY_COMPLETED β result URL (optimized[0].ssl_url ya uploads). updateNodeData(id, { imageUrl } or { videoUrl/output }).
- Execution time: Execute route node.data.imageUrl / videoUrl read karta hai (upload pehle ho chuka hota hai).
- Inputs: system_prompt, user_message, images (handles). Model select. Run button β POST /api/workflows/execute with scope SINGLE, nodeIds = [this node id] (execute route upstream bhi add karta hai). Response β updateNodeData(response).
- TextNode: data.text output. CropImageNode: image_url input + dimensions from data; output = cropped URL. ExtractFrameNode: video_url + timestamp β frame URL. Execution in execute route (switch by type).
- dirs:
['./src/trigger']. Project id, runtime node. Repo mein abhi src/trigger/example.ts hi hai (hello-world task). Execute route task ids llm-execution, crop-image, extract-frame use karta hai β ye tasks agar deploy hon to Trigger.dev worker inko run karta hai; nahi to SKIP_TRIGGER_DEV ya fallback direct/process route.
- Entry: layout (Clerk) β middleware (auth) β / β dashboard if logged in.
- Dashboard: GET /api/workflows β list. Create β POST /api/workflows β push /workflows/:id. Open/duplicate/rename/delete via API.
- Editor: /workflows/:id β loadWorkflow (GET :id) β store set. Canvas = ReactFlow + store (nodes, edges). Add node = NodeSidebar drag ya connection menu drop. Connect = validation β onConnect (store).
- Run: FloatingToolbar (or PropertiesSidebar "Run selected" ya Cmd+R) β handleRun(scope) β POST /api/workflows/execute (workflowId, nodes, edges, scope, nodeIds) β API: topologicalSort β layer-by-layer run, har node ke liye getConnectedInputs + nodeOutputs, type-wise execute (text/upload/llm/crop/frame), Trigger.dev ya direct/process β DB WorkflowRun + NodeResult β response results β client updateNodeData(status, output, error).
- Upload: Node pe file drop β /api/upload/params β Transloadit upload + poll β updateNodeData(url). Run time pe sirf ye URL use hota hai.
- Save: Store saveWorkflow β PATCH /api/workflows/:id (ya POST if new). Auto-save bhi same, debounced.
Yahi end-to-end flow hai β entry se run tak, bina kuch miss kiye.