New to Kestra?
Use blueprints to kickstart your first workflows.
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.
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.
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.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.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.??) on both fields let the flow run manually with inputs for older articles worth re-announcing.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.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.
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.title and url to the webhook URL.customFields entries, each rendered on its own line.