oyi77

content-publisher

Automates drafting and publishing articles to Substack and Medium with Apify and Notion integration

oyi77 17 2 Actualitzat fa 8 mesos

Recursos

2
GitHub

Instal·la

npx skillscat add oyi77/1ai-skills/content-publisher

Instal·la des del registre de SkillsCat.

SKILL.md

Content Publisher Agent

Automates drafting and publishing articles to Substack and Medium with workflow automation.

Required Tools

MCP Servers

Apify MCP (Publishing Automation)

{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/mcp-server"],
      "env": { "APIFY_API_TOKEN": "${APIFY_API_TOKEN}" }
    },
    "notion": {
      "command": "npx",
      "args": ["-y", "@makenotion/mcp-server"],
      "env": { "NOTION_API_KEY": "${NOTION_API_KEY}" }
    },
    "slack": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-slack"],
      "env": { "SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}" }
    }
  }
}

Tool Permissions

Tool Capabilities
Bash(apify:*) Execute browser automation for publishing
MCP(apify:*) Run web scraping/automation actors
MCP(notion:*) Store editorial calendar, track drafts
MCP(slack:*) Send approval notifications

Authentication

Setup

  1. Apify Token

    export APIFY_API_TOKEN="your-token"
  2. Notion Integration

  3. Slack (optional)

    export SLACK_BOT_TOKEN="xoxb-your-token"

Capabilities

  • Drafting: Turn ideas into structured Markdown drafts
  • Publishing: Navigate to platform editors and publish
  • Cross-Posting: Sync content between platforms
  • Scheduling: Schedule posts for future publication
  • Editorial Calendar: Track in Notion

Pseudo Code

Example 1: Draft Article

// 1. Analyze request
const topic = "The impact of Agentic AI on coding";
const audience = "developers";
const tone = "professional";

// 2. Research if needed
const context = await apify.actor("apify/firecrawl-scraper", {
  urls: [`https://news.ycombinator.com/?q=${topic}`]
});

// 3. Generate content
const draft = await generateArticle({ topic, audience, tone, context });

// 4. Save to drafts folder
const filename = `memory/drafts/${dateSlug(topic)}.md`;
await fs.write(filename, draft);

// 5. Log to Notion editorial calendar
await notion.createPage("Editorial Calendar", {
  title: draft.title,
  status: "Draft",
  scheduledDate: null,
  platform: "both"
});

Example 2: Publish to Platform

// 1. Read draft
const content = await fs.read("memory/drafts/agentic-ai.md");

// 2. Navigate to platform
await browser.goto("https://medium.com/new-post");

// 3. Fill content
await browser.fill(".title-input", content.title);
await browser.fill(".body-editor", content.body);

// 4. Add tags
for (const tag of content.tags) {
  await browser.click(".tag-input");
  await browser.type(tag);
}

// 5. Publish or save draft
if (mode === "live") {
  await browser.click(".publish-button");
  await slack.notify("#content", `Published: ${content.title}`);
} else {
  await browser.click(".save-draft");
}

Example 3: Cross-Post to Both Platforms

// 1. Read content
const content = await fs.read(draftPath);

// 2. Convert for each platform
const mediumContent = convertToMedium(content);
const substackContent = convertToSubstack(content);

// 3. Publish to Medium
await publishToMedium(mediumContent);

// 4. Publish to Substack
await publishToSubstack(substackContent);

// 5. Update Notion
await notion.updatePage(draftId, { status: "Published" });

CLI Reference

Command Description
draft "topic" Generate article draft
publish <file> <platform> Publish to platform
publish <file> <platform> live Publish live
schedule <file> <platform> <datetime> Schedule post

Error Handling

Error Code Meaning Fix
AUTH_001 Not logged in Check credentials, re-login
PUBLISH_001 Platform changed UI Update selectors
RATE_001 Rate limited Wait and retry
VALIDATE_001 Content validation failed Check format

Common Patterns

Pattern: Dry-Run Publishing

async function publishWithDryRun(content, platform, dryRun = true) {
  // Validate content
  if (!content.title || !content.body) {
    throw new Error("Missing required fields");
  }

  // Preview
  console.log("=== PREVIEW ===");
  console.log(`Title: ${content.title}`);
  console.log(`Platform: ${platform}`);
  
  if (dryRun) {
    console.log("DRY RUN - No actual publishing");
    return { status: "preview" };
  }

  // Actually publish
  return await platform.publish(content);
}

Skill v2.0 - Content Publisher with MCP