Content Automation System
A comprehensive n8n-powered content creation and publishing platform with AI-driven writing, image generation, multi-platform publishing, and Google Sheets calendar integration.
- ā AI-powered content research & writing
- ā DALL-E 3 image generation
- ā Multi-platform publishing
- ā Google Sheets editorial calendar
- ā Optimal time scheduling
- ā Telegram bot control
- ā Video script generation
- š¼ LinkedIn (Personal & Company)
- š¦ Twitter/X
- š Facebook Business
- šø Instagram
- š WordPress
- š¬ Video (YouTube/TikTok ready)
- š§ OpenAI GPT-4o for writing
- šØ DALL-E 3 for images
- š SerpAPI for research
- š£ļø ElevenLabs for voiceover
- š Custom persona training
System Workflow
Command Input
Calendar
Parse & Route
AI Brief
Web Data
GPT-4o
DALL-E 3
Script + Voice
6 Platforms
Track Results
System Architecture
Workflow Interconnection
{
"workflows": {
"00-calendar-scheduler": {
"triggers": ["schedule"],
"calls": ["01-master-trigger"],
"description": "Hourly check for scheduled content"
},
"01-master-trigger": {
"triggers": ["telegram", "webhook"],
"calls": ["02-ideate-research-write"],
"description": "Entry point for all content requests"
},
"02-ideate-research-write": {
"triggers": ["execute-workflow"],
"calls": ["03-image-creation", "04-content-publisher"],
"description": "Content strategy, research, and writing"
},
"03-image-creation": {
"triggers": ["execute-workflow"],
"calls": ["04-content-publisher"],
"description": "AI image generation and storage"
},
"04-content-publisher": {
"triggers": ["execute-workflow"],
"calls": [],
"description": "Multi-platform publishing"
},
"05-video-production": {
"triggers": ["execute-workflow"],
"calls": ["04-content-publisher"],
"description": "Video script and voice generation"
}
}
}
Data Flow Schema
| Stage | Data Structure | Storage | Duration |
|---|---|---|---|
| Trigger | Command + Metadata | Memory | <1s |
| Brief | Strategy + Research Questions | Memory | 30-60s |
| Research | SERP Data + Insights | Memory | 10-30s |
| Content | Full Text + SEO Data | Memory + S3 | 60-120s |
| Media | Image URLs + Video Assets | S3 | 30-90s |
| Published | Post URLs + Analytics | Google Sheets | Permanent |
External Services
Models: GPT-4o, DALL-E 3
Cost: ~$0.05-0.15 per content piece
Rate Limit: Tier-dependent (TPM)
Purpose: Image storage
Cost: ~$0.023/GB/month
Region: Close to n8n instance
Purpose: Web research
Cost: $50-100/month
Alternative: Perplexity API
Workflow 01: Master Trigger & Orchestrator
The entry point for all content creation requests. Accepts input from Telegram bot or Google Sheets calendar, parses commands, validates input, and routes to appropriate child workflows.
Command Format
/create [account] [content_type] [topic/idea] Examples: /create linkedin-main carousel 5 tax tips for startups /create twitter-tech thread Why AI won't replace accountants /create wordpress-blog blog Complete GST registration guide /create all standard Breaking news: New tax reforms
Input Parameters
| Parameter | Type | Options | Description |
|---|---|---|---|
| account | string | linkedin-main, linkedin-personal, twitter-tech, twitter-personal, facebook-business, instagram-main, wordpress-blog, all | Target platform identifier |
| content_type | string | standard, carousel, thread, blog, video, story | Format of content |
| topic | string | Free text | Content subject matter |
{
"name": "01 - Master Trigger (Dual Source)",
"nodes": [
{
"parameters": {
"updates": ["message"],
"additionalFields": {}
},
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1,
"position": [250, 200],
"webhookId": "telegram-master-trigger"
},
{
"parameters": {
"jsCode": "// Detect trigger source and normalize\nconst telegramData = $input.first().json;\n\n// Check if this is from Telegram or Google Sheets\nif (telegramData.message) {\n // Telegram source\n const message = telegramData.message;\n const text = message.text || '';\n \n // Parse command: /create [account] [type] [idea]\n const commandRegex = /^\\/create\\s+(\\S+)\\s+(\\S+)\\s+(.+)$/i;\n const match = text.match(commandRegex);\n \n if (!match) {\n return [{\n valid_command: false,\n source: 'telegram',\n chat_id: message.chat.id,\n error: 'Invalid command format'\n }];\n }\n \n return [{\n valid_command: true,\n source: 'telegram',\n account: match[1].toLowerCase(),\n content_type: match[2].toLowerCase(),\n idea: match[3],\n chat_id: message.chat.id,\n user_id: message.from.id,\n timestamp: new Date().toISOString(),\n persona_key: null,\n priority: 'normal'\n }];\n} else if (telegramData.source === 'google_sheets_calendar') {\n // Google Sheets source (already formatted)\n return [{\n valid_command: true,\n source: 'google_sheets',\n ...telegramData\n }];\n} else {\n return [{\n valid_command: false,\n source: 'unknown',\n error: 'Unrecognized trigger source'\n }];\n}"
},
"name": "Normalize Input",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [450, 300]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
n "id": "condition-1",
"leftValue": "={{ $json.valid_command }}",
"rightValue": "true",
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
}
},
"name": "Valid Input?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [650, 300]
},
{
"parameters": {
"chatId": "={{ $json.chat_id }}",
"text": "ā Error: {{ $json.error }}\n\nTelegram format: /create [account] [type] [idea]\nOr use Google Sheets Calendar for scheduled posting.",
"additionalFields": {}
},
"name": "Send Error",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1,
"position": [650, 500]
},
{
"parameters": {
"chatId": "={{ $json.chat_id }}",
"text": "=ā
Request received from {{ $json.source === 'telegram' ? 'Telegram' : 'Content Calendar' }}!\n\nšÆ Account: {{ $json.account }}\nš Type: {{ $json.content_type }}\nš” Topic: {{ $json.idea.substring(0, 50) }}...\nā° Priority: {{ $json.priority || 'normal' }}\n\n{{ $json.scheduled_time ? 'š
Scheduled for: ' + $json.scheduled_time : 'š Starting immediately...' }}",
"additionalFields": {}
},
"name": "Confirm Receipt",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1,
"position": [850, 200]
},
{
"parameters": {
"workflowId": "02-ideate-research-write",
"options": {}
},
"name": "Execute Content Workflow",
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1,
"position": [1050, 200]
}
],
"connections": {
"Telegram Trigger": {
"main": [[{ "node": "Normalize Input", "type": "main", "index": 0 }]]
},
"Normalize Input": {
"main": [[{ "node": "Valid Input?", "type": "main", "index": 0 }]]
},
"Valid Input?": {
"main": [
[{ "node": "Confirm Receipt", "type": "main", "index": 0 }],
[{ "node": "Send Error", "type": "main", "index": 0 }]
]
},
"Confirm Receipt": {
"main": [[{ "node": "Execute Content Workflow", "type": "main", "index": 0 }]]
}
}
}
Node Specifications
Type: n8n-nodes-base.telegramTrigger
Webhook ID: telegram-master-trigger
Events: message
Output: Raw Telegram message object
Detects trigger source (Telegram vs Google Sheets) and normalizes into common schema. Validates command format using regex.
Condition: $json.valid_command equals true
True Branch: Proceed to confirmation
False Branch: Send error message
Workflow 02: Ideate ā Research ā Write
The core content creation engine. Loads persona configuration, generates content strategy brief, conducts web research (optional), and produces platform-optimized content using GPT-4o.
Processing Stages
| Stage | Duration | Output | Cost (USD) |
|---|---|---|---|
| Load Persona | <1s | Configuration object | $0.00 |
| AI Content Brief | 5-10s | Strategy + structure | ~$0.02 |
| Web Research | 10-30s | SERP data + insights | ~$0.01 |
| AI Writing | 15-30s | Complete content | ~$0.05-0.10 |
Persona Configuration Schema
const personas = {
'professional_ceo': {
name: 'Professional CEO',
tone: 'authoritative, insightful, data-driven',
style: 'business professional with personal touch',
vocabulary: 'industry terminology, strategic frameworks',
sentence_structure: 'mix of short punchy and detailed',
emoji_usage: 'minimal, professional',
cta_style: 'thought-provoking questions',
linkedin_specific: 'focus on leadership, trends, culture',
twitter_specific: 'concise insights, thread storytelling',
wordpress_specific: 'comprehensive guides, SEO-optimized'
},
'thought_leader': {
name: 'Thought Leader',
tone: 'visionary, challenging, inspiring',
style: 'provocative ideas with actionable insights',
vocabulary: 'forward-thinking, disruptive, innovative',
sentence_structure: 'rhetorical questions + strong opinions',
emoji_usage: 'strategic for emphasis',
cta_style: 'invite debate and discussion',
linkedin_specific: 'contrarian takes, future predictions',
twitter_specific: 'hot takes, viral hooks',
wordpress_specific: 'deep dives, research-backed'
},
'tech_influencer': {
name: 'Tech Influencer',
tone: 'enthusiastic, knowledgeable, accessible',
style: 'explaining complex tech simply',
vocabulary: 'tech jargon explained, analogies',
sentence_structure: 'problem-solution format',
emoji_usage: 'tech-related emojis',
cta_style: 'ask for experiences',
linkedin_specific: 'tech trends, career advice',
twitter_specific: 'quick tips, tool recommendations',
wordpress_specific: 'tutorials, reviews, comparisons'
},
'seo_expert': {
name: 'SEO Expert',
tone: 'helpful, authoritative, comprehensive',
style: 'structured, skimmable, keyword-rich',
vocabulary: 'SEO terminology, action verbs',
sentence_structure: 'H2/H3 hierarchy, bullet points',
emoji_usage: 'section dividers',
cta_style: 'downloadable resources',
linkedin_specific: 'content marketing tips',
twitter_specific: 'SEO quick wins',
wordpress_specific: 'long-form, pillar content'
}
};
AI Content Brief Prompt
You are a content strategist. Based on the persona below, analyze the content idea and create a detailed brief.
PERSONA: {{ $json.persona_config.name }}
TONE: {{ $json.persona_config.tone }}
STYLE: {{ $json.persona_config.style }}
ACCOUNT: {{ $json.account }}
CONTENT TYPE: {{ $json.content_type }}
Create a content brief including:
1. Angle/hook (what makes this interesting)
2. Key messages (3-5 points)
3. Target audience pain points
4. Research questions to investigate
5. Content structure outline
6. Visual requirements (image descriptions)
7. SEO keywords (if applicable)
8. Call-to-action recommendation
AI Writing Prompt
You are an expert content writer. Write content following these exact specifications:
PERSONA: {{ $json.persona_config.name }}
WRITING STYLE: {{ $json.persona_config.style }}
TONE: {{ $json.persona_config.tone }}
VOCABULARY: {{ $json.persona_config.vocabulary }}
SENTENCE STRUCTURE: {{ $json.persona_config.sentence_structure }}
EMOJI USAGE: {{ $json.persona_config.emoji_usage }}
CONTENT TYPE: {{ $json.content_type }}
PLATFORM: {{ $json.account }}
PLATFORM-SPECIFIC RULES:
{{ $json.account.includes('linkedin') ? $json.persona_config.linkedin_specific : '' }}
{{ $json.account.includes('twitter') ? $json.persona_config.twitter_specific : '' }}
{{ $json.account.includes('wordpress') ? $json.persona_config.wordpress_specific : '' }}
REQUIREMENTS:
- Hook/Opening must be compelling
- Include 3-5 key takeaways
- Use platform-appropriate formatting
- Include clear CTA
- Optimize for engagement
- If WordPress: Include SEO title, meta description, H2/H3 structure
- If LinkedIn Carousel: Structure as slide-by-slide with image descriptions
- If Twitter Thread: Number tweets, under 280 chars each
Workflow 03: Image Creation
Generates platform-optimized images using DALL-E 3, converts to binary, uploads to AWS S3, and returns public URLs for publishing.
Image Size Specifications
| Platform | Dimensions | DALL-E Size | Aspect Ratio |
|---|---|---|---|
| LinkedIn Feed | 1200 x 627 | 1792x1024 | 1.91:1 |
| LinkedIn Carousel | 1080 x 1080 | 1024x1024 | 1:1 |
| Twitter/X | 1200 x 675 | 1792x1024 | 16:9 |
| Instagram Feed | 1080 x 1080 | 1024x1024 | 1:1 |
| Instagram Story | 1080 x 1920 | 1024x1792 | 9:16 |
| 1200 x 630 | 1792x1024 | 1.91:1 | |
| WordPress Featured | 1200 x 630 | 1792x1024 | 1.91:1 |
S3 Storage Structure
s3://your-content-bucket/
āāā content-images/
ā āāā 2024/
ā ā āāā 01/
ā ā ā āāā image_001_1705683600.png
ā ā ā āāā ...
ā ā āāā 02/
ā ā āāā ...
ā āāā ...
āāā videos/
ā āāā ...
āāā assets/
āāā brand-templates/
content-images/ prefix or use CloudFront distribution for secure, cached delivery.
Workflow 04: Content Publisher
Publishes content to LinkedIn, Twitter/X, Facebook, Instagram, and WordPress with platform-specific formatting and API handling.
Platform API Specifications
Permissions: r_basicprofile, r_organization_social, w_organization_social, w_member_social
Rate Limit: 100 posts per 24 hours
Character Limit: 3,000 (posts), 125 (headlines)
Access Level: Elevated (required for media uploads)
Rate Limit: 300 tweets per 3 hours
Character Limit: 280 per tweet (4,000 for Twitter Blue)
Requirements: Business Account connected to Facebook Page
Rate Limit: 25 publishes per 24 hours
Aspect Ratios: 1.91:1 to 4:5 (photos), 9:16 (stories)
Authentication: Basic Auth with Application Password
Endpoint: /wp-json/wp/v2/posts
Features: SEO metadata, featured images, categories, tags
Workflow 05: Video Production
Creates video scripts, generates scene images, and produces voiceover using ElevenLabs. Outputs assets for manual assembly or automated video generation.
Video Production Pipeline
ElevenLabs Configuration
{
"model_id": "eleven_multilingual_v2",
"text": "{{ script_text }}",
"voice_settings": {
"stability": 0.5,
"similarity_boost": 0.75,
"style": 0.3,
"use_speaker_boost": true
}
}
Workflow 00: Calendar Scheduler
Hourly scheduled workflow that checks Google Sheets for approved content due for publishing, calculates optimal posting times, and triggers the content creation pipeline.
Scheduler Logic
// Check every hour for content to publish
const now = new Date();
const currentHour = now.getHours();
const today = now.toISOString().split('T')[0];
// Filter criteria:
// 1. Status is 'approved' or 'scheduled'
// 2. Date is today
// 3. Optimal time hour matches current hour (±1 hour buffer)
// 4. Not already published or failed
const scheduledContent = rows.filter(row => {
const status = row.Status?.toLowerCase();
const rowDate = row.Date;
const optimalTime = row.Optimal_Time ? new Date(row.Optimal_Time) : null;
const optimalHour = optimalTime ? optimalTime.getHours() : null;
const isReady = ['approved', 'scheduled'].includes(status);
const isToday = rowDate === today;
const isRightTime = optimalHour !== null ?
Math.abs(optimalHour - currentHour) <= 1 : true;
return isReady && isToday && isRightTime;
});
Google Sheets Column Mapping
| Column | Header | Data Type | Auto/Manual |
|---|---|---|---|
| A | Date | Date (YYYY-MM-DD) | Manual |
| B | Time | Time (HH:MM) | Manual (optional) |
| C | Platform | String (dropdown) | Manual |
| D | Content_Type | String (dropdown) | Manual |
| E | Topic | String | Manual |
| F | Status | String (dropdown) | Auto-updated |
| G | Optimal_Time | DateTime | Auto-calculated |
| H | Persona | String (dropdown) | Manual |
| I | Priority | String (dropdown) | Manual |
| J | Created_By | String | Auto (Apps Script) |
| K | Created_Date | DateTime | Auto (Apps Script) |
| L | Published_URL | String | Auto-updated |
| M | Error_Log | String | Auto-updated |
| N | Content_ID | String | Auto (formula) |
Google Sheets Integration
Setup Instructions
- Visit Google Cloud Console
- Create new project named
ContentAutomation - Enable APIs: Google Sheets API + Google Drive API
- Navigate to IAM & Admin ā Service Accounts
- Create service account:
n8n-content-calendar - Role: Editor (or custom Sheets Editor)
- Create key ā JSON ā Download securely
- Create new Google Sheet named
ContentCalendar - Add column headers (A: Date through N: Content_ID)
- Set up data validation for dropdown columns (C, D, F, H, I)
- Apply conditional formatting for status colors
- Share with service account email (Editor access)
- Copy Sheet ID from URL:
/d/SHEET_ID/edit
Apps Script Automation
function onEdit(e) {
const sheet = e.source.getActiveSheet();
if (sheet.getName() !== 'ContentCalendar') return;
const row = e.range.getRow();
const col = e.range.getColumn();
// Auto-timestamp when Date is added
if (col === 1 && row > 1) {
const createdDateCell = sheet.getRange(row, 11);
if (!createdDateCell.getValue()) {
createdDateCell.setValue(new Date());
}
// Auto-calculate optimal time
const platform = sheet.getRange(row, 3).getValue();
const date = sheet.getRange(row, 1).getValue();
if (platform && date) {
const optimalTime = calculateOptimalTime(platform, date);
sheet.getRange(row, 7).setValue(optimalTime);
}
}
// Status change logging
if (col === 6 && row > 1) {
const newStatus = e.value;
if (newStatus === 'published') {
sheet.getRange(row, 12).setValue(new Date());
}
}
}
function calculateOptimalTime(platform, date) {
const times = {
'linkedin-main': [9, 12, 17],
'twitter-tech': [8, 12, 17, 21],
'facebook-business': [13, 19],
'instagram-main': [11, 19],
'wordpress-blog': [9, 14]
};
const hours = times[platform] || [10];
const randomHour = hours[Math.floor(Math.random() * hours.length)];
const randomMinute = Math.floor(Math.random() * 60);
const result = new Date(date);
result.setHours(randomHour, randomMinute, 0);
return result;
}
Telegram Bot Commands
Command Reference
| Command | Format | Example | Description |
|---|---|---|---|
/create |
/create [account] [type] [topic] | /create linkedin-main carousel 5 tax tips | Create and publish content immediately |
/schedule |
/schedule [account] [type] [date] [topic] | /schedule twitter-tech thread 2024-01-20 AI trends | Add to Google Sheets calendar |
/status |
/status [content_id] | /status 20240115-abc123 | Check content status |
/accounts |
/accounts | /accounts | List available accounts |
/help |
/help | /help | Show detailed help |
BotFather Configuration
setcommands start - Start the bot and see welcome message create - Create content immediately (format: /create account type idea) schedule - Schedule content for later (format: /schedule account type date idea) status - Check status of content by ID accounts - List all available social media accounts help - Show detailed help and examples
https://your-n8n-instance.com/webhook/telegram-master-trigger
API Credentials Matrix
| Service | Type | Cost | Rate Limits | Priority |
|---|---|---|---|---|
| OpenAI | API Key | Pay-per-use | Tier-dependent | Critical |
| Telegram | Bot Token | Free | 30 msgs/sec | Critical |
| AWS S3 | Access Key | Storage + bandwidth | 3,500 PUTs/sec | Critical |
| OAuth 2.0 | Free | 100 posts/day | Platform | |
| Twitter/X | OAuth 2.0 | Free-$5000/mo | 300 tweets/3hrs | Platform |
| Facebook/IG | Graph API | Free | 25 posts/day | Platform |
| WordPress | App Password | Free | Server-dependent | Platform |
| SerpAPI | API Key | $50/mo+ | 5,000 searches/mo | Optional |
| ElevenLabs | API Key | $5/mo+ | Character limits | Video |
Credential Setup in n8n
Name: OpenAI Account
API Key: sk-...
Base URL: https://api.openai.com/v1
Name: Google Sheets Account
Type: Service Account
Email: n8n-content-calendar@...
Private Key: -----BEGIN PRIVATE KEY-----...
Persona Configuration
Define writing styles, tones, and platform-specific rules for each brand voice.
Tone: Authoritative, insightful, data-driven
Style: Business professional with personal touch
Best for: LinkedIn company pages, industry leadership
Tone: Visionary, challenging, inspiring
Style: Provocative ideas with actionable insights
Best for: Personal LinkedIn, Twitter, opinion pieces
Tone: Enthusiastic, knowledgeable, accessible
Style: Explaining complex tech simply
Best for: Developer tools, SaaS products, tutorials
Tone: Inspiring, aesthetic, narrative-driven
Style: Story-first approach
Best for: Instagram, lifestyle brands, behind-scenes
Tone: Helpful, authoritative, comprehensive
Style: Structured, skimmable, keyword-rich
Best for: WordPress blogs, long-form content, guides
Optimal Posting Times
| Platform | Best Days | Peak Times | Timezone |
|---|---|---|---|
| Tue, Wed, Thu | 8-10am, 12-2pm, 5-6pm | Audience local time | |
| Twitter/X | Mon-Thu | 8-10am, 12-1pm, 5-7pm, 9-11pm | Audience local time |
| Wed, Thu, Fri | 1-4pm, 7-9pm | Audience local time | |
| Sat, Sun | 7-9am, 11am-1pm, 7-9pm | Audience local time | |
| WordPress | Tue, Thu | 9-11am, 2-4pm | Audience local time |
function calculateOptimalTime(platform, targetDate, timezone = 'Asia/Kolkata') {
const schedules = {
'linkedin-main': {
slots: [
{ start: 8, end: 10, weight: 0.9 },
{ start: 12, end: 14, weight: 1.0 },
{ start: 17, end: 18, weight: 0.8 }
],
bestDays: [1, 2, 3] // Mon-Wed
},
'twitter-tech': {
slots: [
{ start: 8, end: 10, weight: 0.8 },
{ start: 12, end: 13, weight: 0.9 },
{ start: 17, end: 19, weight: 1.0 },
{ start: 21, end: 23, weight: 0.85 }
],
bestDays: [0, 1, 2, 3]
}
// ... additional platforms
};
// Weighted random selection within best slots
const config = schedules[platform];
const totalWeight = config.slots.reduce((sum, s) => sum + s.weight, 0);
let random = Math.random() * totalWeight;
const selected = config.slots.find(slot => {
random -= slot.weight;
return random <= 0;
});
// Random minute within selected hour range
const hour = selected.start + Math.random() * (selected.end - selected.start);
const minute = Math.floor(Math.random() * 60);
const result = new Date(targetDate);
result.setHours(Math.floor(hour), minute, 0, 0);
return result.toLocaleString('en-US', { timeZone: timezone });
}
Setup Guide
Step 1: Infrastructure
version: '3.8'
services:
n8n:
image: n8nio/n8n:latest
restart: always
ports:
- "5678:5678"
environment:
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=your_secure_password
- N8N_PROTOCOL=https
- N8N_HOST=automation.yourdomain.com
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=db_password
- N8N_ENCRYPTION_KEY=your_32_char_encryption_key
volumes:
- ~/.n8n:/home/node/.n8n
depends_on:
- postgres
postgres:
image: postgres:14-alpine
restart: always
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=db_password
- POSTGRES_DB=n8n
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Step 2: Install n8n
# Create directory mkdir ~/n8n-automation && cd ~/n8n-automation # Save docker-compose.yml above nano docker-compose.yml # Start services docker-compose up -d # Check logs docker-compose logs -f n8n # Access at https://your-server-ip:5678
Step 3: Import Workflows
- Open n8n web interface
- Workflows ā Import from File
- Import in order: 00, 01, 02, 03, 04, 05
- Update credential references in each workflow
- Activate workflows (toggle in top right)
Step 4: Configure Webhooks
# Set webhook
curl -F "url=https://your-n8n-instance.com/webhook/telegram-master-trigger" \
https://api.telegram.org/botYOUR_BOT_TOKEN/setWebhook
# Verify
curl https://api.telegram.org/botYOUR_BOT_TOKEN/getWebhookInfo
Deployment Checklist
Pre-Deployment
- Server provisioned (2 vCPU, 4GB RAM minimum)
- Domain name configured with SSL
- DNS A record pointing to server IP
- Firewall rules: 443 (HTTPS), 5678 (n8n) open
- Docker and Docker Compose installed
Credentials
- OpenAI API key generated and funded
- Telegram Bot created via BotFather
- LinkedIn Developer App created and approved
- Twitter Developer account approved (Elevated)
- Facebook Business Manager verified
- Instagram Business Account connected
- WordPress Application Password generated
- AWS Account with S3 bucket created
- Google Cloud project with Sheets API enabled
Configuration
- All workflow JSON files imported
- Credentials created in n8n for all services
- Google Sheet shared with service account
- Sheet ID updated in all Google Sheets nodes
- S3 bucket policy configured for public read
- Persona configurations customized
Testing
- Telegram webhook set successfully
- Test message received in n8n
- OpenAI connection test passed
- Image generation test passed
- S3 upload test passed
- LinkedIn test post (draft) successful
- Twitter test tweet successful
- WordPress test post (draft) successful
- Google Sheets calendar read test passed
Troubleshooting
Symptom: 429 errors in OpenAI nodes
Solution: Add Wait node with exponential backoff, or upgrade to paid tier for higher TPM limits
Symptom: 401 errors on publish
Solution: OAuth tokens expire every 60 days. Reconnect credential in n8n UI
Symptom: 403 error: duplicate content
Solution: Add unique timestamp or hash to each tweet content
Symptom: Media upload failed
Solution: Ensure images are between 1.91:1 and 4:5 aspect ratio
Symptom: 403 on image upload
Solution: Update bucket CORS policy and IAM permissions
Debug Commands
# Check n8n health curl http://localhost:5678/healthz # View recent logs docker logs n8n --tail 100 # Reset Telegram webhook curl -F "url=" https://api.telegram.org/bot/setWebhook # Test OpenAI curl https://api.openai.com/v1/models \ -H "Authorization: Bearer $OPENAI_API_KEY" # Check S3 access aws s3 ls s3://your-bucket/content-images/