Skip to main content

Code of Conduct

This project is governed by the Code of Conduct. By participating, you agree to uphold this code. Report unacceptable behavior to jan@n8n.io.

Before You Contribute

New Nodes

PRs introducing new nodes will be auto-closed unless explicitly requested by the n8n team and aligned with project scope.Instead, consider building your own custom nodes and publishing them to npm.

Typo-Only PRs

Typo-only PRs are not accepted. Combine typo fixes with meaningful code contributions.

Large Changes

For significant architectural changes or new features, please open an issue or discussion first to align with project direction.

Development Workflow

1. Create a Branch

1

Sync with upstream (external contributors)

git fetch upstream
git checkout master
git merge upstream/master
2

Create a feature branch

For n8n team members, use the Linear ticket branch name:
git checkout -b feature/your-feature-name
For external contributors:
git checkout -b your-feature-name

2. Make Your Changes

  1. Navigate to the relevant package (e.g., packages/cli)
  2. Start development mode:
    cd packages/cli
    pnpm dev
    
  3. Make your changes
  4. Add or update tests
  1. Start backend:
    cd packages/cli
    pnpm dev
    
  2. In a new terminal, start frontend:
    cd packages/frontend/editor-ui
    pnpm dev
    
  3. Make your changes
  4. Add or update tests
  5. Ensure all UI text uses i18n
  1. Watch nodes package:
    cd packages/nodes-base
    pnpm dev
    
  2. In a new terminal, start CLI with hot reload:
    cd packages/cli
    N8N_DEV_RELOAD=true pnpm dev
    
  3. Make your changes
  4. Add workflow tests (see examples in packages/nodes-base/nodes/**/test)

3. Testing

1

Run tests locally

# Run tests for your package
cd packages/cli
pnpm test

# Run affected tests only
pnpm test:affected
2

Run typecheck

cd packages/cli
pnpm typecheck
Critical: Always run pnpm typecheck before committing. TypeScript errors will fail CI.
3

Run linter

cd packages/cli
pnpm lint

# Auto-fix issues
pnpm lint:fix
4

Test in production mode

# From root
pnpm build
pnpm start
Verify your changes work in production mode.

4. Commit Your Changes

Follow Conventional Commits format:
git commit -m "feat: add workflow template support"
Commit messages should focus on why, not what. The diff shows what changed - explain why you made the change.

5. Push and Create PR

1

Push your branch

git push origin your-feature-name
2

Create pull request

Go to GitHub and create a pull request from your branch to n8n-io:master.
3

Fill PR template

Follow the PR template and include:
  • Clear description of changes
  • Link to Linear ticket (team members)
  • Link to related GitHub issues
  • Screenshots/videos for UI changes
  • Breaking change notes (if applicable)

PR Title Conventions

Follow n8n’s PR title conventions:
  • feat(package): Description - New feature
  • fix(package): Description - Bug fix
  • refactor(package): Description - Code refactoring
  • perf(package): Description - Performance improvement
  • test(package): Description - Test additions/changes
  • docs(package): Description - Documentation changes
  • ci: Description - CI/CD changes
  • chore: Description - Maintenance tasks
Examples:
  • feat(cli): Add workflow template import
  • fix(editor-ui): Resolve canvas zoom issue
  • refactor(core): Simplify execution context

Coding Standards

TypeScript

Never use any type - use proper types or unknown:
// Bad
function process(data: any) { }

// Good
function process(data: unknown) {
  if (typeof data === 'string') {
    // Type-safe processing
  }
}
Avoid type casting with as - use type guards:
// Bad
const value = data as string;

// Good
function isString(value: unknown): value is string {
  return typeof value === 'string';
}

if (isString(data)) {
  // Type-safe usage
}
Exception: Type casting is acceptable in test code.
No ts-ignore comments - fix the TypeScript error properly:
// Bad
// @ts-ignore
const result = someFunction();

// Good
const result = someFunction() as ExpectedType;
// Or better: fix the function signature

Error Handling

Use modern error classes:
import { UnexpectedError, OperationalError, UserError } from '@n8n/workflow';

// For unexpected errors (bugs)
throw new UnexpectedError('Database connection failed');

