DEV Community

Chase Dalin
Chase Dalin

Posted on

I import-tested 3 n8n workflow templates like they were going to clients. Here's the checklist I use.

Most workflow templates for sale are hello-world demos: they import, the canvas looks nice, and the first real run explodes. I'm packaging n8n templates I intend to sell to actual businesses, so I test them the way I'd test a client deployment. Here's the method, the 8 bugs it caught across 3 workflows, and the reusable checklist.

The method

  1. Clean-room n8n instance. I spun up n8n 2.42.5 in Docker — no credentials, no prior workflows, no extensions. If a template only works in the author's environment, it's not a template.
  2. Import via the CLI (n8n import:workflow) with no credentials attached. It must import clean — zero errors — before anything else.
  3. Walk every branch of every If/Switch node and confirm each branch actually executes. A branch that can never fire is a dead feature you're selling.
  4. Grep the JSON for {{ placeholders that survive import. Every one must either interpolate from a config node or be documented in the README as buyer setup.
  5. Confirm no node writes outside allowed paths. n8n 2.x blocks /tmp by default, so a template that writes there works on the author's machine and nowhere else.

The 8 bugs

Missed-call text-back pack (4):

  • An If-node routed on largerEquals / smallerEquals operators that don't exist in n8n. The condition silently evaluated so the workflow always took the after-hours branch — the entire AI-reply path could never fire. The correct operators are the numeric comparisons (larger / smaller etc.). This is the kind of bug that passes a visual review and fails every real run.
  • A check used $node.isExecuted in a context where it was always falsy. Rewrote the condition.
  • The logging node pulled from the wrong Twilio output field — every logged interaction would have recorded garbage.
  • A {{business_name}} placeholder was left uninterpolated in the after-hours message body. Buyers would have texted customers a literal template tag.

B2B lead enrichment pack (4):

  • A .item accessor inside a node running in runOnceForEachItem mode, where that accessor is forbidden — it throws on execution. Rewrote the pairing with index-based access.
  • The dedup node was configured with a v1 operation name on a v2 node. It imported fine and silently deduped nothing. Fixed the config and moved dedup before AI scoring so we're not paying for tokens on duplicates.
  • A .map() over CSV rows produced misaligned rows — values landing in the wrong columns. Fixed the row construction.
  • The workflow wrote its CSV to /tmp, which n8n 2.x blocks by default. Changed to a documented, allowed location.

Weekly content pipeline pack: clean. Nine nodes, imported and executed without changes.

(Two more worth mentioning: the lead pack originally shipped two placeholder HTTP nodes pointed at .example.com enrichment endpoints. I disabled them and documented that the buyer wires their own provider — a placeholder that looks like a feature is worse than a documented gap.)

The reusable checklist

  • Clean-room instance, no credentials, no extensions
  • CLI import must be error-free
  • Every conditional branch must be executable
  • No surviving uninterpolated placeholders (or document each one)
  • No writes outside allowed paths
  • Credential placeholders must import without errors; the buyer attaches their own
  • If a node can't work without buyer config, disable it and document the wiring — don't ship a live-looking placeholder

What ships

Each pack goes out as workflow.json + README + per-credential setup guide + demo script, with sticky-note documentation inside the workflow itself. The three packs (content pipeline, missed-call text-back, lead enrichment) are $49 each or $149 bundled: https://chasedalin.gumroad.com/l/cmypoo

Top comments (1)

Collapse
 
launchgatecheck profile image
Launch Gate •

The clean-room branch checks are useful. I'd add one fixture after the CSV pairing fix: give each input an unmistakable ID, reject the middle lead, and have enrichment return results in a different order. Then check that every surviving exported row still carries its own enrichment fields. Index-based pairing can look correct on the all-success path while filtering changes the positions. For the text-back pack, I'd also replay the same inbound event twice and assert one customer message, not just a successful execution.