agentsclimarketplace

N8n syntax node types

Skill Impertio-Studio/n8n-Claude-Skill-Package/skills/source/n8n-syntax/n8n-syntax-node-types

21 deterministic Claude AI skills for n8n v1.x workflow automation

Install
npx -y skills add Impertio-Studio/n8n-Claude-Skill-Package --skill n8n-syntax-node-types

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when creating custom n8n nodes, defining node properties, implementing execute methods, or building declarative nodes. Prevents incorrect INodeProperties types and malformed displayOptions conditions. Covers INodeType interface, INodeTypeDescription, INodeProperties (22 types), displayOptions with rich conditions, execute() method with IExecuteFunctions, Node base class alternative, versioned nodes, declarative routing, and methods (loadOptions, listSearch, credentialTest, resourceMapping). Keywords: n8n, custom nodes, INodeType, INodeProperties, execute,, create custom node, INodeType, node properties, dropdown options, execute method. displayOptions, declarative routing, versioned nodes, credentialTest.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

16.0 KB, as published. Nobody here has run it

n8n-syntax-node-types

Quick Reference

INodeType Interface Members

MemberSignatureRequiredPurpose
descriptionINodeTypeDescriptionYESNode metadata, properties, credentials
execute(this: IExecuteFunctions) => Promise<INodeExecutionData[][]>For regular nodesProcess input items
trigger(this: ITriggerFunctions) => Promise<ITriggerResponse>For event triggersEmit data on events
poll(this: IPollFunctions) => Promise<INodeExecutionData[][] | null>For polling triggersPeriodically check for data
webhook(this: IWebhookFunctions) => Promise<IWebhookResponseData>For webhook nodesHandle HTTP requests
supplyData(this: ISupplyDataFunctions, itemIndex: number) => Promise<SupplyData>For AI sub-nodesProvide data to AI agents
methods{ loadOptions, listSearch, credentialTest, resourceMapping, actionHandler }NoDynamic methods
webhookMethods{ [name]: { checkExists, create, delete } }NoExternal webhook lifecycle

INodeTypeDescription Key Fields

FieldTypeRequiredNotes
displayNamestringYESHuman-readable name in UI
namestringYESInternal identifier (e.g., 'myNode')
iconstring | { light, dark }No'fa:icon-name' or 'file:icon.svg'
groupNodeGroupType[]YES'input', 'output', 'transform', 'trigger', 'schedule'
versionnumber | number[]YESSupported versions
descriptionstringYESShort description
defaults{ name: string }YESDefault node name
inputsNodeConnectionType[] | ExpressionStringYESInput connections
outputsNodeConnectionType[] | ExpressionStringYESOutput connections
credentialsINodeCredentialDescription[]NoRequired credential types
propertiesINodeProperties[]YESNode parameters
pollingtrueNoMarks node as polling trigger
webhooksIWebhookDescription[]NoWebhook registrations
requestDefaultsHttpRequestOptionsNoDeclarative base URL/headers
usableAsTooltrueNoEnable as AI agent tool
subtitlestringNoDynamic expression for UI subtitle

All 22 Property Types (NodePropertyTypes)

TypeUI ElementDefault Value Type
'boolean'Toggle switchboolean
'button'Action buttonstring
'collection'Group of optional fields{}
'color'Color pickerstring
'dateTime'Date/time pickerstring
'fixedCollection'Group with fixed structure{}
'hidden'Hidden valuestring
'icon'Icon selectorstring
'json'JSON editorstring
'callout'Info/warning calloutstring
'notice'Notice/info textstring
'multiOptions'Multi-select dropdownstring[]
'number'Number inputnumber
'options'Single-select dropdownstring
'string'Text inputstring
'credentialsSelect'Credential selectorstring
'resourceLocator'Resource locator (ID/URL/list)object
'curlImport'cURL importstring
'resourceMapper'Resource field mapperobject
'filter'Filter/condition builderobject
'assignmentCollection'Field assignment collectionobject
'workflowSelector'Workflow selectorstring
'credentials'Credentials propertystring

IExecuteFunctions Key Methods

