# Content Automation
Automated content publishing for Pinterest and Instagram with AI-powered content generation and scheduling.
## Features
- β
**MCP Integration** β - Natural language control through AI assistants (primary way of working)
- π [Detailed MCP description](./MCP.md) - setup, prompt examples, troubleshooting
- β
**TypeScript** - Full type safety for reliability and better IDE support
- β
**Late API** - Publishing to Instagram and Pinterest through a unified API
- β
Unique AI-powered content generation for Pinterest and Instagram (OpenAI with customizable prompts)
- β
Publication scheduling through Late API (no local scheduler needed)
- β
**Instagram Stories Support** - Publishing Stories through Late API
- β
Publishing to both platforms with a single request
- β
Processed image tracking
- β
OpenAI integration for content generation (optional)
- β
CLI commands - alternative way of working through terminal
## Installation
1. Install dependencies:
```bash
npm install
```
2. Build the TypeScript project:
```bash
npm run build
```
3. Copy `.env.example` to `.env` and fill it:
```bash
cp .env.example .env
```
4. Configure environment variables in `.env`:
- **Late API** (required): Get API key at [getlate.dev](https://getlate.dev)
- **CDN Base URL** (required): Specify the base CDN URL where images are hosted
- **OpenAI API** (optional): For AI-powered content generation
- **Content Prompt** (optional): Customize content generation by copying `prompts/content-prompt.example.txt` to `prompts/content-prompt.txt` and editing it
## Getting API Keys
### Late API (Required) β
The project uses **only Late API** for publishing to Instagram and Pinterest.
1. Register at [getlate.dev](https://getlate.dev)
2. Get API key
3. Connect Instagram and Pinterest accounts
4. Get Profile ID and Account IDs from the dashboard
5. Add to `.env`:
```
LATE_API_KEY=your_key
LATE_PROFILE_ID=your_profile_id
LATE_INSTAGRAM_ACCOUNT_ID=your_instagram_account_id
LATE_PINTEREST_ACCOUNT_ID=your_pinterest_account_id
```
**Late API Benefits:**
- β
No local scheduler needed - Late API publishes on schedule automatically
- β
Reliable scheduling on Late servers
- β
**Publishing to Instagram AND Pinterest with a single request** - saves API requests!
- β
Free plan available (60 requests/minute)
- β
Support for 13 platforms (Instagram, Pinterest, Facebook, LinkedIn, Twitter/X, TikTok, YouTube, Reddit, Bluesky, Threads, Google Business, Telegram, Snapchat)
**Supported Platforms:** Instagram, Pinterest, Facebook, LinkedIn, Twitter/X, TikTok, YouTube, Reddit, Bluesky, Threads, Google Business, Telegram, Snapchat
## Usage
The project supports **two ways of working**:
1. **Through MCP agent** (recommended) - Natural language control through AI assistant
2. **Through CLI commands** - Traditional way through terminal
### Setup Check
Before starting, check API connection:
```bash
npm run check
```
This will check:
- Late API connection (required)
- CDN configuration (required)
- OpenAI API availability (optional)
### CLI Commands
#### Publishing Images
```bash
npm run publish -- --image=IMG_5857.jpg [options]
```
**Important:**
- Images must be on CDN. Specify only the filename (e.g., `IMG_5857.jpg`), the system will automatically build the CDN URL.
- **Case sensitivity:** Filename is case-sensitive. Specify the filename exactly as it appears on CDN (e.g., `IMG_5857.jpg`, not `img_5857.jpg`).
**Examples:**
```bash
# Default: all three types (Instagram post, Instagram story, Pinterest pin)
npm run publish -- --image=IMG_5857.jpg
# Publish in 1 hour
npm run publish -- --image=IMG_5857.jpg 1
# Draft with publication date
npm run publish -- --image=IMG_5857.jpg --date="tomorrow 18:00" --draft
# With context
npm run publish -- --image=IMG_5857.jpg 1 --context="City center"
# Instagram post only
npm run publish -- --image=IMG_5857.jpg --post
# Instagram story only
npm run publish -- --image=IMG_5857.jpg --story
# Instagram story + Pinterest pin (comma-separated)
npm run publish -- --image=IMG_5857.jpg --types=story,pin
# Instagram post + Pinterest pin
npm run publish -- --image=IMG_5857.jpg --types=post,pin
# Pinterest pin only
npm run publish -- --image=IMG_5857.jpg --pin
# With draft
npm run publish -- --image=IMG_5857.jpg --story --draft
```
**Options:**
- `--image=<filename>` - Image filename (required in CLI mode)
- `--context=<text>` - Context for content generation
- `--types=<list>` - Content types comma-separated: `post`, `story`, `pin` (e.g., `--types=story,pin`)
- `--post` - Instagram post only (short form for `--types=post`)
- `--story` - Instagram story only (short form for `--types=story`)
- `--pin` - Pinterest pin only (short form for `--types=pin`)
- (no flags) - All three types (default): Instagram post, Instagram story, Pinterest pin
- `--date=<date>` - Publication date (YYYY-MM-DD HH:MM or "tomorrow 18:00")
- `<hours>` - Alternative to --date: number of hours from current moment
- `--draft` or `-d` - Create as draft
**Content Types:**
- Default (nothing specified) - Publishes all three types: Instagram post, Instagram story, Pinterest pin
- `--types=post,story,pin` - Specify types comma-separated (e.g., `--types=story,pin`)
- `--post` - Publishes only Instagram post
- `--story` - Publishes only Instagram story
- `--pin` - Publishes only Pinterest pin (without Instagram)
**Detailed Documentation:**
- [CLI.md](./CLI.md) - Detailed CLI description with usage examples
### Building the Project
```bash
# Build TypeScript to JavaScript
npm run build
# Build and watch for changes (auto-recompiles on file changes)
npm run watch
```
### Using MCP in Dev Mode
When developing with MCP, use automatic recompilation:
```bash
# Terminal: Run watch for automatic recompilation
npm run watch
```
**How it works:**
1. `watch` automatically recompiles TypeScript when files change
2. Cursor automatically restarts MCP server when `dist/mcp/mcp-server.js` changes
3. You can immediately use updated MCP tools in Cursor chat
**Important:** After changing code in `src/mcp/` or related modules, changes will apply automatically through watch + MCP restart in Cursor.
**π§ Dev Mode (dry-run):**
- In `watch` mode, `DEV_MODE=true` is automatically enabled
- **Requests to Late API are NOT sent** - instead, JSON ready to send is output
- This allows testing logic without real publications
- For real requests, use `npm run watch:prod` or simply `npm run build` + commands
### Image Processing
#### Publishing a Single Image
```bash
# With specific image
npm run publish -- --image=IMG_0802.JPG
# With context
npm run publish -- --image=IMG_0802.JPG --context="Concert hall, evening"
# With content type
npm run publish -- --image=IMG_0802.JPG --context="City center" --story
# Instagram post only
npm run publish -- --image=IMG_0802.JPG --context="City center" --post
# With publication date
npm run publish -- --image=IMG_0802.JPG --context="Urban landscape" --date="2025-01-25 18:00"
# All parameters together
npm run publish -- --image=IMG_0802.JPG --context="Concert hall, evening" --post --date="2025-01-25 18:00"
```
**Note:** Local scheduler is not needed - Late API automatically publishes posts on schedule.
### Using MCP Agent (Recommended) β
**MCP (Model Context Protocol)** - This is the primary and recommended way to work with the project. Manage publications through AI assistant using natural language directly in Cursor, Claude, or other AI tools.
#### Quick Start with MCP
1. **Build the project:**
```bash
npm run build
```
2. **MCP server is automatically available in Cursor** (via `.cursor/mcp.json`)
3. **Use natural language:**
```
"Publish IMG_0802.JPG tomorrow at 18:00 with context 'Concert hall, evening'"
"Show list of available images"
"Generate content for IMG_1460.JPG"
"Schedule Story for IMG_2228.JPG today at 20:00"
```
**MCP Benefits:**
- β
**Natural language** - No need to remember commands
- β
**AI Integration** - Works directly in Cursor/Claude
- β
**Smart automation** - AI can plan publications itself
- β
**Contextual understanding** - AI understands your intentions
**Detailed Documentation:**
- [MCP.md](./MCP.md) - Setup, prompt examples, troubleshooting
### Using CLI Commands
Alternative way of working through terminal. Detailed documentation: [CLI.md](./CLI.md)
## Project Structure
The project is organized on a **modular principle** for better scalability and support.
### Main Modules:
- **`src/services/`** - API services (Late API, Pinterest API)
- **`src/generators/`** - Content generators (AI-powered with customizable prompts)
- **`src/processors/`** - Data processors (images)
- **`src/utils/`** - Utilities (CDN, configuration, scheduling)
- **`src/cli/`** - CLI commands and entry points
- **`src/mcp/`** - MCP integration for AI assistants
- **`src/types/`** - TypeScript types and interfaces
- **`prompts/`** - Content generation prompts (customizable)
### Modular Structure Benefits:
β
**Separation of concerns** - Each module is responsible for its area
β
**Singleton pattern** - Services are exported as singleton instances
β
**Direct imports** - Simplified structure without intermediate index.ts
β
**Scalability** - Easy to add new services
β
**Testability** - Each module can be tested separately
## Content Format
### Pinterest
- **Title**: SEO-optimized headline
- **Description**: Description with keywords
- **Keywords**: List of keywords
- **CTA**: Call to action (leads to Instagram)
### Instagram Posts
- **Caption**: Emotional story text
- **Soft CTA**: Soft call to action
- **Hashtags**: 3-5 relevant hashtags (customizable via content prompt)
### Instagram Stories
- Stories do not support long captions
- Text overlays can be used (via API)
- User mentions (user_tags) are supported
- Automatically disappear after 24 hours
## Limitations and Capabilities
### Late API
- β
**Only Late API is used** for publishing to Instagram and Pinterest
- β
Native scheduling through Late API
- β
Does not require local scheduler
- β
Publishing to both platforms with a single request
- β
Support for media file upload or using public CDN URLs
- β
**Supports Stories** - Can publish Stories through Late API
- β οΈ **Stories limitations**: Can only schedule for the next 24 hours
- β οΈ Free plan: 60 requests/minute
### CDN for Images
Images must be hosted on a public CDN:
- Specify `CDN_BASE_URL` in `.env` (required)
- Images are accessed directly from CDN (not uploaded to Late API)
- Specify only the filename in commands (e.g., `IMG_5857.jpg`)
- The system automatically builds CDN URLs by content type:
- `post` β `{CDN_BASE_URL}/post/{filename}`
- `story` β `{CDN_BASE_URL}/story/{filename}`
- `pin` β `{CDN_BASE_URL}/pin/{filename}`
- **Important:** Filenames are case-sensitive - use exact case as on CDN
## Content Generation Customization
The content generation prompt can be customized to match your brand voice and target audience:
1. **Copy the example prompt:**
```bash
cp prompts/content-prompt.example.txt prompts/content-prompt.txt
```
2. **Edit `prompts/content-prompt.txt`** with your custom instructions:
- Adjust tone and style
- Modify hashtag requirements
- Change content focus and goals
- Update output format if needed
3. **The custom prompt is automatically loaded** - no code changes needed!
**Note:** `prompts/content-prompt.txt` is ignored by git, so your customizations remain private. The example file (`content-prompt.example.txt`) serves as a template and is version-controlled.
## Security
- Never commit `.env` file
- Never commit `prompts/content-prompt.txt` (already in `.gitignore`)
- Store API keys in a secure place
- Regularly check Late API key expiration
- Do not share API keys publicly
## Troubleshooting
### Late API Connection Error
- Check API key correctness: `npm run check`
- Make sure both accounts (Instagram and Pinterest) are connected in Late
- Check API key expiration
### Publication Error
- Make sure Instagram and Pinterest accounts are connected in Late
- Check account access rights
- Make sure images are available on CDN at specified URLs
### Images Not Processing
- Check file formats (supported: JPG, PNG)
- Make sure files are not corrupted
- **Check filename case** - Filename is case-sensitive (e.g., `IMG_5857.jpg` β `img_5857.jpg`)
- Make sure file exists on CDN at specified path
### CDN Not Working
- Make sure `CDN_BASE_URL` is specified correctly
- Check that images are available at specified URLs
- Make sure URLs are publicly accessible
## License
MIT