Newsletter Generator
Scrapes your blog and industry news, composes a weekly newsletter with human review.
scrapeaiemail
Source
/**
* Generates a weekly newsletter from scraped content and AI summarization.
*/
schedule weekly_newsletter {
label: "Weekly Newsletter"
cron: "0 8 * * 1"
timezone: "America/Los_Angeles"
}
workflow generate_newsletter {
label: "Generate Newsletter"
root {
type: code
label: "Start"
code: @ts {
return { week_of: new Date().toISOString().split("T")[0] }
}
outputSchema: @json {
{
"type": "object",
"properties": {
"week_of": { "type": "string" }
}
}
}
}
node scrape_blog {
type: scrape
label: "Scrape company blog"
url: @ts { return "https://byteslice.co/blog" }
onlyMainContent: true
formats: ["markdown"]
}
node scrape_industry {
type: scrape
label: "Scrape industry news"
url: @ts { return "https://news.ycombinator.com" }
onlyMainContent: true
formats: ["markdown"]
}
node compose {
type: ai
label: "Compose newsletter"
kind: object
model: "google/gemini-2.5-flash"
prompt: @ts {
const blog = context.nodes.scrape_blog.output
const news = context.nodes.scrape_industry.output
return "Write a weekly newsletter for the week of " + context.nodes.root.output.week_of + ".\n\nOur blog content:\n" + JSON.stringify(blog) + "\n\nIndustry news:\n" + JSON.stringify(news) + "\n\nFormat: intro paragraph, 3-5 highlights with brief summaries, closing note."
}
schema: @json {
{
"type": "object",
"required": ["subject", "body_html"],
"properties": {
"subject": { "type": "string" },
"body_html": { "type": "string" },
"preview_text": { "type": "string" }
}
}
}
temperature: 0.8
}
node review_draft {
type: code
label: "Review draft"
code: @ts { return {} }
review: {
enabled: true
title: "Review newsletter draft"
description: "Approve to send this week's newsletter, or discard to stop the run. The draft is in the compose node's output."
schema: @json {
{
"type": "object",
"properties": {
"notes": { "type": "string", "title": "Notes" }
},
"additionalProperties": false
}
}
actions: [
{ id: "send", label: "Send", outcome: "approve" },
{ id: "discard", label: "Discard", outcome: "reject" }
]
}
}
node send_newsletter {
type: email
label: "Send newsletter"
from: @ts { return "[email protected]" }
to: @ts { return "[email protected]" }
subject: @ts { return context.nodes.compose.output.subject }
html: @ts { return context.nodes.compose.output.body_html }
}
flow {
root -> scrape_blog
root -> scrape_industry
scrape_blog -> compose
scrape_industry -> compose
compose -> review_draft
review_draft -> send_newsletter
}
}
trigger on_weekly {
schedule:weekly_newsletter -> generate_newsletter
enabled: true
}
Flow
Trigger to workflow
weekly_newsletterschedule
generate_newsletter
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Workflow nodes
CODE
Code Node
Start
SCRAPE
Scrape Node
Scrape company blog
SCRAPE
Scrape Node
Scrape industry news
AI
AI Node
Compose newsletter
CODE
Code Node
Review draft
EMAIL
Email Node
Send newsletter
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.