MethodSignaturePurpose
getInputData(inputIndex?: number) => INodeExecutionData[]Get input items
getNodeParameter(name: string, itemIndex: number) => anyRead parameter value
getCredentials(type: string) => Promise<ICredentialDataDecryptedObject>Get decrypted credentials
continueOnFail() => booleanCheck continue-on-fail setting
executeWorkflow(workflowInfo, inputData?) => Promise<ExecuteWorkflowData>Call sub-workflow
putExecutionToWait(waitTill: Date) => Promise<void>Pause execution until date
sendMessageToUI(message: any) => voidSend message to editor UI
helpers.httpRequest(options) => Promise<any>Make HTTP requests
helpers.getBinaryDataBuffer(itemIndex, propertyName) => Promise<Buffer>Read binary data
helpers.prepareBinaryData(buffer, fileName?, mimeType?) => Promise<IBinaryData>Create binary data
helpers.normalizeItems(items) => INodeExecutionData[]Normalize item format

Critical Warnings

ALWAYS return INodeExecutionData[][] from execute() -- the outer array represents output indices (for multi-output nodes like IF/Switch), the inner array contains items. Single-output nodes return [returnData].

ALWAYS iterate over input items using this.getInputData() and call getNodeParameter(name, i) with the item index i -- parameters can contain expressions that resolve differently per item.

ALWAYS handle continueOnFail() in the catch block of your item loop -- when enabled, push an error item with pairedItem instead of throwing.

NEVER use &str or borrowed types in node parameters -- n8n uses IDataObject (plain objects) for all parameter values. Cast with as string, as number, etc.

NEVER create an execute() method in declarative nodes -- n8n handles HTTP requests automatically based on routing configuration in properties.

NEVER define inputs on trigger nodes -- trigger nodes ALWAYS have inputs: [] (empty array) because they start workflow execution.

NEVER use this binding in the Node base class -- the Node class passes context as a parameter. Use context.getInputData() instead of this.getInputData().

ALWAYS set noDataExpression: true on resource and operation selector properties -- these properties control node behavior and MUST NOT be expression-dependent.


Decision Trees

Which Node Pattern to Use?

Is this a trigger/starting node?
├── YES: Does it respond to HTTP requests?
│   ├── YES → Webhook pattern (webhook() + webhooks config)
│   └── NO: Does it poll an external service?
│       ├── YES → Poll pattern (poll() + polling: true)
│       └── NO → Trigger pattern (trigger() + emit())
└── NO: Is this a simple REST API wrapper?
    ├── YES → Declarative pattern (routing in properties, NO execute())
    └── NO → Programmatic pattern (execute() with custom logic)

Which Property Type to Use?

What data does the user provide?
├── True/false → 'boolean'
├── Free text → 'string' (add rows for textarea, editor for code)
├── A number → 'number' (set minValue/maxValue in typeOptions)
├── One choice from list → 'options'
├── Multiple choices from list → 'multiOptions'
├── A set of optional fields → 'collection'
├── A structured group of fields → 'fixedCollection'
├── Raw JSON → 'json'
├── Date/time → 'dateTime'
├── A color → 'color'
├── Filter conditions → 'filter'
├── Field mapping → 'resourceMapper'
├── Field assignments → 'assignmentCollection'
├── Resource ID/URL/name → 'resourceLocator'
├── Another workflow → 'workflowSelector'
└── Display-only info → 'notice' or 'callout'

Essential Patterns

Pattern 1: Programmatic Node (implements INodeType)

import type {
    IExecuteFunctions,
    INodeExecutionData,
    INodeType,
    INodeTypeDescription,
} from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';

export class MyNode implements INodeType {
    description: INodeTypeDescription = {
        displayName: 'My Node',
        name: 'myNode',
        icon: 'file:myIcon.svg',
        group: ['transform'],
        version: 1,
        description: 'Processes data',
        defaults: { name: 'My Node' },
        inputs: [NodeConnectionTypes.Main],
        outputs: [NodeConnectionTypes.Main],
        properties: [/* see references/methods.md */],
    };

    async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
        const items = this.getInputData();
        const returnData: INodeExecutionData[] = [];

        for (let i = 0; i < items.length; i++) {
            try {
                const value = this.getNodeParameter('myParam', i) as string;
                returnData.push({ json: { result: value } });
            } catch (error) {
                if (this.continueOnFail()) {
                    returnData.push({
                        json: { error: (error as Error).message },
                        pairedItem: { item: i },
                    });
                    continue;
                }
                throw error;
            }
        }

        return [returnData]; // Single output
    }
}

Pattern 2: Node Base Class (context parameter)

import { Node } from 'n8n-workflow';
import type {
    IExecuteFunctions,
    INodeExecutionData,
    INodeTypeDescription,
} from 'n8n-workflow';

export class MyNode extends Node {
    description: INodeTypeDescription = { /* same as above */ };

