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

277 lines
7.7 KiB
Markdown

---
name: mm-social-writer
description: >
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:
```python
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:**
```python
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)
```markdown
---
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**
```markdown
---
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
```markdown
---
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