Files
Kunthawat Greethong 7b5af16f6d Initial commit: moreminimore-service content pipeline
- 9 mm* skills (orchestrator, article, social, publish, analytics)
- 6 dependency skills (content-writer, geo-optimizer, etc.)
- 3 analytics scripts (GSC, Google Ads, Meta Ads)
- Config template + setup guide
- SOUL-MM.md persona extension
- OrbitOS integration reference
2026-07-02 10:01:53 +07:00

7.7 KiB

name, description
name description
mm-social-writer Create social media posts (Facebook, X/Twitter, Instagram) from a published article. Requires the article's published_url. Generates platform-specific posts with the article link embedded. Use when: "เขียนโพส", "create social posts", "write posts from article", "mm-social", "สร้างโพสจากบทความ".

mm-social-writer

Creates social media posts from a published article, with the article URL embedded.

When This Must Trigger

  • "เขียนโพส", "create social posts", "write posts from article"
  • "mm-social", "สร้างโพสจากบทความ"
  • Called by moreminimore-orchestrator after article is published

Prerequisites

  • Article must be published with published_url in frontmatter
  • Article must have status: published

Process

Step 1: Find the published article

Search for published articles that DON'T have social posts yet:

import os, re

vault = os.path.expanduser("~/vault/60_Articles")
candidates = []

for client_dir in os.listdir(vault):
    client_path = os.path.join(vault, client_dir)
    if not os.path.isdir(client_path) or client_dir == 'Archive':
        continue
    
    for entry in os.listdir(client_path):
        if entry == 'Archive':
            continue
        article_path = os.path.join(client_path, entry, 'article.md')
        if not os.path.exists(article_path):
            continue
        
        content = open(article_path).read()[:800]
        
        # Must be published
        if 'status: published' not in content:
            continue
        
        # Must have published_url
        url_match = re.search(r'^published_url:\s*["\']?(.+?)["\']?\s*$', content, re.MULTILINE)
        if not url_match:
            continue
        
        # Check if posts already exist
        has_posts = os.path.exists(os.path.join(client_path, entry, 'post-facebook.md'))
        
        title_match = re.search(r'^title:\s*["\']?(.+?)["\']?\s*$', content, re.MULTILINE)
        
        candidates.append({
            'client_id': client_dir,
            'slug': entry,
            'title': title_match.group(1) if title_match else entry,
            'url': url_match.group(1),
            'dir': os.path.join(client_path, entry),
            'has_posts': has_posts
        })

Present to user:

บทความที่พร้อมสร้างโพส:

1. [title] — [client] — [url] — ยังไม่มีโพส
2. [title] — [client] — [url] — มีโพสแล้ว
...

เลือกหมายเลข:

If user selects an article that already has posts, ask:

  • สร้างใหม่แทนโพสเดิม?
  • หรือดูโพสที่มีอยู่?

Step 2: Read article content and determine platforms

Read the full article to understand:

  • Main topic and key points
  • Tone and style
  • Target audience
  • Key statistics or quotes to highlight

Determine which platforms to create posts for:

import json, os

config_path = os.path.expanduser("~/vault/99_System/clients-config.json")
config = json.load(open(config_path))

client = None
for c in config['clients']:
    if c['id'] == client_id:
        client = c
        break

# Get platforms from social_platforms field
platforms = client.get('social_platforms', [])

if not platforms:
    print("⚠️ ไม่มี social_platforms ใน config — ข้ามการสร้างโพส")
    # Exit or skip

If social_platforms is empty: skip social post creation entirely.

If social_platforms has values: only create posts for those platforms.

Present to user:

📱 Platforms ที่ใช้: [facebook, x, ig]
(กำหนดใน clients-config.json → social_platforms)

Step 3: Generate social posts

Create platform-specific posts based on social_platforms:

Only create posts for platforms listed in social_platforms. Skip any platform not in the list.

3a. Facebook Post (if "facebook" in social_platforms)

Use post-formatter logic (PAS or AIDA framework):

  • 200-300 words
  • Hook-driven opening
  • Key takeaway from article
  • Article URL embedded in the post
  • No CTA contact info (social posts don't use CTA)
---
type: post
platform: facebook
status: draft
created: YYYY-MM-DD
related_article: "article.md"
published_url: "https://..."
---

[Post content with article link naturally integrated]

3b. X/Twitter Post (if "x" in social_platforms)

Use hook-generator logic for the hook:

  • Single post: 280 chars max, hook + key point + article URL
  • Thread: 3-5 tweets, each with a key point, last tweet has article URL
---
type: post
platform: x
status: draft
created: YYYY-MM-DD
related_article: "article.md"
published_url: "https://..."
format: single|thread
---

[Post content with article link]

3c. Instagram Post (if "instagram" in social_platforms)

Visual-focused post:

  • Caption: 150-200 words, hook + key takeaway
  • Article URL in bio (IG doesn't allow clickable links in captions) → Note: "ลิงค์บทความใน bio" or use link sticker in Stories
  • Image: generate a square (1080x1080) version
  • Hashtags: 5-10 relevant hashtags
---
type: post
platform: instagram
status: draft
created: YYYY-MM-DD
related_article: "article.md"
published_url: "https://..."
image: "images/ig-post.png"
---

[Caption with "🔗 ลิงค์ใน bio" or similar]

Step 4: Generate social images

For each platform:

  • Facebook: use featured image (1200x630)
  • X: use featured image (1200x675)
  • Instagram: generate square version (1080x1080) — may need different composition

Save to: ~/vault/60_Articles/<client-id>/<slug>/images/

Step 5: Present for approval

📝 Social posts พร้อมตรวจ:

📄 Article: [title]
🔗 URL: [published_url]

📱 Platforms: [list from social_platforms]
  ✅ post-facebook.md — [word count] words (if facebook)
  ✅ post-x.md — [format] ([char count] chars) (if x)
  ✅ post-ig.md — [word count] words + image (if instagram)

ตรวจแล้วเป็นยังไงบ้าง?
- ✅ "approve" — อนุมัติ → พร้อม publish
- ✏️ "แก้ไข [specify]" — ปรับแก้

Wait for approval.

Step 6: Save posts

Save all posts to the article directory:

~/vault/60_Articles/<client-id>/<slug>/
├── article.md          (existing)
├── brief.md            (existing)
├── images/             (existing)
├── post-facebook.md    ← NEW
├── post-x.md           ← NEW
└── post-ig.md          ← NEW

Step 7: Confirm

✅ Social posts created:

📂 ~/vault/60_Articles/<client-id>/<slug>/

✅ post-facebook.md    ← Facebook post ready
✅ post-x.md           ← X/Twitter post ready
✅ post-ig.md          ← Instagram post ready

📋 NEXT: Load mm-publish-content → publish social posts

Output

Only creates files for platforms in social_platforms:

  • ~/vault/60_Articles/<client-id>/<slug>/post-facebook.md (if facebook)
  • ~/vault/60_Articles/<client-id>/<slug>/post-x.md (if x)
  • ~/vault/60_Articles/<client-id>/<slug>/post-ig.md (if instagram)
  • Social images in images/ subdirectory

Important Notes

  • published_url is REQUIRED — cannot create posts without it
  • social_platforms determines which posts to create — check clients-config.json
  • If social_platforms is empty, skip social post creation entirely
  • Social posts do NOT include CTA/contact info
  • Article URL should be naturally integrated into the post, not just appended
  • For Instagram, note that links aren't clickable in captions
  • Each post should complement the article, not duplicate it