// For operational errors (retryable)
throw new OperationalError('API rate limit exceeded');

// For user errors (user action required)
throw new UserError('Invalid workflow configuration');
Deprecated: Do not use ApplicationError - it will be removed.

Frontend Guidelines

All UI text must use i18n:
<!-- Bad -->
<n8n-button>Save Workflow</n8n-button>

<!-- Good -->
<n8n-button>{{ $locale.baseText('workflows.save') }}</n8n-button>
Add translations to packages/@n8n/i18n/locales/en/index.json.
Use CSS variables - never hardcode values:
/* Bad */
.container {
  padding: 16px;
  color: #333333;
}

/* Good */
.container {
  padding: var(--spacing-m);
  color: var(--color-text-dark);
}
data-testid must be a single value:
<!-- Bad -->
<div data-testid="workflow card"></div>

<!-- Good -->
<div data-testid="workflow-card"></div>

Code Reusability

Avoid repetitive code - reuse existing components and logic:
// Bad - duplicating parameter definitions
const operation1Parameters = [
  { name: 'url', type: 'string' },
  { name: 'method', type: 'options' },
];

const operation2Parameters = [
  { name: 'url', type: 'string' },
  { name: 'method', type: 'options' },
];

// Good - reusing shared parameters
const commonHttpParameters = [
  { name: 'url', type: 'string' },
  { name: 'method', type: 'options' },
];

const operation1Parameters = [...commonHttpParameters];
const operation2Parameters = [...commonHttpParameters];

Code Formatting

n8n uses Biome for formatting:
# Format code
pnpm format

# Check formatting
pnpm format:check

Testing Requirements

PRs must include tests:
  • Unit tests for new functionality
  • Workflow tests for nodes (see packages/nodes-base/nodes/**/test)
  • E2E tests for UI changes (if applicable)
PRs without tests will be auto-closed after 14 days.

Writing Tests

// packages/cli/src/services/workflow.service.test.ts
import { WorkflowService } from './workflow.service';
import { mock } from 'jest-mock-extended';

describe('WorkflowService', () => {
  it('should validate workflow before saving', async () => {
    const service = new WorkflowService();
    const workflow = { name: 'Test', nodes: [] };

    await expect(service.save(workflow)).rejects.toThrow('Invalid workflow');
  });
});

PR Review Process

Community PR Guidelines

1

Initial submission

  • Ensure PR follows all guidelines above
  • Include tests and documentation
  • Link related issues
2

Review period

  • Team reviews within 1-2 weeks
  • Address requested changes within 14 days
  • PRs with no response after 14 days will be auto-closed
3

Changes requested

If changes are requested:
  1. Make the requested changes
  2. Push to the same branch
  3. Request re-review
  4. Respond to all review comments
4

Approval and merge

  • Once approved, team will merge
  • Your contribution will be included in the next release

Small PRs Only

Focus on a single feature or fix per PR. Large PRs will be requested to be split into smaller ones.Good PR: Adds credential validation for Notion API Bad PR: Adds 5 new nodes, refactors authentication, and updates documentation

Contributor License Agreement

You must sign the Contributor License Agreement before your PR can be merged. An automated bot will comment on your PR with a link to sign. This uses Indie Open Source - a simple, plain-English CLA.

Additional Resources

Documentation

The n8n documentation repository is at n8n-io/n8n-docs. Contribute documentation improvements there.

Workflow Templates

Submit workflow templates to n8n’s template library. See the n8n Creator Hub for details.

Custom Nodes

Learn about building custom nodes and publishing them to npm. Custom nodes allow you to extend n8n without modifying core.

Getting Help

PR Checklist

Before submitting your PR:
  • Code follows n8n coding standards
  • All tests pass locally
  • Added tests for new functionality
  • Ran pnpm typecheck successfully
  • Ran pnpm lint and fixed all issues
  • Tested in production mode (pnpm build && pnpm start)
  • Updated documentation if needed
  • PR title follows conventions
  • PR description is clear and complete
  • Linked related issues/tickets
  • No ts-ignore comments
  • No hardcoded strings (use i18n for UI text)
  • No any types
  • Small, focused PR (single feature/fix)

Next Steps