From 150fee00009840216fbb393077c9d811f2b8a109 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 19 Feb 2026 09:41:18 +0000 Subject: [PATCH] Small tweaks to node creator docs (#4239) Co-authored-by: Kartik Balasubramanian <22399046+HumanistSerif@users.noreply.github.com> --- .../integrations/submit-community-node.md | 4 + .../build/declarative-style-node.md | 31 +++-- .../build/node-development-environment.md | 2 +- .../build/programmatic-style-node.md | 107 ++++++++++-------- .../build/reference/code-standards.md | 4 +- .../build/reference/error-handling.md | 8 +- .../build/reference/node-codex-files.md | 2 +- .../build/reference/node-file-structure.md | 2 +- .../reference/verification-guidelines.md | 17 ++- 9 files changed, 106 insertions(+), 71 deletions(-) diff --git a/_snippets/integrations/submit-community-node.md b/_snippets/integrations/submit-community-node.md index c0bbc1aba..5f26269be 100644 --- a/_snippets/integrations/submit-community-node.md +++ b/_snippets/integrations/submit-community-node.md @@ -19,6 +19,10 @@ Developing with the [`n8n-node` tool](/integrations/creating-nodes/build/n8n-nod ## Submit your node for verification by n8n +/// note | Upcoming Changes +From May 1st 2026 you must publish **ALL** community nodes using a GitHub action and include a [provenance statement](https://docs.npmjs.com/generating-provenance-statements) +/// + n8n vets verified community nodes. Users can discover and install verified community nodes from the nodes panel in n8n. These nodes need to adhere to certain technical and UX standards and constraints. Before submitting your node for review by n8n, you must: diff --git a/docs/integrations/creating-nodes/build/declarative-style-node.md b/docs/integrations/creating-nodes/build/declarative-style-node.md index 04f93fbea..5911e3dcf 100644 --- a/docs/integrations/creating-nodes/build/declarative-style-node.md +++ b/docs/integrations/creating-nodes/build/declarative-style-node.md @@ -41,10 +41,10 @@ Clone the repository and navigate into the directory: The starter contains example nodes and credentials. Delete the following directories and files: -* `nodes/ExampleNode` -* `nodes/HTTPBin` -* `credentials/ExampleCredentials.credentials.ts` -* `credentials/HttpBinApi.credentials.ts` +* `nodes/Example` +* `nodes/GithubIssues` +* `credentials/GithubIssuesApi.credentials.ts` +* `credentials/GithubIssuesOAuth2Api.credentials.ts` Now create the following directories and files: @@ -80,7 +80,8 @@ In this example, the file is `NasaPics.node.ts`. To keep this tutorial short, yo Start by adding the import statements: ```typescript -import { INodeType, INodeTypeDescription } from 'n8n-workflow'; +import { NodeConnectionTypes } from 'n8n-workflow'; +import type { INodeType, INodeTypeDescription } from 'n8n-workflow'; ``` #### Step 3.2: Create the main class @@ -116,8 +117,9 @@ description: 'Get data from NASAs API', defaults: { name: 'NASA Pics', }, -inputs: ['main'], -outputs: ['main'], +usableAsTool: true, +inputs: [ NodeConnectionTypes.Main ], +outputs: [ NodeConnectionTypes.Main ], credentials: [ { name: 'NasaPicsApi', @@ -328,15 +330,16 @@ For this tutorial, you'll add one additional field, to allow users to pick a dat ``` -### Step 4: Set up authentication +### Step 4: Set up authentication and a credential test -The NASA API requires users to authenticate with an API key. +The NASA API requires users to authenticate with an API key. You can also send a request to check that the API key works. Add the following to `nasaPicsApi.credentials.ts`: ```typescript import { IAuthenticateGeneric, + ICredentialTestRequest, ICredentialType, INodeProperties, } from 'n8n-workflow'; @@ -355,14 +358,20 @@ export class NasaPicsApi implements ICredentialType { default: '', }, ]; - authenticate = { + authenticate: IAuthenticateGeneric = { type: 'generic', properties: { qs: { 'api_key': '={{$credentials.apiKey}}' } }, - } as IAuthenticateGeneric; + }; + test: ICredentialTestRequest = { + request: { + baseURL: 'https://api.nasa.gov', + url: '/apod', + }, + }; } ``` diff --git a/docs/integrations/creating-nodes/build/node-development-environment.md b/docs/integrations/creating-nodes/build/node-development-environment.md index 2ce3ff59e..c2b7fe0b1 100644 --- a/docs/integrations/creating-nodes/build/node-development-environment.md +++ b/docs/integrations/creating-nodes/build/node-development-environment.md @@ -10,7 +10,7 @@ This document lists the essential dependencies for developing a node, as well as To build and test a node, you need: -* Node.js and npm. Minimum version Node 18.17.0. You can find instructions on how to install both using nvm (Node Version Manager) for Linux, Mac, and WSL (Windows Subsystem for Linux) [here](https://github.com/nvm-sh/nvm). For Windows users, refer to Microsoft's guide to [Install NodeJS on Windows](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-windows). +* Node.js and npm. Minimum version Node 22.22.0. You can find instructions on how to install both using nvm (Node Version Manager) for Linux, Mac, and WSL (Windows Subsystem for Linux) [here](https://github.com/nvm-sh/nvm). For Windows users, refer to Microsoft's guide to [Install NodeJS on Windows](https://docs.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-windows). * A local instance of n8n. You can install n8n with `npm install n8n -g`, then follow the steps in [Run your node locally](/integrations/creating-nodes/test/run-node-locally.md) to test your node. * When [building verified community nodes](/integrations/community-nodes/build-community-nodes.md), you must use the [`n8n-node` tool](/integrations/creating-nodes/build/n8n-node.md) to create and test your node. diff --git a/docs/integrations/creating-nodes/build/programmatic-style-node.md b/docs/integrations/creating-nodes/build/programmatic-style-node.md index 485d84ec7..78888d60f 100644 --- a/docs/integrations/creating-nodes/build/programmatic-style-node.md +++ b/docs/integrations/creating-nodes/build/programmatic-style-node.md @@ -42,10 +42,10 @@ Clone the repository and navigate into the directory: The starter contains example nodes and credentials. Delete the following directories and files: -* `nodes/ExampleNode` -* `nodes/HTTPBin` -* `credentials/ExampleCredentials.credentials.ts` -* `credentials/HttpBinApi.credentials.ts` +* `nodes/Example` +* `nodes/GithubIssues` +* `credentials/GithubIssuesApi.credentials.ts` +* `credentials/GithubIssuesOAuth2Api.credentials.ts` Now create the following directories and files: @@ -81,21 +81,15 @@ In this example, the file is `FriendGrid.node.ts`. To keep this tutorial short, Start by adding the import statements: ```typescript -import { - IExecuteFunctions, -} from 'n8n-core'; - -import { +import type { IDataObject, + IExecuteFunctions, + IHttpRequestOptions, INodeExecutionData, INodeType, INodeTypeDescription, - NodeConnectionType } from 'n8n-workflow'; - -import { - OptionsWithUri, -} from 'request'; +import { NodeConnectionTypes } from 'n8n-workflow'; ``` #### Step 3.2: Create the main class @@ -133,8 +127,9 @@ description: 'Consume SendGrid API', defaults: { name: 'FriendGrid', }, -inputs: [NodeConnectionType.Main], -outputs: [NodeConnectionType.Main], +inputs: [NodeConnectionTypes.Main], +outputs: [NodeConnectionTypes.Main], +usableAsTool: true, credentials: [ { name: 'friendGridApi', @@ -273,45 +268,61 @@ Add the following the `execute` method in the `FriendGrid.node.ts`: // Handle data coming from previous nodes const items = this.getInputData(); let responseData; -const returnData = []; -const resource = this.getNodeParameter('resource', 0) as string; -const operation = this.getNodeParameter('operation', 0) as string; +const returnData: INodeExecutionData[] = []; +const resource = this.getNodeParameter('resource', 0); +const operation = this.getNodeParameter('operation', 0); // For each item, make an API call to create a contact for (let i = 0; i < items.length; i++) { - if (resource === 'contact') { - if (operation === 'create') { - // Get email input - const email = this.getNodeParameter('email', i) as string; - // Get additional fields input - const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; - const data: IDataObject = { - email, - }; + try { + if (resource === 'contact') { + if (operation === 'create') { + // Get email input + const email = this.getNodeParameter('email', i); + // Get additional fields input + const additionalFields = this.getNodeParameter('additionalFields', i); + const data: IDataObject = { + email, + }; - Object.assign(data, additionalFields); + Object.assign(data, additionalFields); - // Make HTTP request according to https://sendgrid.com/docs/api-reference/ - const options: OptionsWithUri = { - headers: { - 'Accept': 'application/json', - }, - method: 'PUT', - body: { - contacts: [ - data, - ], - }, - uri: `https://api.sendgrid.com/v3/marketing/contacts`, - json: true, - }; - responseData = await this.helpers.requestWithAuthentication.call(this, 'friendGridApi', options); - returnData.push(responseData); + // Make HTTP request according to https://sendgrid.com/docs/api-reference/ + const options: IHttpRequestOptions = { + headers: { + 'Accept': 'application/json', + }, + method: 'PUT', + body: { + contacts: [ + data, + ], + }, + url: 'https://api.sendgrid.com/v3/marketing/contacts', + json: true, + }; + responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'friendGridApi', options); + const executionData = this.helpers.constructExecutionMetaData( + this.helpers.returnJsonArray(responseData as IDataObject), + { itemData: { item: i } }, + ); + + returnData.push.apply(returnData, executionData); + } } + } catch (error) { + if (this.continueOnFail()) { + const executionData = this.helpers.constructExecutionMetaData( + this.helpers.returnJsonArray({ error: error.message }), + { itemData: { item: i } }, + ); + returnData.push.apply(returnData, executionData); + continue; + } + throw error; } } -// Map data to n8n data structure -return [this.helpers.returnJsonArray(returnData)]; +return [returnData]; ``` Note the following lines of this code: @@ -321,7 +332,7 @@ const items = this.getInputData(); ... for (let i = 0; i < items.length; i++) { ... - const email = this.getNodeParameter('email', i) as string; + const email = this.getNodeParameter('email', i); ... } ``` diff --git a/docs/integrations/creating-nodes/build/reference/code-standards.md b/docs/integrations/creating-nodes/build/reference/code-standards.md index 8fc88dd7a..d15c3417c 100644 --- a/docs/integrations/creating-nodes/build/reference/code-standards.md +++ b/docs/integrations/creating-nodes/build/reference/code-standards.md @@ -10,9 +10,9 @@ Following defined code standards when building your node makes your code more re The n8n node linter provides automatic checking for many of the node-building standards. You should ensure your node passes the linter's checks before publishing it. Refer to the [n8n node linter](/integrations/creating-nodes/test/node-linter.md) documentation for more information. -## Use the starter +## Use the n8n-node tool -The n8n node starter project includes a recommended setup, dependencies (including the linter), and examples to help you get started. Begin new projects with the [starter](https://github.com/n8n-io/n8n-nodes-starter). +n8n recommends using the [`n8n-node` CLI tool](/integrations/creating-nodes/build/n8n-node.md) to build and test your node. In particular, this is important if you plan on [submitting your node for verification](/integrations/creating-nodes/deploy/submit-community-nodes.md#submit-your-node-for-verification-by-n8n). This ensures that your node has the correct structure and follows community node requirements. It also simplifies linting and testing. ## Write in TypeScript diff --git a/docs/integrations/creating-nodes/build/reference/error-handling.md b/docs/integrations/creating-nodes/build/reference/error-handling.md index d272b3e3c..7f06f09d1 100644 --- a/docs/integrations/creating-nodes/build/reference/error-handling.md +++ b/docs/integrations/creating-nodes/build/reference/error-handling.md @@ -31,7 +31,7 @@ For basic API request failures, catch the error and wrap it in `NodeApiError`: ```typescript try { - const response = await this.helpers.requestWithAuthentication.call( + const response = await this.helpers.httpRequestWithAuthentication.call( this, credentialType, options @@ -46,7 +46,7 @@ Handle specific HTTP status codes with custom messages: ```typescript try { - const response = await this.helpers.requestWithAuthentication.call( + const response = await this.helpers.httpRequestWithAuthentication.call( this, credentialType, options @@ -54,7 +54,7 @@ try { return response; } catch (error) { if (error.httpCode === "404") { - const resource = this.getNodeParameter("resource", 0) as string; + const resource = this.getNodeParameter("resource", 0); const errorOptions = { message: `${ resource.charAt(0).toUpperCase() + resource.slice(1) @@ -103,7 +103,7 @@ new NodeOperationError(node: INode, error: Error | string | JsonObject, options? Use `NodeOperationError` for validating user inputs: ```typescript -const email = this.getNodeParameter("email", itemIndex) as string; +const email = this.getNodeParameter("email", itemIndex); if (email.indexOf("@") === -1) { const description = `The email address '${email}' in the 'email' field isn't valid`; diff --git a/docs/integrations/creating-nodes/build/reference/node-codex-files.md b/docs/integrations/creating-nodes/build/reference/node-codex-files.md index ade803945..03def6a74 100644 --- a/docs/integrations/creating-nodes/build/reference/node-codex-files.md +++ b/docs/integrations/creating-nodes/build/reference/node-codex-files.md @@ -4,7 +4,7 @@ contentType: reference # Node codex files -The codex file contains metadata about your node. This file is the JSON file at the root of your node. For example, the [`HttpBin.node.json`](https://github.com/n8n-io/n8n-nodes-starter/blob/master/nodes/HttpBin/HttpBin.node.json) file in the n8n starter. +The codex file contains metadata about your node. This file is the JSON file at the root of your node. For example, the [`GithubIssues.node.json`](https://github.com/n8n-io/n8n-nodes-starter/blob/master/nodes/GithubIssues/GithubIssues.node.json) file in the n8n starter. The codex filename must match the node base filename. For example, given a node base file named `MyNode.node.ts`, the codex would be named `MyNode.node.json`. diff --git a/docs/integrations/creating-nodes/build/reference/node-file-structure.md b/docs/integrations/creating-nodes/build/reference/node-file-structure.md index 215bc9fd3..702a616b9 100644 --- a/docs/integrations/creating-nodes/build/reference/node-file-structure.md +++ b/docs/integrations/creating-nodes/build/reference/node-file-structure.md @@ -31,7 +31,7 @@ Your node must include: You can choose whether to place all your node's functionality in one file, or split it out into a base file and other modules, which the base file then imports. Unless your node is very simple, it's a best practice to split it out. -A basic pattern is to separate out operations. Refer to the [HttpBin starter node](https://github.com/n8n-io/n8n-nodes-starter/tree/master/nodes/HttpBin) for an example of this. +A basic pattern is to separate out operations. Refer to the [GithubIssues starter node](https://github.com/n8n-io/n8n-nodes-starter/tree/master/nodes/GithubIssues) for an example of this. For more complex nodes, n8n recommends a directory structure. Refer to the [Airtable node](https://github.com/n8n-io/n8n/tree/master/packages/nodes-base/nodes/Airtable) or [Microsoft Outlook node](https://github.com/n8n-io/n8n/tree/master/packages/nodes-base/nodes/Microsoft/Outlook) as examples. diff --git a/docs/integrations/creating-nodes/build/reference/verification-guidelines.md b/docs/integrations/creating-nodes/build/reference/verification-guidelines.md index 2a16bcc0a..1c73576d7 100644 --- a/docs/integrations/creating-nodes/build/reference/verification-guidelines.md +++ b/docs/integrations/creating-nodes/build/reference/verification-guidelines.md @@ -5,25 +5,36 @@ contentType: reference # Community node verification guidelines /// note | Do you want n8n to verify your node? -Consider following these guidelines while building your node if you want to submit it for verification by n8n. Any user with verified community nodes enabled can discover and install verified nodes from n8n's nodes panel across all deployment types (self-hosted and n8n Cloud). +Follow these guidelines while building your node if you want to submit it for verification by n8n. Any user with verified community nodes enabled can discover and install verified nodes from n8n's nodes panel across all deployment types (self-hosted and n8n Cloud). +/// + + +/// note | Upcoming Changes +From May 1st 2026 you must publish **ALL** community nodes using a GitHub action and include a [provenance statement](https://docs.npmjs.com/generating-provenance-statements) /// ## Use the n8n-node tool -All verified community node authors should strongly consider using the [`n8n-node` tool](/integrations/creating-nodes/build/n8n-node.md) to create and check their package. This helps n8n ensure quality and consistency by: +All verified community node authors should use the [`n8n-node` tool](/integrations/creating-nodes/build/n8n-node.md) to create and check their package. This helps n8n ensure quality and consistency by: * Generating the expected package file structure * Adding the required metadata and configuration to the `package.json` file * Making it easy to lint your code against n8n's standards * Allowing you to load your node in a local n8n instance for testing +## Node Types + +* The node **MUST** not be an existing node, If your node is an iteration on an existing node create a pull request instead. +* n8n isn't accepting Logic or Flow control nodes at the moment. + ## Package source verification -* Verify that your npm package repository URL matches the expected GitHub (or other platform) repository. +* Verify that your npm package repository URL matches the expected GitHub repository. * Confirm that the package author / maintainer matches between npm and the repository. * Confirm that the git link in npm works and that the repository is public. * Make sure your package has proper documentation (README, usage examples, etc.). * Make sure your package license is MIT. +* Packages should be published from a GitHub action and include [provenance](https://docs.npmjs.com/generating-provenance-statements) ## No external dependencies