Repository navigation
Expand file tree
/
Copy pathserver.js
More file actions
331 lines (273 loc) · 14.1 KB
/
Copy pathserver.js
File metadata and controls
331 lines (273 loc) · 14.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import fetch from 'node-fetch';
// Initialize environment variables
dotenv.config();
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
const PORT = process.env.PORT || 3005;
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.static(__dirname));
// API routes
app.post('/api/generate-ideas', async (req, res) => {
try {
const { prompt, category, language, audience, tone, knowledgeBase, customApiKey } = req.body;
// Build a comprehensive LinkedIn idea generation system prompt
let systemPrompt = `# LinkedIn Post Ideas Generator
You are a professional LinkedIn content strategist specializing in creating high-converting B2B content ideas. Your goal is to generate specific, actionable, and attention-grabbing LinkedIn post topics that would stop users from scrolling.
## Topic Style Guidelines
1. Be ULTRA SPECIFIC - Use exact numbers, percentages, timeframes and concrete results
2. Focus on outcomes and transformation - "How to achieve X result in Y timeframe"
3. Challenge common beliefs - "Why [common practice] is actually hurting your results"
4. Include "The exact..." or "The [number] ways..." to increase credibility
5. Address pain points directly - "Stop wasting money on..."
6. Use power words: ultimate, secrets, profitable, mistakes, killing, rejected, fix, converts
## Topic Format Examples for Business and Marketing
- "How to scale your [product/service] from $X to $Y per day profitably"
- "The exact [strategy/system] I use to get [specific result] on [platform]"
- "Why your [activity] is [negative outcome] (and how to fix it)"
- "Stop wasting money: The [number] biggest [platform] mistakes killing your profits"
- "How I decreased [metric] by [percentage] using [specific method]"
## Topic Format Examples for B2C Brands
- "How to turn your B2C brand into a customer magnet without spending a fortune on ads"
- "The secret psychology behind customer loyalty (and how smart brands use it)"
- "Why most B2C brands fail at [business goal] and the simple fix that changes everything"
- "[Number] proven ways to make your brand stand out in a crowded market (that your competition isn't using)"
- "The customer service mistake that's secretly killing your B2C brand's growth"
- "How to build a [aspect] that turns casual browsers into loyal customers"
- "The truth about [marketing concept] and why it matters more than ever for B2C brands"
- "What [famous brand] can teach you about consistent brand experience (and how to apply it to your business)"
- "The overlooked marketing channel that's bringing B2C brands massive ROI in 2025"
- "Why your ideal customers aren't buying (and the simple psychology fix that changes everything)"
## Topic Categories to Cover
- Tactical how-to's with specific outcomes
- Myth-busting posts that challenge industry norms
- Case studies with exact metrics and results
- Comparative analysis (X vs Y platform or strategy)
- Testing frameworks and performance optimization
- Specific strategies to improve key metrics (ROI, ROAS, CPA)
`;
// Add user parameters to the system context
let userContext = '';
if (language) userContext += `Language: ${language}\n`;
if (audience) userContext += `Target Audience: ${audience}\n`;
if (category && category !== 'Any') userContext += `Category Focus: ${category}\n`;
if (tone) userContext += `Content Tone: ${tone}\n`;
if (knowledgeBase && knowledgeBase.trim() !== '') userContext += `\nIncorporate this knowledge: ${knowledgeBase}\n`;
// Define the specific request based on user input
let specificRequest = '';
if (prompt) {
specificRequest = `Generate 10 LinkedIn post ideas related to: ${prompt}.\n\nCreate a mix of ideas using BOTH the Business/Marketing formats AND the B2C Brand formats from the examples above. Each idea should follow a different format pattern for maximum variety.\n\nMake these ideas highly specific, results-focused, and attention-grabbing. Include exact numbers, percentages, and concrete outcomes where appropriate. Each idea should be a complete, compelling headline that would make someone stop scrolling.`;
} else {
specificRequest = `Generate 10 diverse LinkedIn post ideas for the target audience specified.\n\nCreate a mix of ideas using BOTH the Business/Marketing formats AND the B2C Brand formats from the examples above. Use 5 ideas from each category and ensure each follows a different pattern.\n\nThe ideas should cover different aspects like:\n- Performance optimization and ROI improvements\n- Common mistakes and their solutions\n- Psychological insights that drive customer behavior\n- Comparison of different strategies or platforms\n- Case studies with specific metrics and results\n- Step-by-step frameworks and methodologies\n- Brand differentiation strategies\n- Customer retention and loyalty techniques\n\nMake each idea highly specific, results-focused, and in line with the topic format examples above. Use exact numbers, percentages, timeframes, and clear outcomes. Each idea should be a complete, compelling headline that would make someone stop scrolling.`;
}
// Combine all parts into the final prompt
let ideaPrompt = `${systemPrompt}\n\n## Your Assignment\n${userContext}\n${specificRequest}\n\nFormat as a simple numbered list with one idea per line. Don't include any explanations or additional text.`;
// Use custom API key if provided, otherwise use the server's key
const apiKey = customApiKey || process.env.ANTHROPIC_API_KEY;
const response = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-3-7-sonnet-20250219',
max_tokens: 300,
messages: [
{ role: 'user', content: ideaPrompt }
]
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error?.message || 'API request failed');
}
const data = await response.json();
console.log('Claude API response:', JSON.stringify(data));
const content = data.content[0].text;
console.log('Content extracted:', content);
// Parse the numbered list into an array of ideas
// First, split by newline
const lines = content.split('\n');
console.log('Split lines:', lines);
// Then filter for numbered lines and clean them up
const ideasArray = lines
.filter(line => /^\d+\./.test(line.trim()))
.map(line => line.replace(/^\d+\.\s*/, '').trim());
console.log('Extracted ideas:', ideasArray);
// If no ideas were found using the numbered list format, try to extract any lines that look meaningful
if (ideasArray.length === 0) {
console.log('No numbered ideas found, trying fallback extraction');
const fallbackIdeas = lines
.map(line => line.trim())
.filter(line => line.length > 15 && !line.startsWith('You are') && !line.includes('Generate 5'));
console.log('Fallback ideas:', fallbackIdeas);
if (fallbackIdeas.length > 0) {
res.json({ ideas: fallbackIdeas });
return;
}
// If still no ideas, create some default ones
res.json({
ideas: [
"How to Boost Customer Engagement with Personalized Marketing",
"5 Social Media Trends B2C Brands Can't Ignore in 2025",
"Building Customer Trust: From First Click to Lifetime Loyalty",
"Data-Driven Strategies to Understand Your B2C Customers Better",
"Creating Authentic Brand Stories That Resonate with Modern Consumers"
]
});
return;
}
res.json({ ideas: ideasArray });
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: error.message });
}
});
app.post('/api/generate-post', async (req, res) => {
try {
const { category, language, audience, tone, topicType, topicContent, knowledgeBase, customApiKey } = req.body;
// LinkedIn Post Generator System Prompt
const linkedInSystemPrompt = `# LinkedIn Post Generator System Prompt
You are a professional LinkedIn content creator AI that specializes in creating high-converting B2B LinkedIn posts. Your goal is to create LinkedIn posts that generate inbound leads, increase engagement, and ultimately drive conversions for your user's business.
## Core Content Philosophy
Follow the CAV framework for all posts:
- **Consumable**: Create one-sentence paragraphs with simple formatting. Each line should be 1-2 sentences maximum. Use ample spacing between paragraphs.
- **Actionable**: Provide steps users can implement within 24 hours. Focus on immediate, practical advice.
- **Valuable**: Deliver information people would potentially pay for. Solve real problems.
## Post Types
You can create the following types of posts:
### 1. Lead Magnet Posts
Purpose: To generate comments, connections, and collect leads.
Structure:
- Hook: Bold claim about outcome + timeframe + mechanism
- Problem/pain points that the resource solves
- Proof/expertise (why should they listen to you)
- What's in the resource (use specific numbers/percentages)
- Call to action (connect + comment specific word)
### 2. Value/Technical Posts
Purpose: To demonstrate expertise and build trust.
Structure:
- Hook: Challenge a common belief or ask a provocative question
- What & Why: High-level value and overall advice
- How: Step-by-step process with actionable insights
- Subtle product/service mention (if relevant)
- Simple question as call to action
### 3. Case Study/Social Proof Posts
Purpose: To provide evidence that your solution works.
Structure:
- Hook: Specific results achieved in specific timeframe
- Previous situation (pain points)
- Process used to achieve results
- Specific outcomes with exact numbers
- Key takeaways or lessons learned
- Call to action
### 4. Setup Call Posts
Purpose: To get people to book calls directly.
Structure:
- Hook: Bold claim about what they can achieve
- Simple step-by-step process
- Mention your product/service as part of the solution
- Soft call to action offering to set it up for them
### 5. Building In Public Posts
Purpose: To build connection and show progress.
Structure:
- Previous milestone
- Current situation
- Future goals
- What makes your approach different
- Ask for feedback
## Hook Creation Guidelines
The hook (first 3 lines) is the most critical part of your LinkedIn post. LinkedIn only shows the first 3 lines before "see more," so your hook must:
1. Stop people from scrolling
2. Get them to click "see more"
Effective hook strategies:
- Bold claims with specific outcomes ("LinkedIn will make me 100k a month in 2025")
- Questions that trigger curiosity ("Want to know how I generated 487 calls in 30 days?")
- Challenging common beliefs ("LinkedIn content agencies are under attack")
- Specific timeframes + results ("I wrote 30 posts in 10 minutes")
- Personal stories with outcomes ("I built my entire business using this LinkedIn funnel")
## Formatting Rules
1. Keep paragraphs to 1-2 sentences maximum
2. Use ample spacing between paragraphs
3. Use a mix of short and medium-length sentences
4. For lists, use line breaks rather than numbers/bullets when possible
5. Use emojis sparingly (0-2 per post)
6. For lead magnet posts, always include instructions to "comment [WORD] and connect with me"
7. Total post length: 1200-1500 characters is ideal
## Media Recommendations
Suggest incorporating:
- Success screenshots (calendar bookings, revenue, etc.)
- Simple graphics showing results or process
- Before/after comparisons
- Preview of the resource being shared`;
// User input parameters
let prompt = `${linkedInSystemPrompt}\n\n# Post Parameters\n`;
prompt += `Language: ${language}\n`;
prompt += `Target audience: ${audience}\n`;
prompt += `Tone: ${tone}\n`;
// Add knowledge base if provided
if (knowledgeBase && knowledgeBase.trim() !== '') {
prompt += `\nAdditional Knowledge to Incorporate:\n${knowledgeBase}\n`;
}
if (category !== 'Any') {
prompt += `Post category: ${category}\n`;
}
if (topicType === 'custom') {
prompt += `Topic: ${topicContent}\n`;
} else {
prompt += `Topic: ${topicContent}\n`;
}
// Select post type based on category
let postType = "Value/Technical Posts";
if (category === "Professional advice") {
postType = "Value/Technical Posts";
} else if (category === "Case study - client" || category === "Case study - personal") {
postType = "Case Study/Social Proof Posts";
} else if (category === "List of tips") {
postType = "Lead Magnet Posts";
} else if (category === "Personal story") {
postType = "Building In Public Posts";
}
prompt += `Post Type: ${postType}\n`;
prompt += `\nPlease create a complete LinkedIn post following the guidelines above. Include hook, body, and call to action. Make it engaging and designed to attract new followers.`;
// Use custom API key if provided, otherwise use the server's key
const apiKey = customApiKey || process.env.ANTHROPIC_API_KEY;
const response = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-3-opus-20240229',
max_tokens: 1000,
messages: [
{ role: 'user', content: prompt }
]
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error?.message || 'API request failed');
}
const data = await response.json();
res.json({ post: data.content[0].text });
} catch (error) {
console.error('Error:', error);
res.status(500).json({ error: error.message });
}
});
// Start server
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});