n8n-nodes-blog-post 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # n8n Blog Post Node
2
+
3
+ A custom n8n node for posting blog content to the kepha14.dev API.
4
+
5
+ ## Features
6
+
7
+ - Post blog content with all required fields
8
+ - Support for optional fields (excerpt, cover image, tags, category, SEO metadata)
9
+ - Bearer token authentication
10
+ - Error handling with continue on fail option
11
+
12
+ ## Installation
13
+
14
+ 1. Install dependencies:
15
+ ```bash
16
+ npm install
17
+ ```
18
+
19
+ 2. Build the node:
20
+ ```bash
21
+ npm run build
22
+ ```
23
+
24
+ 3. Link the package to n8n:
25
+ ```bash
26
+ npm link
27
+ ```
28
+
29
+ 4. In your n8n installation directory, link the package:
30
+ ```bash
31
+ npm link n8n-nodes-blog-post
32
+ ```
33
+
34
+ 5. Restart n8n to load the custom node.
35
+
36
+ ## Usage
37
+
38
+ ### Setting Up Credentials
39
+
40
+ Before using the Blog Post node, you need to create credentials:
41
+
42
+ 1. In n8n, go to **Credentials** → **Add Credential**
43
+ 2. Search for **Blog API** and select it
44
+ 3. Fill in the following fields:
45
+ - **API URL**: The endpoint URL
46
+ - **Secret**: Your Bearer token for API authentication
47
+ 4. Save the credentials
48
+
49
+ ### Using the Node
50
+
51
+ The Blog Post node allows you to:
52
+ - Set blog post title and slug (required)
53
+ - Add full content (required)
54
+ - Optionally add excerpt, cover image, tags, category
55
+ - Set SEO metadata (meta title, meta description)
56
+ - Specify author email
57
+ - Configure published status
58
+
59
+ ## Node Parameters
60
+
61
+ ### Required Fields
62
+ - **Title**: The title of the blog post
63
+ - **Slug**: URL-friendly slug for the blog post
64
+ - **Content**: Full blog post content
65
+ - **Credentials**: Blog API credentials (configured separately)
66
+
67
+ ### Optional Fields
68
+ - **Excerpt**: Short excerpt or summary
69
+ - **Cover Image URL**: URL of the cover image
70
+ - **Published**: Whether the blog post should be published (default: true)
71
+ - **Tags**: Array of tags for the blog post
72
+ - **Category**: Category of the blog post
73
+ - **Meta Title**: SEO meta title
74
+ - **Meta Description**: SEO meta description
75
+ - **Author Email**: Email of the author
76
+
77
+ ## Credentials
78
+
79
+ The node requires **Blog API** credentials with:
80
+ - **API URL**: The API endpoint URL (e.g., `)
81
+ - **Secret**: Bearer token for authentication
82
+
83
+ ## Development
84
+
85
+ ```bash
86
+ # Watch mode for development
87
+ npm run dev
88
+
89
+ # Build for production
90
+ npm run build
91
+
92
+ # Lint code
93
+ npm run lint
94
+
95
+ # Format code
96
+ npm run format
97
+ ```
98
+
99
+ ## License
100
+
101
+ MIT
102
+
@@ -0,0 +1,7 @@
1
+ import { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class BlogApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BlogApi = void 0;
4
+ class BlogApi {
5
+ constructor() {
6
+ this.name = 'blogApi';
7
+ this.displayName = 'Blog API';
8
+ this.documentationUrl = '';
9
+ this.properties = [
10
+ {
11
+ displayName: 'API URL',
12
+ name: 'url',
13
+ type: 'string',
14
+ default: '',
15
+ required: true,
16
+ description: 'The API endpoint URL for blog posts',
17
+ },
18
+ {
19
+ displayName: 'Secret',
20
+ name: 'secret',
21
+ type: 'string',
22
+ typeOptions: {
23
+ password: true,
24
+ },
25
+ default: '',
26
+ required: true,
27
+ description: 'Bearer token for API authentication',
28
+ },
29
+ ];
30
+ }
31
+ }
32
+ exports.BlogApi = BlogApi;
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class BlogPost implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BlogPost = void 0;
4
+ class BlogPost {
5
+ constructor() {
6
+ this.description = {
7
+ displayName: 'Blog Post',
8
+ name: 'blogPost',
9
+ icon: 'file:blog.svg',
10
+ group: ['transform'],
11
+ version: 1,
12
+ description: 'Post blog content to kepha14.dev API',
13
+ defaults: {
14
+ name: 'Blog Post',
15
+ },
16
+ inputs: ['main'],
17
+ outputs: ['main'],
18
+ credentials: [
19
+ {
20
+ name: 'blogApi',
21
+ required: true,
22
+ },
23
+ ],
24
+ properties: [
25
+ {
26
+ displayName: 'Title',
27
+ name: 'title',
28
+ type: 'string',
29
+ default: '',
30
+ required: true,
31
+ description: 'The title of the blog post',
32
+ },
33
+ {
34
+ displayName: 'Slug',
35
+ name: 'slug',
36
+ type: 'string',
37
+ default: '',
38
+ required: true,
39
+ description: 'URL-friendly slug for the blog post',
40
+ },
41
+ {
42
+ displayName: 'Content',
43
+ name: 'content',
44
+ type: 'string',
45
+ typeOptions: {
46
+ rows: 5,
47
+ },
48
+ default: '',
49
+ required: true,
50
+ description: 'Full blog post content',
51
+ },
52
+ {
53
+ displayName: 'Excerpt',
54
+ name: 'excerpt',
55
+ type: 'string',
56
+ typeOptions: {
57
+ rows: 3,
58
+ },
59
+ default: '',
60
+ description: 'Short excerpt or summary of the blog post',
61
+ },
62
+ {
63
+ displayName: 'Cover Image URL',
64
+ name: 'coverImage',
65
+ type: 'string',
66
+ default: '',
67
+ description: 'URL of the cover image',
68
+ },
69
+ {
70
+ displayName: 'Published',
71
+ name: 'published',
72
+ type: 'boolean',
73
+ default: true,
74
+ description: 'Whether the blog post should be published',
75
+ },
76
+ {
77
+ displayName: 'Tags',
78
+ name: 'tags',
79
+ type: 'string',
80
+ typeOptions: {
81
+ multipleValues: true,
82
+ },
83
+ default: [],
84
+ description: 'Tags for the blog post',
85
+ },
86
+ {
87
+ displayName: 'Category',
88
+ name: 'category',
89
+ type: 'string',
90
+ default: '',
91
+ description: 'Category of the blog post',
92
+ },
93
+ {
94
+ displayName: 'Meta Title',
95
+ name: 'metaTitle',
96
+ type: 'string',
97
+ default: '',
98
+ description: 'SEO meta title',
99
+ },
100
+ {
101
+ displayName: 'Meta Description',
102
+ name: 'metaDescription',
103
+ type: 'string',
104
+ typeOptions: {
105
+ rows: 3,
106
+ },
107
+ default: '',
108
+ description: 'SEO meta description',
109
+ },
110
+ {
111
+ displayName: 'Author Email',
112
+ name: 'authorEmail',
113
+ type: 'string',
114
+ default: '',
115
+ description: 'Email of the author',
116
+ },
117
+ ],
118
+ };
119
+ }
120
+ async execute() {
121
+ const items = this.getInputData();
122
+ const returnData = [];
123
+ const credentials = await this.getCredentials('blogApi');
124
+ for (let i = 0; i < items.length; i++) {
125
+ try {
126
+ const title = this.getNodeParameter('title', i);
127
+ const slug = this.getNodeParameter('slug', i);
128
+ const content = this.getNodeParameter('content', i);
129
+ const excerpt = this.getNodeParameter('excerpt', i);
130
+ const coverImage = this.getNodeParameter('coverImage', i);
131
+ const published = this.getNodeParameter('published', i);
132
+ const tags = this.getNodeParameter('tags', i);
133
+ const category = this.getNodeParameter('category', i);
134
+ const metaTitle = this.getNodeParameter('metaTitle', i);
135
+ const metaDescription = this.getNodeParameter('metaDescription', i);
136
+ const authorEmail = this.getNodeParameter('authorEmail', i);
137
+ const body = {
138
+ title,
139
+ slug,
140
+ content,
141
+ excerpt: excerpt || undefined,
142
+ coverImage: coverImage || undefined,
143
+ published,
144
+ tags: tags || [],
145
+ category: category || undefined,
146
+ metaTitle: metaTitle || undefined,
147
+ metaDescription: metaDescription || undefined,
148
+ authorEmail: authorEmail || undefined,
149
+ };
150
+ const response = await this.helpers.httpRequest({
151
+ method: 'POST',
152
+ url: credentials.url,
153
+ headers: {
154
+ 'Authorization': `Bearer ${credentials.secret}`,
155
+ 'Content-Type': 'application/json',
156
+ },
157
+ body,
158
+ json: true,
159
+ });
160
+ returnData.push({
161
+ json: response,
162
+ pairedItem: {
163
+ item: i,
164
+ },
165
+ });
166
+ }
167
+ catch (error) {
168
+ if (this.continueOnFail()) {
169
+ returnData.push({
170
+ json: {
171
+ error: error instanceof Error ? error.message : String(error),
172
+ },
173
+ pairedItem: {
174
+ item: i,
175
+ },
176
+ });
177
+ continue;
178
+ }
179
+ throw error;
180
+ }
181
+ }
182
+ return [returnData];
183
+ }
184
+ }
185
+ exports.BlogPost = BlogPost;
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2
+ <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
3
+ <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
4
+ <line x1="8" y1="7" x2="16" y2="7"></line>
5
+ <line x1="8" y1="11" x2="16" y2="11"></line>
6
+ <line x1="8" y1="15" x2="12" y2="15"></line>
7
+ </svg>
8
+
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "n8n-nodes-blog-post",
3
+ "version": "1.0.0",
4
+ "description": "Custom n8n node for posting blogs to API endpoints with Bearer token authentication",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "n8n-nodes-base"
8
+ ],
9
+ "license": "MIT",
10
+ "homepage": "",
11
+ "author": {
12
+ "name": "",
13
+ "email": ""
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": ""
18
+ },
19
+ "main": "index.js",
20
+ "scripts": {
21
+ "build": "tsc && gulp build:icons",
22
+ "dev": "tsc --watch",
23
+ "format": "prettier nodes credentials --write",
24
+ "lint": "eslint \"nodes/**/*.ts\" \"credentials/**/*.ts\"",
25
+ "lintfix": "eslint \"nodes/**/*.ts\" \"credentials/**/*.ts\" --fix",
26
+ "prepublishOnly": "npm run build && npm run lint -s"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md"
31
+ ],
32
+ "n8n": {
33
+ "n8nNodesApiVersion": 1,
34
+ "nodes": [
35
+ "dist/nodes/BlogPost/BlogPost.node.js"
36
+ ],
37
+ "credentials": [
38
+ "dist/credentials/BlogApi.credentials.js"
39
+ ]
40
+ },
41
+ "devDependencies": {
42
+ "@typescript-eslint/parser": "^5.45.0",
43
+ "eslint-plugin-n8n-nodes-base": "~1.11.0",
44
+ "gulp": "^4.0.2",
45
+ "n8n-workflow": "*",
46
+ "prettier": "^2.7.1",
47
+ "typescript": "~5.3.3"
48
+ },
49
+ "dependencies": {
50
+ "n8n-workflow": "*"
51
+ }
52
+ }
53
+