Hi Opus, I changed this one to Epic it has too much in it for it to be worked by Sonnet (or Flash High as an executable issue), lets discuss more
Goal
Backend half of the one-click gig promotion feature (spec approved by Josh 2026-07-16). A single admin-authed endpoint publishes an approved caption + image to two Meta surfaces. The JaMmusic UI half (Announce button + preview dialog) is a separate issue there and is blocked on this one.
Endpoint
POST /gig/:id/announce (admin Bearer auth, same guard as other admin routes):
- Body:
{ caption: string (HTML from TinyMCE), imageUrl?: string }.
- Convert caption HTML → plain text: keep paragraph/line breaks, flatten links to their raw URL, drop all styling (neither Meta API accepts HTML).
- Image: use
imageUrl if provided; else the gig's promoImageUrl; else the default — the backend's existing josh-maria.jpg template asset (already publicly served; both APIs require a public image URL).
- Leg 1 — Instagram: publish image + caption via the Instagram Content Publishing API (media container → publish) on Josh's IG business/creator account.
- Leg 2 — Facebook: publish the same image + caption to the Web Jam LLC Page feed via the Pages API (this page's feed renders on the web-jam.com homepage).
- Same caption text posted identically to both legs (by design — FB auto-linkifies URLs, hashtags are valid on both).
- On any leg success, stamp
announcedAt: Date on the gig record (add optional field to gig-schema). Re-announcing later is allowed and just updates the stamp.
- Response reports per-leg outcome (e.g.
{ instagram: {ok, id|error}, facebook: {ok, id|error} }) so the UI can surface partial failure. One leg failing must not block the other.
Config / tokens
Two long-lived Meta tokens as env vars (names the implementer's choice, documented in the PR): ① IG-linked account token with instagram_content_publish; ② Web Jam LLC page token with pages_manage_posts. No tokens in the repo. Endpoint returns a clear 500-with-message when config is missing.
Manual setup steps (Josh, before this can work in prod)
- Create a dedicated Meta developer app at https://developers.facebook.com (own app per the one-app-per-integration practice — do not reuse another integration's app).
- Add the Instagram Graph API + Pages products; add Josh as an app role (dev-mode use on own accounts avoids full App Review).
- Confirm the Instagram account is Business/Creator and linked to its Facebook Page.
- Generate the two long-lived tokens above and set them as Heroku config vars on webjamsalem — and save both to KeePass when generated.
(Exact dashboard click-paths intentionally not asserted here; Meta moves them around.)
Testing
Unit tests mock the Meta HTTP calls (no real posting from CI): conversion HTML→text, image fallback chain, per-leg error isolation, announcedAt stamping, auth guard. Coverage gate 90/90/80/80 applies. The IG→joshua.v.sherman-FB/Threads auto-share fan-out is intentionally unverifiable until the first real announce — note it in the PR body, do not attempt to test it.
Non-goals
No scheduler/cron of any kind (posts fire only on this endpoint call). No Facebook Event creation (Meta removed that API). No caption generation here — the UI generates and the human approves; this endpoint posts exactly what it receives.
Hi Opus, I changed this one to Epic it has too much in it for it to be worked by Sonnet (or Flash High as an executable issue), lets discuss more
Goal
Backend half of the one-click gig promotion feature (spec approved by Josh 2026-07-16). A single admin-authed endpoint publishes an approved caption + image to two Meta surfaces. The JaMmusic UI half (Announce button + preview dialog) is a separate issue there and is blocked on this one.
Endpoint
POST /gig/:id/announce(admin Bearer auth, same guard as other admin routes):{ caption: string (HTML from TinyMCE), imageUrl?: string }.imageUrlif provided; else the gig'spromoImageUrl; else the default — the backend's existingjosh-maria.jpgtemplate asset (already publicly served; both APIs require a public image URL).announcedAt: Dateon the gig record (add optional field to gig-schema). Re-announcing later is allowed and just updates the stamp.{ instagram: {ok, id|error}, facebook: {ok, id|error} }) so the UI can surface partial failure. One leg failing must not block the other.Config / tokens
Two long-lived Meta tokens as env vars (names the implementer's choice, documented in the PR): ① IG-linked account token with
instagram_content_publish; ② Web Jam LLC page token withpages_manage_posts. No tokens in the repo. Endpoint returns a clear 500-with-message when config is missing.Manual setup steps (Josh, before this can work in prod)
(Exact dashboard click-paths intentionally not asserted here; Meta moves them around.)
Testing
Unit tests mock the Meta HTTP calls (no real posting from CI): conversion HTML→text, image fallback chain, per-leg error isolation, announcedAt stamping, auth guard. Coverage gate 90/90/80/80 applies. The IG→joshua.v.sherman-FB/Threads auto-share fan-out is intentionally unverifiable until the first real announce — note it in the PR body, do not attempt to test it.
Non-goals
No scheduler/cron of any kind (posts fire only on this endpoint call). No Facebook Event creation (Meta removed that API). No caption generation here — the UI generates and the human approves; this endpoint posts exactly what it receives.