ultimate-ai-content-pipeline

Automated content pipeline from research to video generation using Claude/OpenAI and Remotion

Skill file

Preview skill file
---
name: ultimate-ai-content-pipeline
description: Automated content creation pipeline from research to video generation using AI (Claude/OpenAI) and Remotion
triggers:
  - how do I automate content creation with AI research and video generation
  - set up an AI content pipeline with Claude and OpenAI
  - create automated marketing content with research and video rendering
  - build a content automation system with AI and Remotion
  - generate videos from AI-written content automatically
  - automate content research and video creation pipeline
  - use ultimate AI content pipeline for marketing automation
  - integrate Claude and OpenAI for automated content generation
---

# Ultimate AI Content Pipeline

> Skill by [ara.so](https://ara.so) — Marketing Skills collection.

Ultimate AI Content Pipeline is a comprehensive TypeScript-based content automation system that handles the entire content creation workflow: from automated research/crawling, AI-powered content generation (Claude 3, OpenAI), to automatic video rendering (Remotion). It crawls news from sources like TechCrunch, a16z, Twitter/X, and LinkedIn to create data-backed content in multiple formats and languages.

## Installation

```bash
# Clone the repository
git clone https://github.com/pennydinh/marketing-pineline-share.git
cd marketing-pineline-share

# Install dependencies
npm install
# or
pnpm install
# or
yarn install
```

## Environment Configuration

Create a `.env.local` file in the root directory:

```bash
# AI Providers
ANTHROPIC_API_KEY=your_claude_api_key
OPENAI_API_KEY=your_openai_api_key

# Research/Crawling APIs
RAPIDAPI_KEY=your_rapidapi_key

# Remotion (Video Rendering)
REMOTION_LICENSE_KEY=your_remotion_license_key

# Next.js Configuration
NEXT_PUBLIC_API_URL=http://localhost:3000
```

## Project Structure

```
marketing-pineline-share/
├── src/
│   ├── app/              # Next.js app directory
│   ├── components/       # React components
│   ├── lib/
│   │   ├── ai/          # AI integration (Claude, OpenAI)
│   │   ├── crawler/     # Content research/crawling
│   │   ├── content/     # Content generation logic
│   │   └── video/       # Remotion video generation
│   └── utils/           # Utility functions
├── remotion/            # Remotion video templates
└── public/              # Static assets
```

## Core Features & Usage

### 1. Automated Research/Crawling

The system automatically crawls and analyzes content from multiple sources:

```typescript
// src/lib/crawler/research.ts
import { RapidAPIClient } from './rapidapi-client';

interface ResearchOptions {
  keyword: string;
  sources: ('techcrunch' | 'twitter' | 'linkedin' | 'a16z')[];
  timeRange: '24h' | '7d' | '30d';
  language?: 'en' | 'vi';
}

export async function conductResearch(options: ResearchOptions) {
  const client = new RapidAPIClient(process.env.RAPIDAPI_KEY!);
  
  const results = await Promise.all(
    options.sources.map(source => 
      client.searchContent({
        source,
        keyword: options.keyword,
        timeRange: options.timeRange
      })
    )
  );
  
  // Aggregate and analyze results
  const insights = analyzeResearchData(results.flat());
  
  return {
    rawData: results,
    insights,
    metadata: {
      keyword: options.keyword,
      sources: options.sources,
      timestamp: new Date().toISOString()
    }
  };
}

function analyzeResearchData(data: any[]) {
  // Extract key insights, trends, and data points
  return {
    trends: extractTrends(data),
    statistics: extractStatistics(data),
    quotes: extractQuotes(data),
    keyTopics: identifyKeyTopics(data)
  };
}
```

### 2. AI Content Generation

Generate content in multiple formats using Claude or OpenAI:

```typescript
// src/lib/ai/content-generator.ts
import Anthropic from '@anthropic-ai/sdk';
import OpenAI from 'openai';

type ContentFormat = 'toplist' | 'pov' | 'case-study' | 'how-to';
type ToneOfVoice = 'expert' | 'friendly' | 'humorous';

interface ContentGenerationOptions {
  researchData: any;
  format: ContentFormat;
  tone: ToneOfVoice;
  language: 'en' | 'vi';
  provider: 'claude' | 'openai';
}

export async function generateContent(options: ContentGenerationOptions) {
  const prompt = buildContentPrompt(options);
  
  if (options.provider === 'claude') {
    return await generateWithClaude(prompt, options);
  } else {
    return await generateWithOpenAI(prompt, options);
  }
}

async function generateWithClaude(prompt: string, options: ContentGenerationOptions) {
  const anthropic = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY!
  });
  
  const message = await anthropic.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 4096,
    messages: [{
      role: 'user',
      content: prompt
    }]
  });
  
  return {
    content: message.content[0].text,
    metadata: {
      model: 'claude-3-5-sonnet',
      tokens: message.usage.input_tokens + message.usage.output_tokens,
      format: options.format,
      language: options.language
    }
  };
}

async function generateWithOpenAI(prompt: string, options: ContentGenerationOptions) {
  const openai = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY!
  });
  
  const completion = await openai.chat.completions.create({
    model: 'gpt-4-turbo-preview',
    messages: [{
      role: 'user',
      content: prompt
    }],
    temperature: 0.7,
    max_tokens: 4096
  });
  
  return {
    content: completion.choices[0].message.content,
    metadata: {
      model: completion.model,
      tokens: completion.usage?.total_tokens,
      format: options.format,
      language: options.language
    }
  };
}

function buildContentPrompt(options: ContentGenerationOptions): string {
  const { researchData, format, tone, language } = options;
  
  const formatInstructions = {
    'toplist': 'Create a top 10 list article',
    'pov': 'Write from a unique point of view perspective',
    'case-study': 'Develop a detailed case study',
    'how-to': 'Write a step-by-step how-to guide'
  };
  
  const toneInstructions = {
    'expert': 'authoritative and professional',
    'friendly': 'conversational and approachable',
    'humorous': 'engaging with light humor'
  };
  
  return `
You are a professional content creator. ${formatInstructions[format]} based on the following research data.

Tone: ${toneInstructions[tone]}
Language: ${language === 'en' ? 'English' : 'Vietnamese'}

Research Data:
${JSON.stringify(researchData.insights, null, 2)}

Requirements:
1. Use data and statistics from the research
2. Include relevant quotes and examples
3. Structure with clear headings and subheadings
4. Make it engaging and actionable
5. Include a compelling introduction and conclusion

Generate the content now:
`;
}
```

### 3. Video Generation with Remotion

Automatically render videos from generated content:

```typescript
// src/lib/video/video-generator.ts
import { bundle } from '@remotion/bundler';
import { renderMedia, selectComposition } from '@remotion/renderer';
import path from 'path';

interface VideoGenerationOptions {
  content: string;
  template: 'infographic' | 'reels' | 'shorts' | 'tiktok';
  aspectRatio: '16:9' | '9:16' | '1:1';
  outputPath: string;
}

export async function generateVideo(options: VideoGenerationOptions) {
  const { content, template, aspectRatio, outputPath } = options;
  
  // Parse content into video segments
  const segments = parseContentToSegments(content);
  
  // Bundle Remotion composition
  const bundleLocation = await bundle({
    entryPoint: path.join(process.cwd(), 'remotion', 'index.ts'),
    webpackOverride: (config) => config,
  });
  
  // Select composition based on template
  const compositionId = getCompositionId(template);
  
  const composition = await selectComposition({
    serveUrl: bundleLocation,
    id: compositionId,
    inputProps: {
      segments,
      aspectRatio,
      theme: getTheme(template)
    }
  });
  
  // Render video
  await renderMedia({
    composition,
    serveUrl: bundleLocation,
    codec: 'h264',
    outputLocation: outputPath,
    inputProps: {
      segments,
      aspectRatio,
      theme: getTheme(template)
    }
  });
  
  return {
    success: true,
    outputPath,
    duration: composition.durationInFrames / composition.fps,
    metadata: {
      template,
      aspectRatio,
      segments: segments.length
    }
  };
}

function parseContentToSegments(content: string) {
  // Parse markdown/structured content into video segments
  const lines = content.split('\n').filter(line => line.trim());
  const segments = [];
  
  for (const line of lines) {
    if (line.startsWith('# ')) {
      segments.push({
        type: 'title',
        text: line.replace('# ', ''),
        duration: 3
      });
    } else if (line.startsWith('## ')) {
      segments.push({
        type: 'subtitle',
        text: line.replace('## ', ''),
        duration: 2
      });
    } else if (line.length > 50) {
      segments.push({
        type: 'content',
        text: line,
        duration: 4
      });
    }
  }
  
  return segments;
}

function getCompositionId(template: string): string {
  const templates = {
    'infographic': 'Infographic',
    'reels': 'Reels',
    'shorts': 'Shorts',
    'tiktok': 'TikTok'
  };
  return templates[template] || 'Default';
}

function getTheme(template: string) {
  return {
    primaryColor: '#3B82F6',
    secondaryColor: '#10B981',
    backgroundColor: '#1F2937',
    font: 'Inter'
  };
}
```

### 4. Remotion Video Component Example

```typescript
// remotion/compositions/Infographic.tsx
import { AbsoluteFill, Sequence, useCurrentFrame, useVideoConfig } from 'remotion';
import React from 'react';

interface InfographicProps {
  segments: Array<{
    type: string;
    text: string;
    duration: number;
  }>;
  theme: {
    primaryColor: string;
    secondaryColor: string;
    backgroundColor: string;
    font: string;
  };
}

export const Infographic: React.FC<InfographicProps> = ({ segments, theme }) => {
  const { fps } = useVideoConfig();
  let currentFrame = 0;
  
  return (
    <AbsoluteFill style={{ backgroundColor: theme.backgroundColor }}>
      {segments.map((segment, index) => {
        const from = currentFrame;
        const durationInFrames = segment.duration * fps;
        currentFrame += durationInFrames;
        
        return (
          <Sequence
            key={index}
            from={from}
            durationInFrames={durationInFrames}
          >
            <SegmentComponent segment={segment} theme={theme} />
          </Sequence>
        );
      })}
    </AbsoluteFill>
  );
};

const SegmentComponent: React.FC<{
  segment: any;
  theme: any;
}> = ({ segment, theme }) => {
  const frame = useCurrentFrame();
  const opacity = Math.min(1, frame / 15);
  
  const styles = {
    title: {
      fontSize: 72,
      fontWeight: 'bold',
      color: theme.primaryColor
    },
    subtitle: {
      fontSize: 48,
      color: theme.secondaryColor
    },
    content: {
      fontSize: 36,
      color: '#FFFFFF',
      lineHeight: 1.5
    }
  };
  
  return (
    <AbsoluteFill
      style={{
        justifyContent: 'center',
        alignItems: 'center',
        padding: 60,
        opacity
      }}
    >
      <div style={styles[segment.type] || styles.content}>
        {segment.text}
      </div>
    </AbsoluteFill>
  );
};
```

### 5. Complete Pipeline Integration

```typescript
// src/lib/pipeline/content-pipeline.ts
import { conductResearch } from '../crawler/research';
import { generateContent } from '../ai/content-generator';
import { generateVideo } from '../video/video-generator';

interface PipelineOptions {
  keyword: string;
  contentFormat: 'toplist' | 'pov' | 'case-study' | 'how-to';
  tone: 'expert' | 'friendly' | 'humorous';
  languages: ('en' | 'vi')[];
  videoTemplate?: 'infographic' | 'reels' | 'shorts' | 'tiktok';
  generateVideo: boolean;
}

export async function runContentPipeline(options: PipelineOptions) {
  console.log('Starting content pipeline for:', options.keyword);
  
  // Step 1: Research
  console.log('Phase 1: Conducting research...');
  const researchData = await conductResearch({
    keyword: options.keyword,
    sources: ['techcrunch', 'twitter', 'linkedin', 'a16z'],
    timeRange: '24h'
  });
  
  // Step 2: Generate content for each language
  console.log('Phase 2: Generating content...');
  const contentResults = await Promise.all(
    options.languages.map(async (language) => {
      const content = await generateContent({
        researchData,
        format: options.contentFormat,
        tone: options.tone,
        language,
        provider: 'claude' // or 'openai'
      });
      
      return { language, ...content };
    })
  );
  
  // Step 3: Generate videos if requested
  let videoResults = null;
  if (options.generateVideo && options.videoTemplate) {
    console.log('Phase 3: Generating videos...');
    videoResults = await Promise.all(
      contentResults.map(async (result, index) => {
        const outputPath = `./output/video_${result.language}_${Date.now()}.mp4`;
        
        return await generateVideo({
          content: result.content,
          template: options.videoTemplate!,
          aspectRatio: options.videoTemplate === 'infographic' ? '16:9' : '9:16',
          outputPath
        });
      })
    );
  }
  
  console.log('Pipeline completed successfully!');
  
  return {
    success: true,
    research: researchData,
    content: contentResults,
    videos: videoResults,
    summary: {
      keyword: options.keyword,
      contentPieces: contentResults.length,
      videosGenerated: videoResults?.length || 0,
      timestamp: new Date().toISOString()
    }
  };
}
```

### 6. Next.js API Route Example

```typescript
// src/app/api/pipeline/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { runContentPipeline } from '@/lib/pipeline/content-pipeline';

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    
    const {
      keyword,
      contentFormat = 'toplist',
      tone = 'expert',
      languages = ['en', 'vi'],
      videoTemplate,
      generateVideo = false
    } = body;
    
    if (!keyword) {
      return NextResponse.json(
        { error: 'Keyword is required' },
        { status: 400 }
      );
    }
    
    const result = await runContentPipeline({
      keyword,
      contentFormat,
      tone,
      languages,
      videoTemplate,
      generateVideo
    });
    
    return NextResponse.json(result);
    
  } catch (error) {
    console.error('Pipeline error:', error);
    return NextResponse.json(
      { error: 'Pipeline execution failed', details: error.message },
      { status: 500 }
    );
  }
}
```

### 7. Frontend Usage Example

```typescript
// src/components/PipelineForm.tsx
'use client';

import { useState } from 'react';

export default function PipelineForm() {
  const [loading, setLoading] = useState(false);
  const [result, setResult] = useState(null);
  
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setLoading(true);
    
    const formData = new FormData(e.target as HTMLFormElement);
    
    const response = await fetch('/api/pipeline', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        keyword: formData.get('keyword'),
        contentFormat: formData.get('format'),
        tone: formData.get('tone'),
        languages: ['en', 'vi'],
        videoTemplate: formData.get('videoTemplate'),
        generateVideo: formData.get('generateVideo') === 'on'
      })
    });
    
    const data = await response.json();
    setResult(data);
    setLoading(false);
  };
  
  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <input
        name="keyword"
        placeholder="Enter keyword"
        required
        className="w-full p-2 border rounded"
      />
      
      <select name="format" className="w-full p-2 border rounded">
        <option value="toplist">Top List</option>
        <option value="pov">POV</option>
        <option value="case-study">Case Study</option>
        <option value="how-to">How-to</option>
      </select>
      
      <select name="tone" className="w-full p-2 border rounded">
        <option value="expert">Expert</option>
        <option value="friendly">Friendly</option>
        <option value="humorous">Humorous</option>
      </select>
      
      <label className="flex items-center gap-2">
        <input type="checkbox" name="generateVideo" />
        Generate Video
      </label>
      
      <select name="videoTemplate" className="w-full p-2 border rounded">
        <option value="infographic">Infographic</option>
        <option value="reels">Reels</option>
        <option value="shorts">Shorts</option>
        <option value="tiktok">TikTok</option>
      </select>
      
      <button
        type="submit"
        disabled={loading}
        className="w-full bg-blue-600 text-white p-2 rounded"
      >
        {loading ? 'Processing...' : 'Start Pipeline'}
      </button>
      
      {result && (
        <div className="mt-4 p-4 bg-gray-100 rounded">
          <pre>{JSON.stringify(result, null, 2)}</pre>
        </div>
      )}
    </form>
  );
}
```

## Development Commands

```bash
# Start development server
npm run dev

# Build for production
npm run build

# Start production server
npm start

# Type checking
npm run type-check

# Lint code
npm run lint

# Run tests
npm test
```

## Troubleshooting

### API Key Issues
- Ensure all API keys are properly set in `.env.local`
- Verify API key permissions and quotas
- Check if keys are correctly referenced without quotes

### Crawling/Research Errors
- Verify RapidAPI subscription includes required endpoints
- Check rate limits on news APIs
- Ensure source URLs are accessible

### AI Generation Failures
- Verify Claude/OpenAI API keys have sufficient credits
- Check model availability (some models require waitlist access)
- Reduce max_tokens if hitting quota limits
- Handle rate limiting with exponential backoff

### Video Rendering Issues
- Ensure Remotion license key is valid
- Check ffmpeg is installed: `ffmpeg -version`
- Verify sufficient disk space for video output
- Review Remotion logs for specific error messages

### Memory Issues
- Increase Node.js memory: `NODE_OPTIONS=--max-old-space-size=4096 npm run dev`
- Process videos sequentially instead of parallel for large batches
- Clear output directory regularly

### TypeScript Errors
```bash
# Clean and reinstall dependencies
rm -rf node_modules package-lock.json
npm install

# Regenerate types
npm run type-check
```

## Best Practices

1. **Rate Limiting**: Implement delays between API calls to avoid hitting rate limits
2. **Error Handling**: Always wrap API calls in try-catch blocks
3. **Caching**: Cache research results to avoid redundant API calls
4. **Monitoring**: Log all pipeline executions for debugging
5. **Testing**: Test with small datasets before running full pipeline
6. **Resource Management**: Clean up temporary files and video outputs regularly

Source

Creator's repository · aradotso/marketing-skills

View on GitHub

Security

Security checks in progress
Results will appear here once audits complete
What this skill can do
Reads your filesConnects to the internetRuns code on your machine
Checked by 3 independent security firms
Does it try to trick the AI?Not yet checkedPending · Gen Agent Trust Hub
Does it sneak in hidden code?Not yet checkedPending · Socket
Does it have known bugs?Not yet checkedPending · Snyk