Showing posts with label automatio. Show all posts
Showing posts with label automatio. Show all posts

Writing My First Custom n8n Node: A Step-by-Step Guide

Recently, I decided to create a custom node for n8n, the workflow automation tool I've been using. I'm not an expert in Node.js development, but I wanted to understand how n8n nodes work under the hood. This blog post shares my journey and the steps that actually worked for me.

French version here

Why I Did This

Before starting this project, I was curious about how n8n nodes are built. The best way to learn something is by doing it, so I decided to create a simple custom node following n8n's official tutorial. Now that I understand the basics, I'm planning to build a more complex node featuring AI Vision capabilities, but that's for another blog post!

The Challenge

I started with the official n8n tutorial: Build a declarative-style node. While the tutorial is well-written, I ran into some issues along the way. The steps didn't work exactly as described, so I had to figure out what was missing. This post documents what actually worked for me, in case you're facing similar challenges. I already have an n8n instance running in a container. In Step 8, I'll explain how I run a second instance for development purposes.

Prerequisites

Before you start, you'll need:

  • Node.js and npm - I used Node.js version 24.12.0
  • Basic understanding of JavaScript/TypeScript - you don't need to be an expert

Step 1: Fixing the Missing Prerequisites

I didn't have Node.js installed on my machine, so my first step was getting that sorted out. Instead of installing Node.js directly, I used nvm (Node Version Manager), which makes it easy to manage different Node.js versions. Installation details are available on the nvm GitHub repository. Once nvm was set up, I installed Node.js version 24.12.0.

Most of the time, I use VS Code as my code editor. I created a new profile and used the template for Node.js development to get the right extensions and settings.

Step 2: Cloning the Starter Repository

n8n provides a n8n-nodes-starter on GitHub that includes all the basic files and dependencies you need. You can clone it or use it as a template for your own project. Since this was just a "learning exercise" for me, I cloned the repository directly:

git clone https://github.com/n8n-io/n8n-nodes-starter
cd n8n-nodes-starter

Step 3: Getting Started with the Tutorial

I won't repeat the entire tutorial here; it's clear enough, but I'll highlight some details along the way that I found useful.

The tutorial makes you create a "NasaPics" node and provides a logo for it. It's great, but I suggest you use your own logo images and have light and dark versions. Add both images in a new folder icons (same level as nodes and the credentials folder). Having two versions of the logo will make your node look better, whatever theme the user is using in n8n (light or dark). The tutorial only adds the logo in NasaPics.node.ts, but I found that adding it also in the credentials file NasaPicsApi.credentials.ts makes the node look more consistent.

Replace or add the logo line with this, and add Icon to the import statement at the top of the file:

icon: Icon = { light: 'file:MyLogo-dark.svg', dark: 'file:MyLogo-light.svg' };

Note: the darker logo should be used in light mode, and vice versa.

Step 4: Following the Tutorial (With Adjustments)

Here's where things got interesting. I followed the official tutorial to create the node files, but I had to make some adjustments that weren't mentioned in the documentation.

Adjustment 1: Making the Node Usable as a Tool

In the NasaPics.node.ts file, I added this line just before the properties array:

requestDefaults: {
      baseURL: 'https://api.nasa.gov',
      headers: {
         Accept: 'application/json',
         'Content-Type': 'application/json',
      },
   },
   usableAsTool: true, // <-- Added this line
   properties: [
      // Resources and operations will go here

This setting allows the node to be used as a tool within n8n workflows and also fixes warnings from the lint tool.

Adjustment 2: Securing the API Key Field

In the NasaPicsApi.credentials.ts file, I added a typeOptions to make the API key field a password field. This ensures the API key is hidden when users enter it, which is a security best practice.

properties: INodeProperties[] = [
   {
      displayName: 'API Key',
      name: 'apiKey',
      type: 'string',
      typeOptions: { password: true }, // <-- Added this line
      default: '',
   },
];

A Note on Errors

I noticed there were some other errors showing up in the credentials file. If you read the error message, you'll see that it's complaining about missing test properties. To fix this, I added a test property at the end of the class that implements ICredentialTestRequest. I also added the interface import at the top of the file.

authenticate: IAuthenticateGeneric = {
   type: 'generic',
   properties: {
      qs: {
         api_key: '={{$credentials.apiKey}}',
      },
   },
};

// Add this at the end of the class
test: ICredentialTestRequest = {
   request: {
      baseURL: 'https://api.nasa.gov/',
      url: '/user',
      method: 'GET',
   },
};

Step 5: Building and Linking the Package

Once I had all my files ready, it was time to build the node. From the root of my node project folder, I ran:

npm i
npm run build
npm link

During the build process, pay attention to the package name that gets generated. In my case, it was n8n-nodes-nasapics. You'll need this name in the next steps.

> n8n-nodes-nasapics@0.1.0 build
> n8n-node build

┌   n8n-node build 
│
◓  Building TypeScript files│
◇  TypeScript build successful
│
◇  Copied static files
│
└  ✓ Build successful

Step 6: Setting Up the n8n Custom Folder

n8n looks for custom nodes in a specific location: ~/.n8n/custom/. If this folder doesn't exist, you need to create it:

mkdir -p ~/.n8n/custom
cd ~/.n8n/custom

Then initialize a new npm package in this folder: run npm init and press Enter to accept all the defaults.

Step 7: Linking Your Node to n8n

Now comes the magic part - linking your custom node so n8n can find it. Replace n8n-nodes-nasapics with whatever your package name is. From the ~/.n8n/custom folder, run:

npm link n8n-nodes-nasapics

Step 8: Running n8n

This is where my setup differs from the standard tutorial. As mentioned at the beginning, I already have an instance of n8n running in a container and didn't want to install it. So I decided to run a second container using a different port. Here's the command I used:

docker run -d --name n8n-DEV -p 5680:5678 \
  -e N8N_COMMUNITY_PACKAGES_ENABLED=true \
  -v ~/.n8n/custom/node_modules/n8n-nodes-nasapics:/home/node/.n8n/custom/node_modules/n8n-nodes-nasapics \
  n8nio/n8n

Let me break down what this command does:

  • -d: Runs the container in detached mode (in the background)
  • --name n8n-DEV: Names the container for easy reference
  • -p 5680:5678: Maps port 5678 from the container to port 5680 on my machine so it doesn't conflict with my existing n8n instance
  • -e N8N_COMMUNITY_PACKAGES_ENABLED=true: Enables community packages — you need this to use custom nodes
  • -v: Mounts my custom node folder into the container, which lets me try my custom node without having to publish it.
  • n8nio/n8n: The official n8n container image

If you're running n8n directly on your machine (not in a container), you can simply start it.

Step 9: Testing Your Node

Once n8n-DEV is running, open your browser and navigate to it. Create a new workflow and search for your node. In my case, I searched for "NasaPics" and my custom node appeared!

To test it:

  1. Add your node to the workflow
  2. Configure the credentials with a NASA API key (you can get one for free at api.nasa.gov)
  3. Execute the node
  4. Check if the data is retrieved correctly

Updating Your Node

During development, you'll likely need to make changes to your code (aka node). Once done, you have to rebuild npm run build and restart the n8n container docker restart n8n-DEV to see the changes.

What's Next?

Now that I understand the basics of building custom n8n nodes, I'm ready to tackle something more ambitious. My next project will be creating a node that uses AI Vision capabilities. Spoiler alert: It's done and I'll be sharing the details in an upcoming blog post!

If you're interested in creating your own custom nodes, I encourage you to give it a try. Start with something simple, like I did, and build from there. Don't be afraid to experiment and make mistakes - that's how we learn!

Resources