How to Create Custom Nodes in n8n: A Complete Implementation Guide
To create custom nodes in n8n, you build a TypeScript class implementing the IExecuteFunctions interface with a static description object for metadata, then place the compiled module in the directory specified by the customNodesPath instance setting (default ~/.n8n/custom).
n8n's extensible architecture allows developers to add custom nodes that integrate seamlessly into the visual workflow editor alongside built-in integrations. These custom nodes are standard Node.js modules that follow n8n's node interface conventions and are automatically discovered at runtime. When you create custom nodes in n8n, you enable direct integration of proprietary APIs, internal services, or specialized business logic into your automation workflows.
Understanding Custom Node Discovery
n8n loads node definitions from two distinct sources during startup. Built-in nodes reside in packages/nodes-base, while custom nodes are loaded from the file system path defined by the customNodesPath instance setting. According to the source code in packages/core/src/instance-settings/instance-settings.ts, this path defaults to ~/.n8n/custom but can be overridden via the N8N_CUSTOM_NODES_PATH environment variable or configured in the UI under Instance Settings → Custom Nodes Path.
The loading mechanism is handled by packages/core/src/nodes-loader/directory-loader.ts, which scans the designated directory and registers each discovered node and credential. The CLI helper that resolves these paths and initializes the runtime is located in packages/cli/src/load-nodes-and-credentials.ts.
Step 1: Scaffold the Node Structure
Begin by creating a new TypeScript file that exports a class implementing the required n8n interfaces. The official scaffolding guide in packages/@n8n/create-node/README.md provides templates and best practices for node development.
Your node file must export a class that implements execution functions. The minimal structure requires:
- A class implementing
IExecuteFunctions - A static
descriptionobject defining metadata, UI properties, and connection points - An
executemethod containing the runtime logic
Step 2: Implement the Node Class and Description
The static description object defines how your node appears in the editor, including its display name, icon, inputs, outputs, and configurable properties. The execute method receives the runtime context and returns an array of execution data.
The following example demonstrates a basic custom node structure based on the templates in packages/@n8n/create-node:
// packages/@n8n/create-node/templates/MyCustomNode.node.ts
import {
IExecuteFunctions,
} from 'n8n-workflow';
export class MyCustomNode implements IExecuteFunctions {
// Static description used by the UI
static description = {
displayName: 'My Custom Node',
name: 'myCustomNode',
group: ['transform'],
version: 1,
description: 'Fetches data from My API',
defaults: {
name: 'My Custom Node',
},
inputs: ['main'],
outputs: ['main'],
properties: [
{
displayName: 'Endpoint',
name: 'endpoint',
type: 'string',
default: '',
required: true,
},
],
};
async execute(this: IExecuteFunctions): Promise<any[]> {
const endpoint = this.getNodeParameter('endpoint', 0) as string;
const response = await this.helpers.request({
method: 'GET',
uri: endpoint,
json: true,
});
return this.prepareOutputData([{ json: response }]);
}
}
Step 3: Configure Credentials (Optional)
If your custom node requires authentication, create a matching credentials class in the same custom nodes directory. Define the credential properties and reference them in your node's description.credentials array. The credential definition follows the same pattern as built-in nodes found in packages/nodes-base.
Step 4: Deploy to the Custom Nodes Directory
Place the compiled node file (or the entire npm package) into the custom nodes directory. By default, n8n watches ~/.n8n/custom/, but you can configure this via the N8N_CUSTOM_NODES_PATH environment variable as implemented in packages/core/src/instance-settings/instance-settings.ts.
Organize your files using the following structure:
mkdir -p ~/.n8n/custom/MyCustomNode
cp dist/MyCustomNode.node.js ~/.n8n/custom/MyCustomNode/
For npm packages, n8n resolves modules from node_modules when the package name begins with n8n-nodes-, or when you explicitly add the package path to the custom nodes folder.
Step 5: Restart or Enable Hot-Reload
After deployment, restart the n8n instance to load the new node. For development workflows, enable hot-reload by setting the environment variable N8N_HOT_RELOAD=true before starting n8n. This feature is exercised in the test suite at packages/core/src/nodes-loader/__tests__/directory-loader.test.ts, allowing automatic detection of file changes without manual restarts.
export N8N_HOT_RELOAD=true
n8n start
Packaging Custom Nodes for Distribution
To distribute your custom node, package it as an npm module with the n8n-nodes- prefix. This naming convention allows n8n to automatically resolve the package from node_modules. Include the compiled JavaScript, TypeScript definitions, and a package.json that declares the node files. Users can then install your package into their custom nodes directory or alongside their n8n installation.
Summary
- Custom nodes are Node.js modules implementing
IExecuteFunctionswith a staticdescriptionobject that defines UI metadata and execution logic. - n8n discovers custom nodes from the path defined in
customNodesPath(default~/.n8n/custom), handled bypackages/core/src/nodes-loader/directory-loader.ts. - Place compiled node files or npm packages in the custom directory, then restart n8n or enable
N8N_HOT_RELOAD=truefor automatic reloading during development. - Optional credentials are implemented as separate classes in the same directory and referenced via the
description.credentialsproperty. - For distribution, publish npm packages prefixed with
n8n-nodes-to enable automatic resolution fromnode_modules.
Frequently Asked Questions
Where does n8n look for custom nodes?
n8n searches for custom nodes in the directory specified by the customNodesPath instance setting, which defaults to ~/.n8n/custom/ as defined in packages/core/src/instance-settings/instance-settings.ts. You can override this location using the N8N_CUSTOM_NODES_PATH environment variable or through the Instance Settings UI.
What is the N8N_CUSTOM_NODES_PATH environment variable?
N8N_CUSTOM_NODES_PATH is an environment variable that specifies the absolute file system path where n8n should scan for user-provided nodes and credentials. When set, it overrides the default ~/.n8n/custom/ location processed by packages/core/src/nodes-loader/directory-loader.ts.
How do I debug a custom node during development?
Enable hot-reload by setting N8N_HOT_RELOAD=true before starting n8n, which allows the runtime to detect file changes in the custom nodes directory without requiring a full restart. This functionality is tested in packages/core/src/nodes-loader/__tests__/directory-loader.test.ts. You can also add console.log statements in the execute method or use the VS Code debugger attached to the n8n Node.js process.
Can I publish custom nodes as npm packages?
Yes, you can publish custom nodes as standard npm packages. Name your package with the n8n-nodes- prefix so n8n automatically discovers it in node_modules, or manually place the package contents in your configured custom nodes directory. Ensure your package.json correctly points to the compiled node files.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →