| name | ai-content-pipeline-automation |
| description | Automate content creation from research to video generation using AI (Claude/OpenAI) and Remotion for Vietnamese/English marketing content |
| triggers | ["how do I automate content research and video generation","set up AI content pipeline with Claude and Remotion","generate marketing content automatically from keywords","create videos from blog posts using AI","build automated content workflow with TypeScript","scrape news and generate social media content","use Remotion to render marketing videos","configure AI content automation pipeline"] |
AI Content Pipeline Automation
Skill by ara.so — Marketing Skills collection.
This skill enables AI coding agents to work with Ultimate AI Content Pipeline, a TypeScript-based automation system that transforms keywords into complete content packages: research, scripts, blog posts, and rendered videos. The pipeline leverages Claude 3, OpenAI, web scraping, and Remotion for end-to-end content creation.
What This Project Does
The AI Content Pipeline automates:
- Research: Crawls recent news from TechCrunch, a16z, Twitter, LinkedIn within 24h
- Content Generation: Creates blog posts in multiple formats (toplist, POV, case study, how-to) in Vietnamese and English
- Video Rendering: Automatically generates infographics and short-form videos using Remotion
- Multi-platform Export: Optimized output for Reels, TikTok, Shorts
Installation
git clone https://github.com/pennydinh/marketing-pineline-share.git
cd marketing-pineline-share
npm install
yarn install
pnpm install
Environment Setup
Create a .env.local file in the root directory:
# AI Services
ANTHROPIC_API_KEY=your_claude_api_key
OPENAI_API_KEY=your_openai_api_key
# Research APIs
RAPIDAPI_KEY=your_rapidapi_key
# Database (if using)
DATABASE_URL=your_database_url
# Remotion (for video rendering)
REMOTION_AWS_ACCESS_KEY_ID=your_aws_key
REMOTION_AWS_SECRET_ACCESS_KEY=your_aws_secret
Run Development Server
npm run dev
yarn dev
pnpm dev
Access the application at http://localhost:3000
Project Structure
marketing-pineline-share/
├── src/
│ ├── app/ # Next.js app directory
│ ├── components/ # React components
│ ├── lib/
│ │ ├── ai/ # AI integration (Claude, OpenAI)
│ │ ├── scraper/ # Web scraping modules
│ │ └── video/ # Remotion video generation
│ └── types/ # TypeScript type definitions
├── remotion/ # Remotion video templates
└── public/ # Static assets
Core API Usage
1. Research & Content Scraping
import { scrapeNewsArticles } from '@/lib/scraper/news-crawler';
interface NewsArticle {
title: string;
url: string;
source: string;
publishedAt: Date;
content: string;
keywords: string[];
}
async function gatherResearch(keyword: string): Promise<NewsArticle[]> {
const sources = [
'techcrunch',
'a16z',
'twitter',
'linkedin'
];
const articles = await scrapeNewsArticles({
keyword,
sources,
timeRange: '24h',
limit: 20
});
return articles;
}
const research = await gatherResearch('AI marketing automation');
console.log(`Found ${research.length} relevant articles`);
2. AI Content Generation with Claude
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
interface ContentGenerationParams {
keyword: string;
format: 'toplist' | 'pov' | 'case-study' | 'how-to';
language: 'vi' | 'en';
tone: 'professional' | 'friendly' | 'humorous';
research: NewsArticle[];
}
async function generateContent(params: ContentGenerationParams): Promise<string> {
const { keyword, format, language, tone, research } = params;
const researchContext = research
.map(article => `- ${article.title} (${article.source}): ${article.content.slice(0, 200)}...`)
.join('\n');
const prompt = `You are an expert content creator for ${language === 'vi' ? 'Vietnamese' : 'English'} marketing content.
Topic: ${keyword}
Format: ${format}
Tone: ${tone}
Recent Research:
${researchContext}
Create a comprehensive ${format} article about ${keyword}. Include:
- Compelling headline
- Introduction with hook
- Main content with data-backed insights from the research
- Actionable takeaways
- Conclusion with CTA
${language === 'vi' ? 'Write in Vietnamese.' : 'Write in English.'}`;
const message = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 4096,
messages: [
{ role: 'user', content: prompt }
],
});
return message.content[0].type === 'text' ? message.content[0].text : '';
}
const content = await generateContent({
keyword: 'AI Content Marketing',
format: 'how-to',
language: 'en',
tone: 'professional',
research: research
});
3. OpenAI Alternative
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function generateWithOpenAI(params: ContentGenerationParams): Promise<string> {
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: `You are an expert marketing content creator specializing in ${params.language} content.`
},
{
role: 'user',
content: `Create a ${params.format} article about ${params.keyword} in ${params.tone} tone.`
}
],
temperature: 0.7,
max_tokens: 3000,
});
return completion.choices[0].message.content || '';
}
4. Video Generation with Remotion
import { bundle } from '@remotion/bundler';
import { renderMedia, selectComposition } from '@remotion/renderer';
import { VideoConfig } from '@/types/video';
interface VideoGenerationParams {
content: string;
title: string;
platform: 'reels' | 'tiktok' | 'youtube-shorts';
style: 'minimal' | 'dynamic' | 'professional';
}
async function generateVideo(params: VideoGenerationParams): Promise<string> {
const { content, title, platform, style } = params;
const dimensions = {
'reels': { width: 1080, height: 1920 },
'tiktok': { width: 1080, height: 1920 },
'youtube-shorts': { width: 1080, height: 1920 }
};
const { width, height } = dimensions[platform];
const bundleLocation = await bundle({
entryPoint: './remotion/index.ts',
webpackOverride: (config) => config,
});
const composition = await selectComposition({
serveUrl: bundleLocation,
id: 'ContentVideo',
inputProps: {
title,
content: extractKeyPoints(content),
style,
},
});
const outputLocation = `./output/${Date.now()}-${platform}.mp4`;
await renderMedia({
composition,
serveUrl: bundleLocation,
codec: 'h264',
outputLocation,
inputProps: {
title,
content: extractKeyPoints(content),
style,
},
});
return outputLocation;
}
function extractKeyPoints(content: string): string[] {
const lines = content.split('\n');
return lines
.filter(line => line.trim().startsWith('-') || line.trim().startsWith('•'))
.map(line => line.replace(/^[-•]\s*/, '').trim())
.slice(0, 5);
}
const videoPath = await generateVideo({
content: generatedContent,
title: 'AI Marketing Automation 101',
platform: 'reels',
style: 'professional'
});
5. Complete Pipeline Example
import { scrapeNewsArticles } from '@/lib/scraper/news-crawler';
import { generateContent } from '@/lib/ai/content-generator';
import { generateVideo } from '@/lib/video/remotion-renderer';
interface PipelineResult {
research: NewsArticle[];
englishContent: string;
vietnameseContent: string;
videos: {
reels: string;
tiktok: string;
shorts: string;
};
}
async function runContentPipeline(keyword: string): Promise<PipelineResult> {
console.log(`🚀 Starting content pipeline for: ${keyword}`);
console.log('📡 Gathering research...');
const research = await scrapeNewsArticles({
keyword,
sources: ['techcrunch', 'a16z', 'twitter'],
timeRange: '24h',
limit: 15
});
console.log('🧠 Generating English content...');
const englishContent = await generateContent({
keyword,
format: 'how-to',
language: 'en',
tone: 'professional',
research
});
console.log('🧠 Generating Vietnamese content...');
const vietnameseContent = await generateContent({
keyword,
format: 'how-to',
language: 'vi',
tone: 'friendly',
research
});
console.log('🎬 Rendering videos...');
const [reelsVideo, tiktokVideo, shortsVideo] = await Promise.all([
generateVideo({
content: englishContent,
title: keyword,
platform: 'reels',
style: 'dynamic'
}),
generateVideo({
content: englishContent,
title: keyword,
platform: 'tiktok',
style: 'dynamic'
}),
generateVideo({
content: englishContent,
title: keyword,
platform: 'youtube-shorts',
style: 'professional'
})
]);
console.log('✅ Pipeline complete!');
return {
research,
englishContent,
vietnameseContent,
videos: {
reels: reelsVideo,
tiktok: tiktokVideo,
shorts: shortsVideo
}
};
}
const result = await runContentPipeline('AI Marketing Automation 2026');
console.log(`Generated ${result.videos.reels}`);
Remotion Video Template Example
Create a video composition in remotion/ContentVideo.tsx:
import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig } from 'remotion';
import { interpolate } from 'remotion';
interface ContentVideoProps {
title: string;
content: string[];
style: 'minimal' | 'dynamic' | 'professional';
}
export const ContentVideo: React.FC<ContentVideoProps> = ({ title, content, style }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const titleOpacity = interpolate(frame, [0, 30], [0, 1], {
extrapolateRight: 'clamp',
});
return (
<AbsoluteFill style={{ backgroundColor: '#000' }}>
{/* Title Sequence */}
<Sequence from={0} durationInFrames={fps * 3}>
<AbsoluteFill style={{
justifyContent: 'center',
alignItems: 'center',
opacity: titleOpacity,
}}>
<h1 style={{
fontSize: 80,
color: '#fff',
textAlign: 'center',
fontWeight: 'bold',
padding: '0 40px',
}}>
{title}
</h1>
</AbsoluteFill>
</Sequence>
{/* Content Points */}
{content.map((point, index) => (
<Sequence
key={index}
from={fps * (3 + index * 2)}
durationInFrames={fps * 2}
>
<ContentPoint text={point} index={index} />
</Sequence>
))}
</AbsoluteFill>
);
};
const ContentPoint: React.FC<{ text: string; index: number }> = ({ text, index }) => {
const frame = useCurrentFrame();
const opacity = interpolate(frame, [0, 15], [0, 1]);
const translateY = interpolate(frame, [0, 15], [50, 0]);
return (
<AbsoluteFill style={{
justifyContent: 'center',
alignItems: 'center',
opacity,
}}>
<div style={{
transform: `translateY(${translateY}px)`,
padding: '40px',
maxWidth: '80%',
}}>
<p style={{
fontSize: 50,
color: '#fff',
textAlign: 'center',
lineHeight: 1.5,
}}>
{text}
</p>
</div>
</AbsoluteFill>
);
};
Configuration Patterns
Custom AI Provider Configuration
export const aiConfig = {
providers: {
claude: {
model: 'claude-3-5-sonnet-20241022',
maxTokens: 4096,
temperature: 0.7,
},
openai: {
model: 'gpt-4-turbo-preview',
maxTokens: 3000,
temperature: 0.7,
},
},
contentFormats: {
'toplist': 'Create a numbered list of top items',
'pov': 'Write from a specific point of view',
'case-study': 'Analyze a real-world example',
'how-to': 'Step-by-step tutorial format',
},
languages: ['vi', 'en'],
tones: ['professional', 'friendly', 'humorous'],
};
Scraper Configuration
export const scraperConfig = {
sources: {
techcrunch: {
baseUrl: 'https://techcrunch.com',
rateLimit: 1000,
},
a16z: {
baseUrl: 'https://a16z.com',
rateLimit: 1500,
},
},
headers: {
'User-Agent': 'Mozilla/5.0 (compatible; ContentBot/1.0)',
},
timeout: 10000,
};
Troubleshooting
API Rate Limits
class RateLimiter {
private queue: Array<() => Promise<any>> = [];
private processing = false;
async add<T>(fn: () => Promise<T>, delay: number = 1000): Promise<T> {
return new Promise((resolve, reject) => {
this.queue.push(async () => {
try {
const result = await fn();
resolve(result);
} catch (error) {
reject(error);
}
});
if (!this.processing) {
this.process(delay);
}
});
}
private async process(delay: number) {
this.processing = true;
while (this.queue.length > 0) {
const fn = this.queue.shift();
if (fn) await fn();
await new Promise(resolve => setTimeout(resolve, delay));
}
this.processing = false;
}
}
export const rateLimiter = new RateLimiter();
Video Rendering Errors
try {
const { getCompositions } = require('@remotion/renderer');
console.log('✅ Remotion installed correctly');
} catch (error) {
console.error('❌ Remotion not found. Run: npm install @remotion/renderer @remotion/bundler');
}
async function safeRenderVideo(params: VideoGenerationParams): Promise<string | null> {
try {
return await generateVideo(params);
} catch (error) {
console.error('Video rendering failed:', error);
return null;
}
}
Memory Issues with Large Content
function chunkArray<T>(array: T[], size: number): T[][] {
const chunks: T[][] = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
async function processLargeDataset(articles: NewsArticle[]) {
const chunks = chunkArray(articles, 5);
const results = [];
for (const chunk of chunks) {
const chunkResults = await Promise.all(
chunk.map(article => processArticle(article))
);
results.push(...chunkResults);
}
return results;
}
This skill provides AI coding agents with comprehensive knowledge to help developers implement automated content marketing pipelines using this TypeScript-based system.