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
This commit is contained in:
276
skills/mm-social-writer/SKILL.md
Normal file
276
skills/mm-social-writer/SKILL.md
Normal file
@@ -0,0 +1,276 @@
|
||||
---
|
||||
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
|
||||
Reference in New Issue
Block a user