n n8n

How to add a custom code node on n8n

intermediate 12 min read Updated 2026-03-13
Quick Answer

Clone the n8n-nodes-starter template, create your TypeScript node file with INodeType interface, build with npm run build, then copy dist/ to ~/.n8n/custom/ and restart n8n. For Docker, mount the dist/ folder or build a custom image. Test by searching for your node name in the + panel.

Prerequisites

  • Node.js v14+ and npm installed
  • n8n self-hosted instance (local or Docker)
  • Git for cloning repositories
  • Basic TypeScript knowledge
  • Access to n8n's ~/.n8n/custom/ directory

Step-by-Step Instructions

1

Clone n8n Nodes Starter Repository

Open terminal and run git clone https://github.com/n8n-io/n8n-nodes-starter then cd n8n-nodes-starter. This provides boilerplate package.json, tsconfig.json, and node examples for quick setup.
2

Install Dependencies

Run npm install to fetch TypeScript, n8n-workflow, and dev dependencies. Edit package.json to set "name": "n8n-nodes-mycustom" (prefix with n8n-nodes-), version, and scripts like "build": "tsc" and "dev": "tsc --watch".
Use yarn if preferred, but stick to npm for n8n compatibility.
3

Create Your Node File

import { IExecuteFunctions } from 'n8n-core';
import { INodeType, INodeTypeDescription } from 'n8n-workflow';

export class MyCustomNode implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'My Custom Node',
    name: 'myCustomNode',
    group: ['transform'],
    version: 1,
    description: 'Reverses input string',
    defaults: { name: 'My Custom Node', color: '#1F8EB2' },
    inputs: ['main'],
    outputs: ['main'],
    properties: [{
      displayName: 'String to Reverse',
      name: 'stringToReverse',
      type: 'string',
      default: '',
      placeholder: 'Enter string'
    }]
  };

  async execute(this: IExecuteFunctions) {
    const items = this.getInputData();
    const returnData = [];
    const stringToReverse = this.getNodeParameter('stringToReverse', 0) as string;
    returnData.push({ json: { reversed: stringToReverse.split('').reverse().join('') } });
    return this.prepareOutputData(returnData);
  }
}
Save as nodes/MyCustomNode/MyCustomNode.node.ts. Update index.ts to export the class.
Add JSDoc comments and helper functions for maintainability.
4

Configure TypeScript

Ensure tsconfig.json has "outDir": "./dist", "target": "ES2019", "module": "CommonJS", and includes your node files. This compiles TS to JS in /dist/.
5

Build the Node Package

Run npm run build to compile TypeScript to JavaScript in the dist/ folder. Verify dist/node/ and dist/credentials/ (if any) contain your files.
Use <code>npm run dev</code> for watch mode during development.
6

Set Up Custom Directory in n8n

Create ~/.n8n/custom/ if missing. Copy dist/node/ and dist/credentials/ into it, then cd ~/.n8n/custom/, run npm init -y, and npm install.
For linked development, use <code>npm link</code> in your node project and <code>npm link n8n-nodes-mycustom</code> in custom/.
7

Restart n8n

Restart your n8n instance (e.g., docker restart n8n or kill/restart local process). Open n8n at http://localhost:5678, create a new workflow, click +, and search for 'My Custom Node'.
Check browser console and n8n logs for errors.
8

Docker Deployment (Production)

FROM n8nio/n8n:latest
USER root
COPY ./dist /home/node/.n8n/custom/
USER node
Build custom image with your docker-compose.yml mounting ./dist:/home/node/.n8n/custom/node_modules/n8n-nodes-mycustom. Match n8n version.
Use volumes for hot-reloading in dev: <code>- ./dist:/home/node/.n8n/custom/node_modules/&lt;repo-name&gt;</code>.
9

Test and Debug

Add the node to a workflow, input a string, execute, and verify output (e.g., 'hello' becomes 'olleh'). Check logs with docker logs n8n for module resolution issues.
10

Document and Enhance

Add descriptions, icons (SVG in node folder), and properties to description object. Modularize with helpers and constants for complex logic.
Run n8n node linter before sharing.

Common Issues & Troubleshooting

Node not visible in + panel (search yields nothing)

Create ~/.n8n/custom/, cd into it, npm init -y, copy dist/node/ and dist/credentials/, run npm install, restart n8n.

ENOENT: no such file or directory or module resolution fails in logs

Verify dist/ compiled correctly, run npm install in ~/.n8n/custom/, check paths, restart n8n, and inspect docker logs.

Node fails to execute (runtime errors)

Ensure async execute uses getInputData() and prepareOutputData(), match n8n-workflow version, rebuild with npm run build.

Changes not reflecting after edits

Rebuild with npm run build, recopy to custom/, run npm install, restart n8n, or use npm link for dev.

Docker: Node not found in container

Mount dist/ correctly in docker-compose.yml as /home/node/.n8n/custom/node_modules/&lt;package-name&gt;, rebuild image.