    async execute(
        context: IExecuteFunctions  // context parameter, NOT this
    ): Promise<INodeExecutionData[][]> {
        const items = context.getInputData();  // Use context, not this
        const returnData: INodeExecutionData[] = [];

        for (let i = 0; i < items.length; i++) {
            const value = context.getNodeParameter('myParam', i) as string;
            returnData.push({ json: { result: value } });
        }

        return [returnData];
    }
}

Pattern 3: Declarative Node (routing, NO execute)

export class ApiNode implements INodeType {
    description: INodeTypeDescription = {
        displayName: 'API Node',
        name: 'apiNode',
        group: ['input'],
        version: 1,
        description: 'Interacts with an API',
        defaults: { name: 'API Node' },
        inputs: [NodeConnectionTypes.Main],
        outputs: [NodeConnectionTypes.Main],
        credentials: [{ name: 'myApi', required: true }],
        requestDefaults: {
            baseURL: 'https://api.example.com',
            headers: { Accept: 'application/json' },
        },
        properties: [
            {
                displayName: 'Operation',
                name: 'operation',
                type: 'options',
                noDataExpression: true,
                options: [
                    {
                        name: 'Get Many',
                        value: 'getAll',
                        action: 'Get many items',
                        routing: {
                            request: { method: 'GET', url: '/items' },
                        },
                    },
                ],
                default: 'getAll',
            },
        ],
    };
    // NO execute() method -- n8n handles requests via routing
}

Pattern 4: displayOptions (Conditional Properties)

// Show 'limit' only when operation is 'getAll' AND returnAll is false
{
    displayName: 'Limit',
    name: 'limit',
    type: 'number',
    default: 50,
    typeOptions: { minValue: 1 },
    displayOptions: {
        show: {
            operation: ['getAll'],
            returnAll: [false],
        },
    },
}

// Rich conditions with operators
{
    displayName: 'Advanced Field',
    name: 'advancedField',
    type: 'string',
    default: '',
    displayOptions: {
        show: {
            '@version': [{ _cnd: { gte: 2 } }],      // Version 2+
            status: [{ _cnd: { not: 'archived' } }],  // Not archived
        },
    },
}

Pattern 5: Versioned Node

import type { IVersionedNodeType, INodeType } from 'n8n-workflow';

export class MyNodeVersioned implements IVersionedNodeType {
    currentVersion = 2;
    description = { /* INodeTypeBaseDescription */ };
    nodeVersions: { [key: number]: INodeType } = {
        1: new MyNodeV1(),
        2: new MyNodeV2(),
    };

    getNodeType(version?: number): INodeType {
        return this.nodeVersions[version ?? this.currentVersion];
    }
}

Pattern 6: methods Object (Dynamic Loading)

methods = {
    loadOptions: {
        async getUsers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
            const credentials = await this.getCredentials('myApi');
            const users = await this.helpers.httpRequest({ /* ... */ });
            return users.map((u: any) => ({ name: u.name, value: u.id }));
        },
    },
    listSearch: {
        async searchUsers(
            this: ILoadOptionsFunctions,
            filter?: string,
            paginationToken?: string,
        ): Promise<INodeListSearchResult> {
            // Return { results: [...], paginationToken?: string }
        },
    },
    credentialTest: {
        async testMyApi(this: ICredentialTestFunctions): Promise<INodeCredentialTestResult> {
            // Return { status: 'OK', message: 'Success' }
            // or { status: 'Error', message: 'Invalid credentials' }
        },
    },
    resourceMapping: {
        async getFields(this: ILoadOptionsFunctions): Promise<ResourceMapperFields> {
            // Return field definitions for resource mapper
        },
    },
};

INodeExecutionData Structure

interface INodeExecutionData {
    json: IDataObject;                     // REQUIRED -- the main data payload
    binary?: IBinaryKeyData;               // Optional binary/file data
    error?: NodeApiError;                  // Error info if item errored
    pairedItem?: IPairedItemData | number; // Source item linking
}

// Binary data keyed by property name
interface IBinaryKeyData {
    [key: string]: IBinaryData;  // e.g., { data: {...}, attachment: {...} }
}

ALWAYS include a json property on every output item -- it is the only required field. Binary data is ALWAYS secondary.


execute() Return Type

The return type INodeExecutionData[][] is a 2D array:

  • Outer array: One entry per output connector (index 0 = first output, index 1 = second output)
  • Inner array: Items for that output
// Single output (most nodes):
return [returnData];

// Two outputs (like IF node):
return [trueItems, falseItems];

// Three outputs:
return [output1Items, output2Items, output3Items];

// Empty output (no items):
return [[]];

Reference Links

Official Sources

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.