| name | social-publish-article |
| sheetId | 1.29 |
| description | Publishes a finalized post to your SOCIAL channels — Facebook, Threads & Instagram — via the Buffer API, with per-channel formatting, Instagram image support, and a preview-confirm gate before anything posts. Use when you say 'publish my post', 'post this to Threads/IG/FB', 'push this draft live to social', or 'schedule this post'. The SOCIAL publisher — not the website/blog one (seo-publish-article). |
| category | brand-marketing |
| project | social-publish-article |
| platform | claude |
| status | Done |
| author | Peter Tu |
| input | A finalized post/caption (plus a public image URL for Instagram), which channels to target, and whether to draft, post now, or schedule |
| process | Formats the copy per channel (Threads 500-char aware; Instagram needs a public image URL + caption), previews the exact copy for confirmation, then publishes through the Buffer API using your own token and connected channels |
| output | The post created in Buffer — as a draft, an immediate publish, or a scheduled post — with the Buffer post id and status returned per channel |
| synergy | [] |
Social Publish Article
npx skills add https://github.com/peter-tu-zynkr/zynkr-skill-builder --skill social-publish-article
Publish a finished post to your social channels — Facebook, Threads, and Instagram — through Buffer, so you don't have to open three apps or Buffer's dashboard. You bring your own Buffer access token and your already-connected channels; the skill formats the copy per platform, shows you exactly what will go out, and only publishes after you confirm. It can stage a draft in Buffer, post immediately, or schedule for later.
Configuration — connect Buffer (one-time)
This skill talks to your own Buffer account — nothing is shared or hardcoded.
- In Buffer, connect the channels you want (Facebook Page, Threads, Instagram Business/Creator account) and create a Buffer API access token (Buffer → Developers; choose the longest expiry offered).
- Copy
.secrets.env.example to .secrets.env (it's gitignored — keep it that way) and paste your token as BUFFER_ACCESS_TOKEN. Never put the token in chat or in SKILL.md.
- Discover your org + channel IDs with the helper, then paste them into
.secrets.env:
python3 scripts/buffer_post.py --list-channels
Fill in BUFFER_ORG_ID, BUFFER_CHANNEL_FACEBOOK, BUFFER_CHANNEL_THREADS, BUFFER_CHANNEL_INSTAGRAM.
The token is read only by the helper at runtime — it never appears in output or on the command line.
The one rule — confirm before anything goes public
Never publish (now / schedule) without showing the user the exact final copy per channel and getting an explicit "yes." Posting is public and hard to undo. The default mode is draft (stages the post in Buffer; nothing public) until the user says go live.
Step 1 — Gather the final post
Collect the finished copy from the user (pasted text, a file, or a doc). Confirm per channel:
- Facebook / Threads: the post text.
- Instagram: a caption and an image (see Step 3 — IG can't post text-only).
If the same copy is reused across channels, confirm that's intended; otherwise take per-channel text.
Step 2 — Pick channels and mode
- Channels:
facebook, threads, instagram — whichever apply. Text-only content skips Instagram unless an image is supplied.
- Mode:
draft (default — stage in Buffer for a final look), now (publish immediately), or schedule (needs an ISO timestamp).
Step 3 — Format per channel
- Facebook (text): full body + optional link; no hard length limit in practice.
- Threads (text, 500-char cap): Threads posts cap at 500 characters. If the copy fits, post once. If it's longer, split into ≤500-char chunks on sentence/paragraph boundaries and post each as a separate Threads post — this helper posts one Buffer post per call and does not chain a native reply-thread, so note the split in the preview.
- Instagram (image + caption): Instagram requires an image — text-only is rejected. Buffer takes a public image URL, not a file upload, so host the image at a reachable URL first (any public bucket/CDN) and pass that URL. The post text becomes the caption.
Step 4 — Preview & confirm ⟵ the gate
Show the user, clearly separated per channel: the exact text (with Threads char counts / chunk splits), and for Instagram the image URL + caption. State the mode explicitly ("mode: draft" vs "mode: NOW — goes public immediately"). Then ask: "Post these now? (yes / edit / cancel)" Only on an explicit yes proceed. "edit" → revise and re-preview. Default to NOT publishing live.
Step 5 — Publish via Buffer
Run the helper once per channel. It reads your token from .secrets.env; never put the token on the command line.
python3 scripts/buffer_post.py --channel facebook --text "<copy>" --mode draft
python3 scripts/buffer_post.py --channel threads --text "<chunk>" --mode draft
python3 scripts/buffer_post.py --channel instagram --image "<public-url>" --text "<caption>" --mode draft
Swap --mode draft → --mode now to publish immediately (only after the Step 4 "yes"), or --mode schedule --due 2026-06-20T09:00:00Z to queue. For a split Threads thread, call the threads line once per chunk, in order.
Read each result: OK post id=… status=… (success) or FAIL <ErrorType>: <message>. If any call fails, stop and report which channels posted and which didn't — a half-published set is worse left silent. On a daily-limit error, surface Buffer's posting limit rather than blind-retrying.
Outputs
- The post(s) created in Buffer — draft, immediate, or scheduled — with the Buffer post id + status per channel. For
now/schedule, Buffer performs the actual publish (you do not need your own scheduler).
Configuration files
.secrets.env — your Buffer token + channel IDs (gitignored; copy from .secrets.env.example). Never commit or reveal it.
scripts/buffer_post.py — the Buffer GraphQL helper. Modes: --list-channels, and --channel/--text/--image/--mode/--due.
Limitations
- One Buffer post per call — a Threads thread posts as separate posts, not a native reply-chain.
- Instagram needs a public image URL (no direct byte upload) and a Business/Creator account connected in Buffer.
- Buffer access tokens expire — pick the longest expiry and refresh before it lapses, or publishing silently 401s.
- Buffer's API returns no analytics — this skill publishes only.