n8n-code-javascript — скилл для Claude Code: что делает
Помогает писать и отлаживать JavaScript в нодах Code для n8n, выбирать правильный режим выполнения и заменять цепочки промежуточных узлов.
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript -a claude-codeЧто делает n8n-code-javascript
Скилл проверяет, действительно ли сценарию нужен JavaScript-узел, или задачу решат стандартные ноды n8n вроде Filter или Merge. Он формулирует код для рекурсивных структур и накопительных итогов между элементами.
Внутри заложены правила работы с окружением n8n: обращение к телу вебхука через $json.body и вызовы this.helpers.httpRequest(). Глобальный объект $helpers в песочнице не объявлен и вызовет ошибку. Сторонние библиотеки через require() допускаются только тогда, когда они явно добавлены в переменные окружения инстанса.
Для кастомных инструментов ИИ-агентов (toolCode) скилл не подходит, потому что там действует другой контракт с текстовым выводом.
Какие задачи решает
- рассчитать нарастающий итог по массиву элементов
- обойти вложенное дерево объектов неизвестной глубины через рекурсию
- исправить ошибку обращения к данным вебхука в узле Code
- заменить цепочку из четырёх узлов-трансформеров одним скриптом
Примеры запросов агенту
- Напиши JavaScript для ноды n8n, чтобы посчитать нарастающий итог баланса по всем входящим элементам
- Помоги обойти рекурсивное дерево категорий в Code node n8n
- Проверь этот скрипт для n8n Code node: почему падает вызов $helpers?
Как установить n8n-code-javascript
1Через Skills CLI (Vercel)
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript -a claude-code2Вручную: положить файлы
~/.claude/skills/n8n-code-javascript/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/n8n-code-javascript/
1Через Skills CLI (Vercel)
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript -a codex2Вручную: положить файлы
.agents/skills/n8n-code-javascript/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript -a cursor2Вручную: положить файлы
.cursor/skills/n8n-code-javascript/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install czlonkowski/n8n-skills n8n-code-javascript2Вручную: положить файлы
.github/skills/n8n-code-javascript/SKILL.md1Через Skills CLI (Vercel)
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript -a gemini-cli2Командой платформы
gemini skills install https://github.com/czlonkowski/n8n-skills --path skills/n8n-code-javascriptВручную: положить файлы
.devin/skills/n8n-code-javascript/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
Из того же набора9
Весь набор →Похожие
Вопросы о n8n-code-javascript
Как установить n8n-code-javascript в Claude Code?
Выполните команду npx skills add czlonkowski/n8n-skills --skill n8n-code-javascript -a claude-code. Навык сразу станет доступен агенту.
Что делает n8n-code-javascript?
Скилл помогает писать, проверять и оптимизировать код для узлов Code в n8n, выбирая между режимами обработки всех элементов сразу или по отдельности.
Подходит ли этот скилл для Custom Code Tool в ИИ-агентах n8n?
Нет, для узла @n8n/n8n-nodes-langchain.toolCode используется отдельный скилл n8n-code-tool, так как у него другой контракт: данные приходят в поле query, а на выходе ожидается строка.
Исходный текст
SKILL.md · MIT
---
name: n8n-code-javascript
description: "Write, review, or debug JavaScript in an n8n Code node. Use when a Code node is already in the workflow (editing it, fixing an error, choosing its mode, making it faster), or when a new one is justified: no native node fits (check the job-to-node table in using-n8n-mcp-skills first) and the job is on the closed list — loops or recursion no node expresses, state across runs, parsing no node handles, an allowlisted library, heavy all-items work, or one short node replacing 4+ glue nodes. Covers $input/$json/$node in code, this.helpers, Luxon, SplitInBatches loops, cross-iteration data, pairedItem, per-item performance, and the \"Why Code:\" note. Filtering, totals, dedupe, sorting, joins, file formats and API paging have native nodes (Filter, Summarize, Remove Duplicates, Sort, Merge, Extract From File, HTTP Request): see n8n-node-configuration. EXCEPTION — for the AI-agent-callable Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode), use n8n-code-tool; it has a different runtime contract."
---
# JavaScript Code Node
Expert guidance for writing JavaScript code in n8n Code nodes.
---
## Before you write a Code node
A new Code node has to pass this gate first:
1. **Is there a native node for the job?** Check the job-to-node table in `using-n8n-mcp-skills`: Filter, IF / Switch,
Summarize, Aggregate, Split Out, Merge, Compare Datasets, Remove Duplicates, Sort + Limit, Date & Time, XML / HTML /
Extract From File / Convert To File, HTTP Request (pagination, batching) and Crypto cover most reaches for Code.
Their configs are in `n8n-node-configuration` → NATIVE_NODES.md.
2. **Would a short expression in that node do?** One expression, no function body — the helper methods (`.pluck()`,
`.sum()`, `.unique()`, `$ifEmpty()`, `.diffTo()`) are in `n8n-expression-syntax` and, on n8n-mcp 2.97.0+, in
`tools_documentation({topic: "expression_helpers"})`. Several statements inside `{{ }}` count as code, so they belong
here rather than in an Edit Fields field.
3. **Is the job on the closed list?** Loops or recursion no node expresses, state across runs
(`$getWorkflowStaticData`), parsing no node handles, an allowlisted library, heavy all-items work (thousands of items,
stated or measured), or one short Code node (~15 lines) replacing 4+ glue nodes that only reshape data.
If it passes, write the Code node and give it a note, so the next reader (and the review hooks) can see why:
```json
{ "name": "Flatten category tree", "type": "n8n-nodes-base.code", "notes": "Why Code: Split Out considered — the tree has arbitrary depth (recursion)", "notesInFlow": true }
```
Editing or debugging a Code node that is already there doesn't need the gate, but if the node does a native-node job,
say so and offer the native replacement.
---
## Quick Start
```javascript
// Basic template for Code nodes
const items = $input.all();
// Process data
const processed = items.map(item => ({
json: {
...item.json,
processed: true,
timestamp: new Date().toISOString()
}
}));
return processed;
```
### Essential Rules
1. **Choose "Run Once for All Items" mode** (recommended for most use cases)
2. **Access data**: `$input.all()`, `$input.first()`, or `$input.item`
3. **Return `[{json: {...}}]`** — the canonical, mode-portable form. In *Run Once for All Items* mode n8n also auto-wraps a bare `return {…}` object, so that runs too; what genuinely fails is returning a primitive (string/number) or `null`.
4. **CRITICAL**: Webhook data is under `$json.body` (not `$json` directly)
5. **Built-ins available**: `this.helpers.httpRequest()` (no auth — the bare `$helpers` global is **undefined** in the task-runner sandbox, so `$helpers.httpRequest()` throws `ReferenceError: $helpers is not defined`), DateTime (Luxon), $jmespath(). **Not available**: `this.helpers.httpRequestWithAuthentication` (deny-listed), $env (when N8N_BLOCK_ENV_ACCESS_IN_NODE=true), require() (unless allowlisted). For anything beyond a trivial unauthenticated GET (auth, pagination, retries), prefer the **HTTP Request node** and keep Code nodes for pure logic.
6. **Instance-allowlisted libraries**: Self-hosted instances can allowlist modules via `N8N_RUNNERS_ALLOWED_BUILT_IN_MODULES` and `N8N_RUNNERS_ALLOWED_EXTERNAL_MODULES` (legacy: `NODE_FUNCTION_ALLOW_BUILTIN` / `NODE_FUNCTION_ALLOW_EXTERNAL`). If the user says their instance allows specific modules (e.g. `axios`, `lodash`, `crypto`), use them via `require()` — don't refuse. If unsure, ask or default to built-ins only.
7. **Wrong skill?** If you're writing code for a **Custom Code Tool** attached to an AI Agent (`@n8n/n8n-nodes-langchain.toolCode`), stop — that node has a different contract (input via `query`, must return a string, no `$input`/`$helpers`). Use the **n8n-code-tool** skill.
---
## Mode Selection Guide
The Code node offers two execution modes. Choose based on your use case:
### Run Once for All Items (Recommended - Default)
**Use this mode for:** 95% of use cases
- **How it works**: Code executes **once** regardless of input count
- **Data access**: `$input.all()` or `items` array
- **Best for**: logic that needs every item at once and passed the gate above
- **Performance**: Faster for multiple items (single execution)
```javascript
// Example: running balance — each item depends on the ones before it,
// which no native node expresses (Summarize gives one total per group, not a running one)
let balance = 0;
return $input.all().map(item => {
balance += item.json.amount || 0;
return { json: { ...item.json, balance } };
});
```
**When to use:**
- ✅ Each item depends on earlier items (running totals, sessionizing events, gap detection)
- ✅ Multi-pass algorithms or recursion over nested data of unknown depth
- ✅ Heavy transforms over thousands of items where one node beats a long chain (measured)
Native first: totals, averages and counts → **Summarize**; sorting or ranking → **Sort + Limit**; deduplication →
**Remove Duplicates**; items into one array → **Aggregate**; joining two lists → **Merge**.
### Run Once for Each Item
**Use this mode for:** Specialized cases only
- **How it works**: Code executes **separately** for each input item
- **Data access**: `$input.item` or `$item`
- **Best for**: Item-specific logic, independent operations, per-item validation
- **Performance**: Slower for large datasets (multiple executions)
```javascript
// Example: Add processing timestamp to each item
const item = $input.item;
return [{
json: {
...item.json,
processed: true,
processedAt: new Date().toISOString()
}
}];
```
**When to use:**
- ✅ Each item needs independent API call
- ✅ Per-item validation with different error handling
- ✅ Item-specific transformations based on item properties
- ✅ When items must be processed separately for business logic
**Decision Shortcut:**
- **Need to look at multiple items?** → Use "All Items" mode
- **Each item completely independent?** → Use "Each Item" mode
- **Not sure?** → Use "All Items" mode (you can always loop inside)
### Why "All Items" is faster — the per-item boundary
Mode choice is the single biggest performance lever in a Code node. Each *per-item* execution context costs a setup tax (measured on n8n 2.x, small records):
| What runs per item | Approx. cost |
|---|---|
| Code **All Items** (one run for the whole set) | ~0.02 ms/item |
| Expression in any node (IF / Set / etc.) | ~0.2 ms/item |
| Code **Each Item** (a full sandbox per item) | ~0.6 ms/item — ~25–30× All Items |
So `Run Once for Each Item` over 10k items is ~6 s of pure overhead vs ~0.2 s in `Run Once for All Items`. Use Each Item only when an item genuinely needs isolating (independent error handling, or a per-item API call you can't batch); otherwise loop *inside* one All Items node. Expression complexity itself is essentially free (~90% of the cost is the per-item context, not your code) and every node→node hop re-copies all items — so reduce the *number* of per-item boundaries, don't micro-optimize each one.
On top of the per-item cost, every Code node run pays a fixed hand-off to the task runner. In the default internal mode the runner stops after 15 s idle (`N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT`), so a workflow that runs now and then pays a cold start of hundreds of milliseconds on most runs. Native transform nodes process all items in one in-process call and skip that hand-off.
**What this means for node choice.** Most workflows are I/O-bound, and below a few hundred items none of these costs matter: choose by readability, which means native nodes first. Performance becomes the deciding argument only for heavy all-items work — thousands of items per run, transform work rather than I/O dominating, stated by the user or measured. Then one All Items Code node can beat a long chain of nodes, and the reason goes in its `Why Code:` note. These figures are the pack's one measured reference; the other skills point here instead of repeating them.
**See**: [DATA_ACCESS.md](DATA_ACCESS.md) → "Mode Performance" for the corollaries, hop costs, and scale check.
---
## Data Access Patterns
Four ways to pull data from upstream nodes. Note `$node["Name"]` and `$('Name')` need `.first().json` or `.all()` — never `.json` directly.
```javascript
const allItems = $input.all(); // 1. All items — batch ops, aggregation (most common)
const data = $input.first().json; // 2. First item — single objects, API responses
const item = $input.item; // 3. Current item — "Each Item" mode ONLY (undefined otherwise)
const other = $node["Webhook"].json; // 4. Named node — combine data across nodes
```
Always access fields via `.json` (e.g. `item.json.name`, not `item.name`), and prefer the explicit `$input.first().json.field` over a bare `$json.field`.
**See**: [DATA_ACCESS.md](DATA_ACCESS.md) for the full guide — every pattern with examples, a decision tree, and the common mistakes (mutating originals, missing length checks, `$input.item` in the wrong mode).
---
## Critical: Webhook Data Structure
**MOST COMMON MISTAKE**: Webhook data is nested under `.body`
```javascript
// ❌ WRONG - Will return undefined
const name = $json.name;
const email = $json.email;
// ✅ CORRECT - Webhook data is under .body
const name = $json.body.name;
const email = $json.body.email;
// Or with $input
const webhookData = $input.first().json.body;
const name = webhookData.name;
```
**Why**: Webhook node wraps all request data under `body` property. This includes POST data, query parameters, and JSON payloads.
**See**: [DATA_ACCESS.md](DATA_ACCESS.md) for full webhook structure details
---
## Return Format Requirements
**Canonical form**: `[{json: {...}}]` — an array of objects each with a `json` property. It is unambiguous and works identically in both execution modes, so make it your default.
In *Run Once for All Items* mode n8n auto-normalizes looser shapes on the way out: a single bare object, or an array of bare objects, gets wrapped under `json` for you. So `return {foo: 1}` runs. What has nothing to wrap — and therefore genuinely fails at runtime with "Code doesn't return items properly" — is a primitive (string/number/boolean) or `null`/`undefined`. (n8n-mcp ≥ 2.63.0 no longer flags a bare-object return as an error; it reflects this auto-wrap behavior.)
### Correct Return Formats
```javascript
// ✅ Single result
return [{
json: {
field1: value1,
field2: value2
}
}];
// ✅ Multiple results
return [
{json: {id: 1, data: 'first'}},
{json: {id: 2, data: 'second'}}
];
// ✅ Transformed array
const transformed = $input.all()
.filter(item => item.json.valid)
.map(item => ({
json: {
id: item.json.id,
processed: true
}
}));
return transformed;
// ✅ Empty result (when no data to return)
return [];
// ✅ Conditional return
if (shouldProcess) {
return [{json: processedData}];
} else {
return [];
}
```
### Non-Canonical Returns (auto-wrapped — prefer the canonical form)
```javascript
// ⚠️ Auto-wrapped in All Items mode → [{json: {field: value}}]. Runs, but prefer the array form.
return {
json: {field: value}
};
// ⚠️ Auto-wrapped → [{json: {field: value}}]. Runs, but add the json wrapper for clarity.
return [{field: value}];
// ✅ Fine — input items already carry a json property, so returning them unchanged is a valid passthrough
return $input.all();
```
### Genuinely Broken Returns
```javascript
// ❌ FAILS: primitive — n8n errors "Code doesn't return items properly"
return "processed";
// ❌ FAILS: null / undefined — nothing to pass to the next node
return null;
```
**Why it matters**: The canonical `[{json: {...}}]` is unambiguous and behaves the same in both modes. n8n auto-normalizes bare objects and arrays-of-objects in All Items mode, but a primitive or `null` return has nothing to wrap and stops execution.
**See**: [ERROR_PATTERNS.md](ERROR_PATTERNS.md) #3 for detailed error solutions
---
## Common Patterns Overview
The most useful Code node shapes from production workflows, for when Code passed the gate. Several of them have a native equivalent (totals → Summarize, top-N → Sort + Limit, JSON comparison → Compare Datasets, string aggregation → Aggregate or Summarize `concatenate`); each pattern in the library opens with its native alternative. The full library covers 10 patterns: multi-source aggregation, regex filtering, markdown/structured-text parsing, JSON comparison, CRM/form transformation, release processing, array transformation with computed fields, Slack Block Kit formatting, top-N ranking, and string-aggregation reporting — each with variations.
**See**: [COMMON_PATTERNS.md](COMMON_PATTERNS.md) for the 10 detailed production patterns (and the Best Practices section: validate input, try-catch, filter-early, array methods over loops, console.log debugging).
---
## Error Prevention - Top Mistakes
The recurring Code node failures, in rough frequency order:
1. **Empty code / missing return** — always end with `return [...]`, and make sure *every* branch returns.
2. **Expression syntax as code** — don't write `{{ }}` where JavaScript belongs (`return {{ $json.x }}` is a syntax error). Use `` `${$json.field}` `` or `$input.first().json.field`. `{{ }}` *inside a string literal* is fine — it's just literal text n8n won't evaluate.
3. **Return shape** — prefer `return [{json:{...}}]`. A bare `return {…}` auto-wraps in All Items mode, but returning a primitive (string/number) or `null` is what actually fails.
4. **Missing null checks** — use optional chaining: `item.json?.user?.email || 'fallback'`.
5. **Webhook body nesting** — `$json.email` is undefined; use `$json.body.email`.
6. **Auth helpers blocked** (`httpRequestWithAuthentication`) and `$env` blocked — route secrets through credentials/HTTP Request node, not the Code node sandbox.
**See**: [ERROR_PATTERNS.md](ERROR_PATTERNS.md) for the comprehensive guide — each error with wrong/right code, escaping rules, the sandbox restrictions (Errors #6–#7), a prevention checklist, and a quick error-message lookup table.
---
## Built-in Functions & Helpers
```javascript
// HTTP requests (no auth — see sandbox note below)
const res = await this.helpers.httpRequest({ method: 'GET', url: 'https://api.example.com/data' });
// DateTime (Luxon): now, formatting, arithmetic
const now = DateTime.now();
const formatted = now.toFormat('yyyy-MM-dd');
const tomorrow = now.plus({ days: 1 });
// $jmespath() — query JSON structures
const adults = $jmespath($input.first().json, 'users[?age >= `18`]');
// $getWorkflowStaticData() — data that persists across executions
```
**Sandbox (since n8n v2.0, JsTaskRunnerSandbox):** the accessor is `this.helpers.httpRequest()` — the bare `$helpers` global is **undefined** here (`$helpers.httpRequest()` throws `ReferenceError`). Inside a nested async function where `this` is lost, call it as `await fn.call(this, ...)`. `this.helpers.httpRequestWithAuthentication` and `this.helpers.requestWithAuthenticationPaginated` are deny-listed (→ `UnsupportedFunctionError`); for authenticated calls use an **HTTP Request node** with the credential (preferred), a sub-workflow, or a manual `Authorization: Bearer ${token}` header on `this.helpers.httpRequest()` only when the token already flows through the workflow as data. `$env` is blocked when `N8N_BLOCK_ENV_ACCESS_IN_NODE=true`; `require()` works only for allowlisted modules. `Buffer`, `URL`, and standard JS globals (Math, JSON, Object, Array) always work.
**See**: [BUILTIN_FUNCTIONS.md](BUILTIN_FUNCTIONS.md) for the complete reference — full httpRequest options, all DateTime/Luxon operations, JMESPath patterns, static-data use cases, and the sandbox-restriction details.
---
## Best Practices
- **Validate input first** — guard for empty arrays / missing `.json` before processing.
- **Try-catch risky work** (HTTP calls) and return an error object instead of crashing.
- **Prefer array methods** (`filter`/`map`/`reduce`) over manual loops.
- **Filter early, transform late** — shrink the dataset before expensive work.
- **Descriptive names** and `console.log()` for debugging (output goes to the browser console).
**See**: [COMMON_PATTERNS.md](COMMON_PATTERNS.md) → "Best Practices" for code examples of each.
---
## Production Gotchas
Hard-won lessons from real deployments — summarized here, with code in [DATA_ACCESS.md](DATA_ACCESS.md) → "Production Gotchas":
- **SplitInBatches outputs are counterintuitive**: `main[0]` = **done** (fires once, after all batches), `main[1]` = **each batch** (the loop body). Add a **Limit 1** node after the done output as a safety.
- **Iteration count is the cost**: each loop iteration re-runs the whole body through the engine (~0.8 ms overhead each). `batchSize: 1` is the loop equivalent of *Each Item* — use the largest batch your real constraint (rate limit, page size, memory) allows, or don't loop at all.
- **Cross-iteration accumulation (CRITICAL)**: after the loop, `$('Node Inside Loop').all()` returns ONLY the last iteration's items. Accumulate via `$getWorkflowStaticData('global')` (reset before, push inside, read after).
- **pairedItem**: when emitting items that don't map 1:1 to input, set `pairedItem: { item: i }` or downstream Set nodes fail with `paired_item_no_info`.
- **Node reference syntax**: `$('Node').first().json` or `$('Node').all()` — never `.json` directly on the reference.
- **Float precision**: compare currency at the cent level — `Math.round(a*100) !== Math.round(b*100)` — to avoid false positives from float noise.
---
## When to Use Code Node
Code is the last rung, after the service's own node, a native node for the job, and a short expression inside that node.
The gate at the top of this skill is the test; this is the closed list it checks against:
| Code is right for | Example | Not Code |
|---|---|---|
| Loops or recursion no node expresses | flatten a tree of unknown depth; multi-pass matching | one level of nesting → Split Out |
| State across runs | counters or cursors in `$getWorkflowStaticData` | "only new items" → Remove Duplicates across executions |
| Parsing no node handles | fixed-width records, a custom log format | CSV / XLSX / PDF / XML / HTML → Extract From File, XML, HTML |
| An allowlisted library | `require('some-lib')` the instance allows | hashing / HMAC / UUID → Crypto |
| Heavy all-items work | thousands of items, transform-bound, stated or measured | a few hundred items → native nodes |
| One short node replacing 4+ glue nodes | ~15 lines that would otherwise be a Set → Split Out → Set → Aggregate chain that only reshapes data | a chain with real routing or I/O in it |
Not on the list, so not Code: filtering (Filter), routing (IF / Switch), totals and counts (Summarize), top-N (Sort + Limit),
dedupe (Remove Duplicates), joins (Merge), diffs (Compare Datasets), dates (Date & Time or a Luxon expression), API calls
and paging (HTTP Request), crypto and XML (Crypto, XML).
Every Code node that stays carries the note `Why Code: <native node considered> — <reason>` (set `notes`, and
`notesInFlow: true` to show it on the canvas). The create/update hooks remind you when a Code node has no such note.
---
## Integration with Other Skills
### Works With:
**n8n Expression Syntax**:
- Expressions use `{{ }}` syntax in other nodes
- Code nodes use JavaScript directly (no `{{ }}`)
- When to use expressions vs code
**n8n MCP Tools Expert**:
- How to find Code node: `search_nodes({query: "code"})`
- Get configuration help: `get_node({nodeType: "nodes-base.code"})`
- Validate code: `validate_node({nodeType: "nodes-base.code", config: {...}})`
**n8n Node Configuration**:
- Mode selection (All Items vs Each Item)
- Language selection (JavaScript vs Python)
- Understanding property dependencies
**n8n Workflow Patterns**:
- Code nodes in transformation step
- Webhook → Code → API pattern
- Error handling in workflows
**n8n Validation Expert**:
- Validate Code node configuration
- Handle validation errors
- Auto-fix common issues
---
## Quick Reference Checklist
Before deploying Code nodes, verify:
- [ ] **Passed the gate** - No native node fits; `notes` starts with `Why Code:`
- [ ] **Code is not empty** - Must have meaningful logic
- [ ] **Return statement exists** - Returns items, not a primitive/`null`
- [ ] **Canonical return format** - Each item: `{json: {...}}` (bare objects auto-wrap, but be explicit)
- [ ] **Data access correct** - Using `$input.all()`, `$input.first()`, or `$input.item`
- [ ] **No `{{ }}` written as code** - Use JavaScript template literals: `` `${value}` ``
- [ ] **Error handling** - Guard clauses for null/undefined inputs
- [ ] **Webhook data** - Access via `.body` if from webhook
- [ ] **Mode selection** - "All Items" for most cases
- [ ] **Performance** - Prefer map/filter over manual loops
- [ ] **Output consistent** - All code paths return same structure
---
## Additional Resources
### Related Files
- [DATA_ACCESS.md](DATA_ACCESS.md) - Comprehensive data access patterns
- [COMMON_PATTERNS.md](COMMON_PATTERNS.md) - 10 production-tested patterns
- [ERROR_PATTERNS.md](ERROR_PATTERNS.md) - Top 5 errors and solutions
- [BUILTIN_FUNCTIONS.md](BUILTIN_FUNCTIONS.md) - Complete built-in reference
### n8n Documentation
- Code Node Guide: https://docs.n8n.io/code/code-node/
- Built-in Methods: https://docs.n8n.io/code-examples/methods-variables-reference/
- Luxon Documentation: https://moment.github.io/luxon/
---
**Ready to write JavaScript in n8n Code nodes!** Start with simple transformations, use the error patterns guide to avoid common mistakes, and reference the pattern library for production-ready examples.
© czlonkowski · MIT · czlonkowski/n8n-skills