How do i visually assemble and test an n8n custom node without writing code, and where to add optional javascript?

I’m not a full-time dev but I need to build a custom n8n node that does some non-trivial transformations. I started with the no-code/low-code builder and it let me drag together inputs, simple transforms, and example webhooks. The big win was the ability to run and inspect the scenario in the visual editor: I could see how arrays and objects moved between steps and fix mapping mistakes quickly.

When I needed more power, I dropped in a JavaScript step. A few practical takeaways: use the JS step for focused tasks (parsing, calling an external API, complex array manipulation), keep the code small and well-commented, and leverage available npm-like helpers if your platform offers them. I also used an AI code assistant to synthesize a short snippet to normalize nested arrays — it wasn’t perfect, but it got me 80% of the way there and saved a lot of fiddling.

For those who’ve done this: how do you decide which logic stays in visual nodes and which you push into JS? Any tips for keeping optional code maintainable over time?

i split logic by inspectability. if a non-dev should read the flow, keep it visual. put specialized parsing or heavy transforms in js so it’s testable and versioned.

i also add small unit tests around the js bits and keep the code short. the visual builder handles retries and webhooks nicely, which keeps ops simple.

I keep validation and routing visual. Complex transforms go into JS. For maintainability I create a tiny wrapper that exposes only a few inputs and outputs to the visual flow. That way you can swap the JS without touching the main scenario.

When adding JS, I document expected input schema in the step description and include a sample payload. It makes handoffs way less painful if someone else needs to update the function later.

In a recent project I had to process nested arrays, enrich data from third-party APIs, and then route items based on business rules. I designed the scenario so that the visual steps handled orchestration: webhooks, conditional branches, retries. All heavy lifting — array flattening, data merging, deduplication — went into a single JavaScript node that used small helper functions. To keep that code maintainable I did three things: kept the JS node under 120 lines, split helpers into named functions with tests, and logged structured diagnostics back into the scenario so I could replay failing inputs. I also used an AI assistant to bootstrap the helper functions, then reviewed and tightened them. That pattern let non-dev teammates understand the overall flow while letting the dev work live in a single, testable JS block.

My rule of thumb: visual nodes for flow control and observability; code for deterministic data transforms and performance-sensitive logic. Always extract JS into small, pure functions and include unit tests. Keep side effects out of the JS node; let the visual steps handle retries and external calls when possible.

visual = routing + checks. js = parsing + transforms. keep tests for js. simple as that.

keep ui for flow; js for transforms

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.