This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is an n8n community node package forked from the n8n node starter repository, focused on developing nodes for Cloudflare services including R2 (object storage), KV (key-value storage), Queues (message queuing), D1 (serverless SQL database), and AI modules.
# Install dependencies
npm install
# Build the project (compiles TypeScript and copies icons)
npm run build
# Development mode (watch for TypeScript changes)
npm run dev
# Lint the code
npm run lint
# Fix linting issues
npm run lintfix
# Format code with Prettier
npm run format
# Run before publishing (build + lint with prepublish config)
npm run prepublishOnlycredentials/- Contains credential type definitions for authenticating with Cloudflare servicesnodes/- Contains all the custom n8n node implementations for Cloudflare services
These are the two main folders where all the custom n8n package code lives.
- Nodes are located in
nodes/[NodeName]/[NodeName].node.ts - Each node implements the
INodeTypeinterface fromn8n-workflow - Nodes must be registered in
package.jsonundern8n.nodes - Icons (.svg or .png) should be placed alongside the node file
- Use
requestDefaultsfor API base configuration
Important: Be very careful with the naming of files and classes. Everything must match exactly:
- Folder name:
nodes/[NodeName] - File name:
[NodeName].node.ts - Class name:
[NodeName] - Registration in
package.jsonmust use the exact same naming
- Credentials are in
credentials/[ServiceName]Api.credentials.ts - Implement
ICredentialTypeinterface - Must be registered in
package.jsonundern8n.credentials - Include
authenticateproperty for request authentication - Add
testproperty for credential validation
- TypeScript compiles to
dist/directory - Gulp task copies icons to dist structure
- Only
dist/folder is published to npm - Source maps and declarations are generated
- Support all REST operations (list, get, create, delete)
- Option to create bucket if it doesn't exist
- Handle private/public bucket configuration
- Note: R2 buckets are private by default
- CRUD operations for serverless SQL database
- Similar to existing Supabase/SQL database nodes
- Handle D1-specific connection patterns
- Integrate with Cloudflare AI services
- Support completions, image generation, and transcription
- Handle multiple model options
- List: Lists all KV namespaces in the account
- Create: Creates a new KV namespace with a title
- Delete: Deletes a KV namespace by ID
- Get: Retrieves a single value by key (with metadata support)
- Set: Stores a value with optional expiration, TTL, and metadata
- Delete: Deletes a single key-value pair
- List Keys: Lists all keys with optional prefix filtering and pagination
- Get Multiple: Retrieves multiple values by comma-separated keys
- Set Multiple: Bulk sets multiple key-value pairs with individual settings
- Delete Multiple: Bulk deletes multiple keys
- Metadata support for storing arbitrary JSON with each key-value pair
- TTL and absolute expiration time support
- Proper URL encoding for special characters in keys
- Bulk operations for efficiency
- Cursor-based pagination for listing keys
- Prefix filtering capabilities
- List: Lists all queues in the account
- Create: Creates a new queue with configurable settings
- Update: Updates queue settings
- Delete: Deletes a queue
- Get Info: Retrieves information about a specific queue
- Send: Sends a single message with optional delay
- Send Batch: Sends multiple messages in a single request
- Pull: Pulls messages with configurable batch size and visibility timeout
- Acknowledge: Acknowledges processed messages by lease IDs
- Retry: Retries failed messages with optional delay
- Delivery delay for messages
- Message retention period (default: 4 days)
- Maximum retry attempts
- Dead letter queue configuration
- Polling-based message consumption
- Auto-acknowledgment option for successful messages
- Exponential backoff retry logic (capped at 5 minutes)
- Configurable polling interval (minimum 5 seconds)
- Batch message pulling (1-100 messages)
- Visibility timeout configuration
- Manual trigger support for testing
- Graceful error handling and recovery
- Use
displayNamefor UI andnamefor internal reference - Implement
resourceandoperationpattern for organizing actions - Properties can be separated into description files for clarity
- Use
typeOptions: { password: true }for sensitive credential fields - Include
usableAsTool: truefor nodes that can be used as tools
When creating or modifying nodes, use the "review loop" to verify your implementation:
- Double-check naming consistency:
Check that the names between folder, file, class and package.json registration are consistent and follow the n8n naming convention required to be able to be installed and used in n8n.
- Validate implementation details:
- Use subagents to verify code correctness and safety
- When uncertain about n8n node implementation patterns, use the REF mcp to get n8n documentation
- Perform web searches for specific implementation areas when needed
Example validation prompt: "For my custom n8n node I was asked to implement [task definition], I wrote the following code: [code snippet]. Will the code work correctly, is it safe? If you have conflicting knowledge on the correct implementation of a custom n8n node use the REF mcp to get documentation about n8n or do a websearch for the specific area"
When working with Cloudflare APIs, implement enhanced error handling to extract meaningful error messages:
} catch (error: any) {
// Extract Cloudflare API error message
let errorMessage = error.response?.data?.errors?.[0]?.message || error.message;
if (this.continueOnFail()) {
returnData.push({
json: {
error: errorMessage,
originalError: error.message,
httpCode: error.httpCode,
},
pairedItem: { item: i },
});
continue;
}
// Create enhanced error for throw
const enhancedError = new Error(errorMessage);
(enhancedError as any).httpCode = error.httpCode;
(enhancedError as any).originalError = error.message;
throw enhancedError;
}For operations with known failure patterns, add specific error handling:
// Example: R2 bucket deletion 409 error
if (error.status === 409 || error.httpCode === '409' || error.message?.includes('409')) {
throw new Error(`Cannot delete bucket '${bucketName}': Bucket must be completely empty before deletion. Please ensure all objects, including hidden files and incomplete multipart uploads, are removed first.`);
}When multiple resources use similar parameters, ensure unique naming or proper displayOptions:
// Bad: Both bucket and object operations use 'bucketName'
// Good: Use specific displayOptions to avoid conflicts
{
displayName: 'Bucket Name',
name: 'bucketName',
displayOptions: {
show: {
resource: ['object'],
operation: ['upload', 'download', 'delete', 'list'],
},
hide: {
operation: ['copy'], // Explicitly hide for operations with different parameters
},
},
}When implementing expiration functionality, clearly distinguish between absolute and relative time:
- Expiration: Absolute UNIX timestamp (seconds since epoch)
- TTL: Relative time in seconds from now
- Always include clear descriptions and realistic placeholder values
- Document mutual exclusivity when both options are available
- R2 Bucket Deletion: Requires completely empty buckets (no objects, hidden files, or incomplete uploads)
- KV Namespaces: Duplicate names not allowed within same account
- Queue Operations: Requires paid Workers plan for most operations
- API Rate Limits: Implement appropriate error handling for 429 responses