diff --git a/packages/dashboard/app/components/WorkflowNodeEditor.tsx b/packages/dashboard/app/components/WorkflowNodeEditor.tsx
index bb19eba2ba..d134ee042e 100644
--- a/packages/dashboard/app/components/WorkflowNodeEditor.tsx
+++ b/packages/dashboard/app/components/WorkflowNodeEditor.tsx
@@ -2627,7 +2627,7 @@ function InnerEditor({
setSelectedEdgeId(null);
}}
defaultEdgeOptions={{ interactionWidth: WF_EDGE_INTERACTION_WIDTH }}
- fitView
+ defaultViewport={{ x: 0, y: 0, zoom: 1 }}
>
diff --git a/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx b/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx
index 110402c6b4..276b5165f6 100644
--- a/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx
+++ b/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx
@@ -443,6 +443,22 @@ describe("WorkflowNodeEditor — U5 auto-layout", () => {
});
});
+ it("starts the canvas viewport at the top-left on first open", async () => {
+ vi.mocked(fetchWorkflows).mockResolvedValue([v2Def()]);
+ const { container } = render(
+ {}} addToast={() => {}} />,
+ );
+
+ await screen.findByTestId("wf-node-start");
+
+ await waitFor(() => {
+ const viewport = container.querySelector(".react-flow__viewport");
+ expect(viewport).not.toBeNull();
+ expect(viewport?.style.transform).toMatch(/translate\(0px,\s*0px\)/);
+ expect(viewport?.style.transform).toContain("scale(1)");
+ });
+ });
+
it("clicking auto-layout still works after initial load", async () => {
vi.mocked(fetchWorkflows).mockResolvedValue([v2Def()]);
render(