BlueskyExecution icon
DiscordIncomingWebhook icon
Webhook icon

Announce New Blog Articles on Bluesky from a CMS Webhook

Announce new blog posts on Bluesky automatically with Kestra. A CMS webhook posts the title and link as a skeet and confirms each announcement in Discord.

Categories
Business

An article nobody hears about might as well be a draft. This blueprint wires the CMS publish button directly to your community channel: when an article goes live, the CMS fires a webhook into Kestra, io.kestra.plugin.bluesky.BlueskyExecution posts an execution-notification skeet carrying the title and link, and Discord confirms internally that the announcement went out. On Bluesky, where developer readers follow projects directly rather than through an algorithm, the announcement post is often the article's single biggest traffic source, so it should never depend on someone remembering to write it.

The skeet is public and immediate, so this flow is intentionally a relay, not an author: the title and URL come verbatim from the CMS payload, and editorial review happens where it belongs, before the publish button is pressed. The post also wears its automation openly. Every skeet opens with the execution state and flow id and closes with a link to the execution, so the community sees exactly which pipeline announced the article.

How it works

  1. The cms_webhook trigger (io.kestra.plugin.core.trigger.Webhook) receives the publish event with title and url in the JSON body. Most headless CMSes and static site pipelines can fire such a hook on publish.
  2. post_announcement (io.kestra.plugin.bluesky.BlueskyExecution) authenticates with the handle and app password from secrets and posts the announcement, carrying the article title in customMessage and the URL as a customFields entry.
  3. The plugin always renders its built-in execution template: the post opens with the execution state and flow id, for example RUNNING: company.team/bluesky-blog-published-announcer, then the custom message, one key: value line per custom field, and a closing link to the execution in the Kestra UI. Bluesky's 300-grapheme limit applies to that whole rendered post, so the CMS payload should carry a display title, not an SEO title.
  4. Null-coalescing fallbacks (??) on both fields let the flow run manually with inputs for older articles worth re-announcing.
  5. confirm_internally posts the title and execution id to Discord, and the errors block raises a distinct alert when posting failed, because a live but unannounced article is easy to miss.

What you get

  • Announcements published the same second as the article, with zero manual posting.
  • A consistent announcement format across every article and author.
  • Internal Discord confirmation plus a failure alert, so the content team always knows the public state.
  • A manual re-announcement path through flow inputs for evergreen articles.

Who it's for

  • Content and developer relations teams announcing articles to a Bluesky audience.
  • Engineering blogs run on headless CMSes or static site generators with publish hooks.
  • Teams consolidating scattered social posting scripts into observable orchestration.

Why orchestrate this with Kestra

CMS-native social integrations are opaque: when they fail, nobody is told, and the app password lives in a plugin settings page. In Kestra the announcement is an execution with history, the credential is a managed secret, a transient Bluesky API error is retryable, and a failure posts to Discord instead of vanishing. The same flow also becomes the natural place to fan out to more channels later.

Prerequisites

  • A Bluesky account for the blog or project and an app password created under Settings, never the account password.
  • A CMS or publishing pipeline able to POST JSON on publish.
  • A Discord incoming webhook for the internal content channel.

Secrets

  • BLUESKY_IDENTIFIER: the Bluesky handle, for example yourblog.bsky.social.
  • BLUESKY_APP_PASSWORD: an app password generated in Bluesky settings.
  • DISCORD_WEBHOOK_URL: Discord incoming webhook URL.

Quick start

  1. Add the three secrets to your Kestra namespace.
  2. Execute the flow manually with a test title and URL, and check the skeet and the Discord confirmation.
  3. Replace the webhook key with a strong random value.
  4. Configure your CMS publish hook to POST title and url to the webhook URL.

How to extend

  • Add the author or a one-line teaser as extra scalar fields in the CMS payload and surface them as additional customFields entries, each rendered on its own line.
  • Announce releases through the same pattern, as shown in the release notes blueprint.
  • Roll announced articles into a weekly recap, as shown in the changelog digest blueprint.
  • Add a delay task before posting to announce at your audience's peak hour instead of publish time.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.