← Back to blog
"n8nClaudeAInewsletter

Building a daily AI-curated newsletter with n8n and Claude: RSS ingestion, relevance scoring, and plain-text delivery via Resend

A daily AI-curated newsletter can run unattended in n8n — RSS ingestion, Claude relevance scoring, and Resend plain-text delivery in a 5-node workflow. Heres the complete setup.

A daily AI-curated newsletter that surfaces relevant content from multiple RSS feeds is a three-part problem: ingest, score, and deliver. n8n handles the scheduling and integrations; Claude handles the relevance judgment.

Architecture

Five nodes, running daily at 06:00:

1. Schedule Trigger — fires once daily, no configuration needed

2. HTTP Request — fetches 3-5 RSS feeds as raw XML using GET requests

3. Code node — parses XML to JavaScript objects, extracts title, link, pubDate, description; filters to items published in the last 24 hours

4. AI Agent (Claude) — passes each item to Claude with a system prompt defining the newsletter topic and scoring rubric; returns score + one-line summary as JSON

5. Resend node — assembles the filtered, scored items into a plain-text email body and sends via Resend API

Claude scoring prompt

The system prompt defines the newsletter's scope once:

`

You are a content curator for [newsletter name], a daily digest for [target reader] focused on [topic].

Score each article for relevance on a scale of 1-10, where 10 is directly on-topic and actionable,

and 1 is tangentially related or too general. Return JSON: {"score": number, "summary": "one sentence"}.

`

The user prompt passes the article title and description. After the Claude node, an IF node filters out items with score below 7 (adjust threshold based on feed quality and desired newsletter length).

Prompt caching

The system prompt is static — same for every item in the same run. Add cache_control: {type: "ephemeral"} to the system prompt message block. Claude caches the processed prompt for 5 minutes (long enough for a single workflow run processing 50-100 items). At Haiku pricing, this saves ~$0.05-0.08 per day at 100 items.

Resend delivery

Build the email body in a Code node after filtering:

`javascript

const items = $input.all();

const lines = items.map(i => • ${i.json.summary}\n ${i.json.link}).join('\n\n');

return [{ json: { subject: Daily digest — ${new Date().toDateString()}, text: lines } }];

`

Pass subject and text to the Resend node. Plain text avoids email client rendering issues and improves deliverability compared to HTML-heavy templates.

Threshold tuning

The score threshold is the most important parameter. Start at 7, run for a week, and read the output:

  • Newsletter consistently empty: lower to 6, or expand the scope of "relevant" in the system prompt
  • Newsletter too long (15+ items): raise to 8, or add a Code node that sorts by score and takes the top 5
  • The scoring prompt's phrasing matters more than the number. "Directly actionable for a solo operator" selects different content than "technically interesting for developers" even on the same feeds.

    FAQ

    Can I use the n8n Claude integration directly instead of the HTTP Request node?

    Yes — n8n has a native Claude AI node. The HTTP Request approach gives more control over the raw API call (including cache_control headers for prompt caching, which the native node doesn't expose as of May 2026).

    What RSS feeds work best?

    The system is feed-agnostic. Technical newsletters, industry blogs, and Substack RSS feeds (append /feed to any Substack URL) all work. Avoid feeds that only include descriptions without full content — scoring works better with a complete article description.

    How do I handle feeds with no new items?

    The Code node that filters to last-24-hours items returns an empty array when no new items exist. Add an IF node after the filter: items.length > 0 routes to Claude; the false branch routes to a Stop And Error or a log comment. An empty newsletter feels like an error to subscribers — better to skip the send entirely.