Authoring surface
React Flow and Liveblocks make the canvas collaborative. Node data remains plain JSON so it can move between the browser, room storage, and database without a translation layer.
A practical map of the architecture, maintenance boundaries, and debugging lessons behind ForgeFlow. This is intentionally specific to the codebase rather than a general workflow-automation guide.
ForgeFlow separates collaborative authoring from durable execution so each system can do one job well.
React Flow and Liveblocks make the canvas collaborative. Node data remains plain JSON so it can move between the browser, room storage, and database without a translation layer.
The database stores the validated graph snapshot. Trigger.dev reads that snapshot with the owning organization id instead of trusting a browser payload after the run begins.
Browser steps share one lazy Stagehand session. This preserves login state between nodes and produces one Browserbase recording for the run.
Most regressions are ownership mistakes. Before moving code or state, decide which system is authoritative and what it must never be trusted to do.
Owns: Canvas edits, node positions, edges, cursors, and presence
Must not own: The graph that a task executes or durable run history
components/canvas.tsx, components/room.tsxOwns: Authentication, entitlement checks, mutations, cache revalidation, and integration routes
Must not own: Long-running browser work or secret-bearing client state
features/workflows/actions.ts, app/api/Owns: Organization-owned workflow identity and the executable JSONB graph snapshot
Must not own: Realtime cursor state or transient step progress
lib/db/schema.ts, features/workflows/data.tsOwns: Durable queued execution, retries, logs, cancellation, and realtime run metadata
Must not own: Clerk session authorization or a permanent ForgeFlow audit record
features/workflows/tasks/run-workflow.tsOwns: A run-scoped browser, automation calls, recording, and replay source
Must not own: Authorization decisions or browser-visible API secrets
nodes/*.ts, lib/browserbase.ts, api/replays/Owns: Actual email delivery and duplicate-request rejection
Must not own: Workflow scheduling or retry policy
nodes/send-email.tsThese decisions keep the visual canvas, runner, and external services coherent as node types evolve.
The node registry defines kinds, fields, icons, and outputs, while the executor map satisfies every action-node type at compile time. Adding a node is a three-file change, not a canvas rewrite.
features/workflows/nodes/Liveblocks holds the collaborative editing copy. The Run action validates and writes an organization-owned JSONB snapshot before Trigger.dev loads and executes it.
features/workflows/actions.ts and data.tsTrigger metadata powers live node status and output while a run is active. A future run-history view should use a durable record rather than assume a realtime subscription is a permanent audit log.
workflow-runs-provider.tsx and run-workflow.tsWorkflow tasks retry. The Send Email executor receives the Trigger run id and node id so Resend can reject a duplicate attempt without blocking a deliberately new workflow run.
node-executors.ts and send-email.tsStagehand opens lazily on the first browser node and is reused for later browser nodes. A finally block closes it whether the run succeeds, fails, or is cancelled.
features/workflows/tasks/run-workflow.tsThe palette can guide users to upgrade, but direct Server Action calls remain possible. Agent execution and replay retrieval independently check the active organization plan on the server.
actions.ts and app/api/replays/[sessionId]/route.tsA node field can be marked required in the registry and highlighted in the editor, yet the current server validator checks only graph structure. Treat node values as untrusted executor input until field-level validation exists on both sides of the boundary.
node-registry.ts and lib/validate-graph.tsClerk Billing advertises several plan features, but ForgeFlow code currently enforces only the Pro plan for Agent execution and replay. A plan label or configured feature has no effect until a server boundary checks it.
billing.json, use-pro-gate.ts, actions.tsUse these checklists when changing the system. They encode the hidden cross-file contracts that are easy to miss in an otherwise small feature.
Start from the durable system that owns the behavior, then work outward to the user interface.
Inspect the Trigger run metadata first. The runner publishes pending, running, done, and failed steps; a missing step usually means the graph was not saved or the node is disconnected.
Browserbase records asynchronously after a session closes. The replay route translates the temporary not-ready state to HTTP 202, and the player polls it instead of treating it as a hard failure.
Verify the upstream node ran first and that the token path matches one of the outputs in the registry. Missing paths deliberately interpolate to an empty string so a template never crashes the runner.
Resend returns errors in its response object rather than throwing. Treat an error or missing data object as a failed step, then verify the Resend API key and sender domain.
The current graph validator deliberately checks only one Start node, at least one edge, and no cycle. Inspect the executor input and add explicit validation before relying on a red required marker as a safety boundary.
Check SENTRY_DSN first, then review the current 1.0 trace sample rate and browser Replay sampling. The sample Sentry page and API are probes; they are not evidence that ordinary product errors are correctly classified.
The useful optimization is usually a clear ownership boundary, not a clever cache.
Run metadata is realtime UI state with a finite size budget. Publish step summaries and serializable outputs, not browser objects or full page payloads.
Browserbase, Liveblocks, Resend, Trigger.dev, and database credentials stay server-side. Only Clerk's publishable key is meant for the browser.
Run typecheck, lint, build, database migrations, and a real organization-scoped browser run. Replay verification is part of the security check, not only a UI test.
These are small rules with large consequences. Keep them true when adding nodes, changing tasks, or evolving the collaboration model.
Every workflow read, update, and delete includes the active organization id.
Only connected nodes execute; a graph must contain one Start trigger and no cycle.
A browser session is created lazily and always closed by the task runner.
Replay access verifies the user, organization, Pro plan, workflow ownership, run tag, and session id.
Action-node executor coverage stays compile-time checked against the registry.
Liveblocks room permissions and identity group ids use the same Clerk organization id.
These are current product boundaries, not accidental omissions. Preserve them or replace them with an explicit design and migration plan.
The most useful next improvements are durable run history, explicit save semantics, automated authorization coverage, and richer graph-level validation.
Open ForgeFlow