From b0fb05f93ac8db4627207b4e68bc03024f2e0c18 Mon Sep 17 00:00:00 2001 From: Doug Hatcher Date: Mon, 18 May 2026 21:01:28 -0400 Subject: [PATCH] fix(blog-publish): pass mp-syndicate-to to actually cross-post to LinkedIn micro.blog's Micropub API does NOT honor the account-level cross-post defaults for API-posted entries. Each post must explicitly opt in via mp-syndicate-to[]=. Without it, the note lands on the timeline but LinkedIn/Mastodon/Bluesky/Threads stay silent. - microblog-poster.js: read MICROBLOG_SYNDICATE_TO (comma-separated UIDs) and emit one mp-syndicate-to[]= field per destination. - blog-publish.yml: default MICROBLOG_SYNDICATE_TO=linkedin if the repo variable is unset. Override by setting vars.MICROBLOG_SYNDICATE_TO (e.g. "linkedin,bluesky"). Discover available UIDs at GET https://micro.blog/micropub?q=syndicate-to. --- .github/workflows/blog-publish.yml | 3 +++ apps/editorial-loop/lib/microblog-poster.js | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/.github/workflows/blog-publish.yml b/.github/workflows/blog-publish.yml index c03ff71..e61837a 100644 --- a/.github/workflows/blog-publish.yml +++ b/.github/workflows/blog-publish.yml @@ -57,6 +57,9 @@ jobs: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} MICROBLOG_APP_TOKEN: ${{ secrets.MICROBLOG_APP_TOKEN }} MICROBLOG_DESTINATION_UID: ${{ vars.MICROBLOG_DESTINATION_UID }} + # Comma-separated UIDs from GET /micropub?q=syndicate-to (linkedin, mastodon, bluesky, threads). + # Defaults to 'linkedin' if the repo variable is unset. + MICROBLOG_SYNDICATE_TO: ${{ vars.MICROBLOG_SYNDICATE_TO || 'linkedin' }} POST_PATH: ${{ steps.post.outputs.path }} BASE_URL: https://doughatcher.com run: node apps/editorial-loop/publish.js diff --git a/apps/editorial-loop/lib/microblog-poster.js b/apps/editorial-loop/lib/microblog-poster.js index 46c87d1..7f3a802 100644 --- a/apps/editorial-loop/lib/microblog-poster.js +++ b/apps/editorial-loop/lib/microblog-poster.js @@ -76,6 +76,17 @@ export async function postToMicroblog(text) { if (process.env.MICROBLOG_DESTINATION_UID) { params.append('mp-destination', process.env.MICROBLOG_DESTINATION_UID); } + // micro.blog requires per-post opt-in for syndication — it does NOT honor + // the account-level cross-post default for API-posted entries. Pass each + // destination UID as a separate mp-syndicate-to[] form field. + // Discover UIDs at GET /micropub?q=syndicate-to (e.g. "linkedin", "mastodon"). + const syndicateTo = (process.env.MICROBLOG_SYNDICATE_TO || '') + .split(',') + .map(s => s.trim()) + .filter(Boolean); + for (const uid of syndicateTo) { + params.append('mp-syndicate-to[]', uid); + } const res = await fetch('https://micro.blog/micropub', { method: 'POST',