FormView on GitHub
Changelog Announcer
Takes a changelog entry and generates announcements for email, Slack, and social.
aihttpresend
Source
/**
* Takes a changelog entry and generates an announcement
* for multiple channels: email, Slack, and social media.
*/
form changelog_entry {
label: "Changelog Entry"
schema: @json {
{
"type": "object",
"required": ["version", "changes"],
"properties": {
"version": { "type": "string", "title": "Version" },
"changes": { "type": "string", "title": "What Changed" },
"breaking": { "type": "boolean", "title": "Breaking Changes?" }
}
}
}
}
secret announce_config {
vars: [SLACK_WEBHOOK_URL]
}
graph announce_release {
label: "Announce Release"
root {
type: code
label: "Extract changelog"
code: @ts { return context.nodes.root.input }
outputSchema: @json {
{
"type": "object",
"properties": {
"version": { "type": "string" },
"changes": { "type": "string" },
"breaking": { "type": "boolean" }
}
}
}
}
node generate_announcement {
type: ai
label: "Generate announcement"
kind: object
model: "google/gemini-2.5-flash"
prompt: @ts {
const entry = context.nodes.root.output
return "Generate release announcements for version " + entry.version + ".\n\nChanges:\n" + entry.changes + "\n\nBreaking changes: " + (entry.breaking ? "yes" : "no") + "\n\nGenerate: a short Slack message (2-3 lines), an email body (1 paragraph), and a tweet (under 280 chars)."
}
schema: @json {
{
"type": "object",
"required": ["slack_message", "email_body", "tweet"],
"properties": {
"slack_message": { "type": "string" },
"email_body": { "type": "string" },
"tweet": { "type": "string" }
}
}
}
temperature: 0.7
}
node post_slack {
type: http
label: "Post to Slack"
method: "POST"
url: @ts { return context.secrets.announce_config.SLACK_WEBHOOK_URL }
body: @ts {
return JSON.stringify({
text: context.nodes.generate_announcement.output.slack_message
})
}
secrets: {
announce_config: [SLACK_WEBHOOK_URL]
}
}
node send_email {
type: resend
label: "Send email announcement"
from: @ts { return "[email protected]" }
to: @ts { return "[email protected]" }
subject: @ts { return "Release " + context.nodes.root.output.version }
text: @ts { return context.nodes.generate_announcement.output.email_body }
}
node result {
type: code
label: "Compile results"
code: @ts {
return {
version: context.nodes.root.output.version,
tweet_draft: context.nodes.generate_announcement.output.tweet,
tweet_length: context.nodes.generate_announcement.output.tweet.length,
slack_sent: true,
email_sent: true
}
}
}
flow {
root -> generate_announcement
generate_announcement -> post_slack
generate_announcement -> send_email
post_slack -> result
send_email -> result
}
}
trigger on_changelog {
form:changelog_entry -> announce_release
enabled: true
}
Flow
Trigger → graph
Graph nodes