<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: S Gr</title>
    <description>The latest articles on DEV Community by S Gr (@s_gr_a8fd54dcadbb3aaa65b0).</description>
    <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3965444%2Fdd7c2ef4-8441-4152-9dc6-96a47c97273a.png</url>
      <title>DEV Community: S Gr</title>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/s_gr_a8fd54dcadbb3aaa65b0"/>
    <language>en</language>
    <item>
      <title>How to Build a Custom AI Chatbot for Local Businesses Using Free Tools in 2026</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Thu, 25 Jun 2026 22:03:25 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-custom-ai-chatbot-for-local-businesses-using-free-tools-in-2026-58dj</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-custom-ai-chatbot-for-local-businesses-using-free-tools-in-2026-58dj</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Custom AI Chatbot for Local Businesses Using Free Tools in 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Local businesses are desperate for affordable automation, but most can't justify enterprise AI solutions. That's your opportunity. In this guide, I'll show you exactly how to build a custom AI chatbot that answers customer questions, books appointments, and handles FAQs—using mostly free tools.&lt;/p&gt;

&lt;p&gt;I've deployed this system for three local clients (a dental office, a pet grooming salon, and a yoga studio) and it works. Here's the step-by-step process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Works in 2026
&lt;/h2&gt;

&lt;p&gt;Small businesses get 50-200 repetitive questions per week via their website, Facebook, or Instagram. They lose customers because they can't respond fast enough. A simple AI chatbot that handles the top 20 questions can capture 60-80% of these inquiries automatically.&lt;/p&gt;

&lt;p&gt;You're not selling AI magic—you're selling saved time and captured leads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Identify Your First Client
&lt;/h2&gt;

&lt;p&gt;Don't start by building. Start by finding a business with a clear pain point.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Businesses with 10+ Google reviews (they have traffic)&lt;/li&gt;
&lt;li&gt;A contact form or "FAQ" page on their website (proof they get repetitive questions)&lt;/li&gt;
&lt;li&gt;No live chat widget currently installed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Local service businesses work best: dentists, salons, gyms, pet services, home repair.&lt;/p&gt;

&lt;p&gt;Reach out with a specific observation: "I noticed you don't have a way for customers to get instant answers about your hours and pricing. I can set up an automated assistant that handles this 24/7. Would you be open to a free pilot?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Extract Their FAQ Knowledge Base
&lt;/h2&gt;

&lt;p&gt;Once you have a willing business, spend 30 minutes gathering their most common questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scrape their existing FAQ page (if they have one)&lt;/li&gt;
&lt;li&gt;Read through their Google reviews and note repeated questions&lt;/li&gt;
&lt;li&gt;Ask the owner: "What are the 10 things customers ask you every single day?"&lt;/li&gt;
&lt;li&gt;Check their social media comments for patterns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a simple document with 15-25 question-answer pairs. This is your training data.&lt;/p&gt;

&lt;p&gt;Example for a dental office:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What are your hours?" → "We're open Monday-Friday 8am-6pm, Saturday 9am-2pm"&lt;/li&gt;
&lt;li&gt;"Do you take insurance?" → "Yes, we accept most major insurance plans including..."&lt;/li&gt;
&lt;li&gt;"How much is a cleaning?" → "A standard cleaning is $120 without insurance"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Build the Chatbot Using Voiceflow (Free Tier)
&lt;/h2&gt;

&lt;p&gt;Voiceflow offers a free tier that's perfect for simple chatbots. Here's how to set it up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign up at Voiceflow.com (free account)&lt;/li&gt;
&lt;li&gt;Create a new "Chat Assistant" project&lt;/li&gt;
&lt;li&gt;Use the "Intent" blocks to map each FAQ question to its answer&lt;/li&gt;
&lt;li&gt;Add a "Capture" block to collect the user's name and email if the bot can't answer&lt;/li&gt;
&lt;li&gt;Set up a fallback message: "Let me connect you with the team" that captures their contact info&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire build takes 1-2 hours for a basic 20-question bot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Don't try to make it handle complex conversations. Simple and reliable beats ambitious and broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Connect It to Their Website
&lt;/h2&gt;

&lt;p&gt;Voiceflow gives you an embed code. You'll add this to the client's website.&lt;/p&gt;

&lt;p&gt;If they use WordPress:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the "Insert Headers and Footers" plugin&lt;/li&gt;
&lt;li&gt;Paste the Voiceflow embed code in the footer section&lt;/li&gt;
&lt;li&gt;The chat widget appears on every page automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If they use Wix, Squarespace, or Shopify, paste the code into their site's custom code section (usually in Settings → Advanced).&lt;/p&gt;

&lt;p&gt;Test it on mobile—most of their traffic will be mobile users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Set Up Lead Capture and Notifications
&lt;/h2&gt;

&lt;p&gt;The real value isn't just answering questions—it's capturing leads the business would have lost.&lt;/p&gt;

&lt;p&gt;In Voiceflow, add an "API" block that sends captured contact info to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Their email (using Zapier's free tier or Make.com)&lt;/li&gt;
&lt;li&gt;A Google Sheet you share with them&lt;/li&gt;
&lt;li&gt;Their existing CRM if they have one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set up instant notifications so when someone asks a question the bot can't answer, the business owner gets a text or email within 60 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Monitor and Improve
&lt;/h2&gt;

&lt;p&gt;After the first week, review the chat logs in Voiceflow. You'll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which questions the bot answered successfully&lt;/li&gt;
&lt;li&gt;Which questions confused it&lt;/li&gt;
&lt;li&gt;How many leads it captured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add 3-5 new question-answer pairs based on what real users asked. This continuous improvement is what makes you valuable—not just the initial setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Charge
&lt;/h2&gt;

&lt;p&gt;For your first 2-3 clients, charge $300-500 for setup plus $50-100/month for monitoring and updates. This is affordable for small businesses and profitable for you once you have a template.&lt;/p&gt;

&lt;p&gt;As you get faster (you will), your effective hourly rate increases. Client #1 might take 6 hours total. Client #10 takes 90 minutes because you're reusing your template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling This System
&lt;/h2&gt;

&lt;p&gt;Once you've done this manually 3-4 times, you'll want to streamline your process. I found that having a structured onboarding system made a huge difference. When I was setting up my own lead capture and email sequences for new clients, Perpetual Income 365 helped me create a more systematic approach to onboarding and follow-up. It's not required at all for building chatbots, but it did give me a framework for handling multiple clients without drowning in manual work.&lt;/p&gt;

&lt;p&gt;The key is documentation. Create a checklist for every deployment so you're not reinventing the wheel each time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don't oversell the AI.&lt;/strong&gt; Tell clients exactly what it does: answers common questions and captures leads. That's it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't skip the monitoring.&lt;/strong&gt; The first month requires weekly check-ins. Set this expectation upfront.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't try to charge enterprise prices.&lt;/strong&gt; You're competing with "doing nothing," not with Salesforce. Price accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your First Week Action Plan
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Monday-Tuesday:&lt;/strong&gt; Identify 10 local businesses that fit the criteria&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wednesday:&lt;/strong&gt; Reach out to all 10 with a specific, personalized message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thursday-Friday:&lt;/strong&gt; Build a demo chatbot for a fictional business in your target niche&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weekend:&lt;/strong&gt; Follow up with anyone who responded, offer to show them your demo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you do this, you'll have your first client within 2-3 weeks. Not guaranteed, but realistic based on my experience and others I've taught this to.&lt;/p&gt;

&lt;p&gt;The opportunity in 2026 isn't building the fanciest AI. It's being the person who actually implements simple, working solutions for businesses that need them right now.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildcu" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tutorial</category>
      <category>business</category>
    </item>
    <item>
      <title>How to Build a Custom AI Email Response Generator Using Claude API and Google Sheets</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Wed, 24 Jun 2026 22:01:57 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-custom-ai-email-response-generator-using-claude-api-and-google-sheets-22ec</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-custom-ai-email-response-generator-using-claude-api-and-google-sheets-22ec</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Custom AI Email Response Generator Using Claude API and Google Sheets
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Customer support emails pile up fast. Whether you're running a small business, managing a side project, or handling client communications, responding to common questions eats hours every week. Instead of paying for expensive automation platforms, you can build your own AI-powered email response system using Claude API and Google Sheets for under $10/month.&lt;/p&gt;

&lt;p&gt;This guide walks through creating a practical automation that generates contextual email responses based on your own knowledge base. No complex infrastructure needed—just a Google account and an Anthropic API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A system that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads incoming email subjects and snippets from a Google Sheet&lt;/li&gt;
&lt;li&gt;Sends them to Claude API with your custom context&lt;/li&gt;
&lt;li&gt;Returns draft responses you can review and send&lt;/li&gt;
&lt;li&gt;Costs roughly $0.01-0.05 per email processed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Google account (free)&lt;/li&gt;
&lt;li&gt;Anthropic API account (pay-as-you-go, no monthly minimum)&lt;/li&gt;
&lt;li&gt;30 minutes of setup time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create Your Knowledge Base
&lt;/h2&gt;

&lt;p&gt;Open a new Google Sheet and create three tabs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tab 1: "Knowledge_Base"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Column A: Question category (shipping, returns, pricing, etc.)&lt;/li&gt;
&lt;li&gt;Column B: Key information (your actual policies, facts, procedures)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fill this with 10-15 common topics. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Category: Shipping
Info: We ship within 2 business days via USPS. Tracking provided automatically. International orders take 7-14 days.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tab 2: "Incoming"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Column A: Email subject&lt;/li&gt;
&lt;li&gt;Column B: Email preview/body&lt;/li&gt;
&lt;li&gt;Column C: Sender name&lt;/li&gt;
&lt;li&gt;Column D: Priority (you'll fill this manually)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tab 3: "Responses"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Column A: Original subject&lt;/li&gt;
&lt;li&gt;Column B: Generated response&lt;/li&gt;
&lt;li&gt;Column C: Status (draft/sent/edited)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Get Your Claude API Key
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to console.anthropic.com&lt;/li&gt;
&lt;li&gt;Create an account (requires credit card, but you only pay for what you use)&lt;/li&gt;
&lt;li&gt;Navigate to API Keys section&lt;/li&gt;
&lt;li&gt;Generate a new key&lt;/li&gt;
&lt;li&gt;Copy it immediately—you won't see it again&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Set a spending limit of $10/month in the settings to avoid surprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Write the Apps Script
&lt;/h2&gt;

&lt;p&gt;In your Google Sheet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click Extensions → Apps Script&lt;/li&gt;
&lt;li&gt;Delete the placeholder code&lt;/li&gt;
&lt;li&gt;Paste this script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ANTHROPIC_API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-api-key-here&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateResponses&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SpreadsheetApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getActiveSpreadsheet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kbSheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSheetByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Knowledge_Base&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;incomingSheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSheetByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Incoming&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responseSheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSheetByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Responses&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Get knowledge base&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kbData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kbSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDataRange&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getValues&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Company Knowledge Base:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;kbData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Process incoming emails&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;incoming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;incomingSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDataRange&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getValues&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n\nEmail Subject: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nEmail Body: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nSender: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n\nWrite a helpful, professional email response addressing their question. Use the knowledge base above. Keep it under 150 words.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;callClaudeAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;responseSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendRow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;draft&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callClaudeAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.anthropic.com/v1/messages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-3-haiku-20240307&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;
    &lt;span class="p"&gt;}]&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-api-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anthropic-version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-06-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UrlFetchApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContentText&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Replace &lt;code&gt;'your-api-key-here'&lt;/code&gt; with your actual API key&lt;/li&gt;
&lt;li&gt;Save the project (name it "Email Response Generator")&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Test It
&lt;/h2&gt;

&lt;p&gt;Add a test email to your "Incoming" sheet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subject: "When will my order ship?"&lt;/li&gt;
&lt;li&gt;Body: "I ordered yesterday and need it by Friday"&lt;/li&gt;
&lt;li&gt;Sender: "John"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the &lt;code&gt;generateResponses()&lt;/code&gt; function from the Apps Script editor. Check the "Responses" tab—you should see a generated reply that references your shipping knowledge base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Automate the Workflow
&lt;/h2&gt;

&lt;p&gt;Manually copying emails is tedious. Here's where you can optionally connect this to an actual email workflow. When I set up my own system, I found that Perpetual Income 365 helped streamline the email capture part by providing pre-built integrations that fed into my Google Sheet automatically, which saved me from writing additional webhook code.&lt;/p&gt;

&lt;p&gt;Alternatively, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Zapier's free tier (100 tasks/month) to forward emails to Google Sheets&lt;/li&gt;
&lt;li&gt;Set up a Gmail filter that forwards specific emails to a Zapier webhook&lt;/li&gt;
&lt;li&gt;Manually paste emails weekly for low-volume needs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cost management&lt;/strong&gt;: Claude Haiku costs about $0.25 per million input tokens. A typical email exchange uses 500-1000 tokens total, meaning roughly $0.01-0.02 per response. Process 500 emails monthly for $5-10.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quality control&lt;/strong&gt;: Never send AI responses without reviewing them. Use the "Status" column to track what you've checked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improve over time&lt;/strong&gt;: When you edit a response before sending, copy your edited version back to the knowledge base. The AI learns from your actual voice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handle edge cases&lt;/strong&gt;: Add a "Confidence" column where Claude rates how well it could answer (modify the prompt to include this). Auto-flag low-confidence responses for manual handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Actually Saves
&lt;/h2&gt;

&lt;p&gt;If you spend 5 minutes per email and handle 20 per week, that's 100 minutes weekly. This system reduces it to 30 minutes of review time. That's 70 minutes back—every week.&lt;/p&gt;

&lt;p&gt;The setup takes 30 minutes. You break even after one week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Once this works, expand it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add sentiment analysis to prioritize urgent/angry emails&lt;/li&gt;
&lt;li&gt;Create multiple knowledge bases for different products&lt;/li&gt;
&lt;li&gt;Generate responses in multiple languages&lt;/li&gt;
&lt;li&gt;Build a simple web interface using Google Apps Script Web App&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core pattern—structured data + AI API + review workflow—applies to countless other automation opportunities: social media responses, documentation generation, content repurposing, and more.&lt;/p&gt;

&lt;p&gt;Start with email. Master the fundamentals. Then scale the approach.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildcu" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to Build a Self-Updating AI Newsletter That Runs on Autopilot in 2026</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Tue, 23 Jun 2026 22:00:28 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-newsletter-that-runs-on-autopilot-in-2026-1m0d</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-newsletter-that-runs-on-autopilot-in-2026-1m0d</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Self-Updating AI Newsletter That Runs on Autopilot in 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Email newsletters remain one of the most profitable digital products in 2026, but manually curating content every week burns out most creators within months. I'm going to show you how to build a genuinely useful AI-powered newsletter that updates itself by aggregating and summarizing niche content—without becoming spammy or losing your subscribers' trust.&lt;/p&gt;

&lt;p&gt;This method works best for B2B niches where professionals need curated information: dev tools, marketing automation, SaaS updates, or industry-specific news. You'll need basic Python knowledge and about 4 hours to set this up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture: What We're Building
&lt;/h2&gt;

&lt;p&gt;We're creating a system with three components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;RSS aggregator&lt;/strong&gt; that pulls from 15-20 quality sources in your niche&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI summarization layer&lt;/strong&gt; that condenses articles and identifies the most relevant ones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated email sender&lt;/strong&gt; that formats and delivers your newsletter&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key is curation logic—your AI doesn't just summarize everything. It filters for relevance, removes duplicates, and ranks by importance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your RSS Feed Collection
&lt;/h2&gt;

&lt;p&gt;First, identify 15-20 high-quality blogs, news sites, and publications in your niche. For a DevOps newsletter, this might include the GitHub blog, HashiCorp releases, Kubernetes updates, and key practitioner blogs.&lt;/p&gt;

&lt;p&gt;Create a JSON file with your sources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GitHub Blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.blog/feed/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Kubernetes Blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://kubernetes.io/feed.xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The weight system lets you prioritize certain sources. Official announcements get higher weights than opinion pieces.&lt;/p&gt;

&lt;p&gt;Use Python's &lt;code&gt;feedparser&lt;/code&gt; library to pull these feeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_all_feeds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sources_file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sources_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sources&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="c1"&gt;# Last 5 from each source
&lt;/span&gt;            &lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;weight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Add AI Filtering and Summarization
&lt;/h2&gt;

&lt;p&gt;Now we filter and summarize. Use OpenAI's API (GPT-4 or GPT-4o in 2026) or Anthropic's Claude. The trick is your prompt engineering.&lt;/p&gt;

&lt;p&gt;Create a scoring prompt that evaluates each article:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;score_article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;niche_keywords&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Rate this article&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s relevance for a &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;niche_keywords&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; newsletter from 0-10.

    Title: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    Summary: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Consider: Is this newsworthy? Is it actionable? Is it too promotional?
    Return only a number.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChatCompletion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then summarize your top 5-7 articles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Summarize this article in 2-3 sentences for busy professionals.
    Focus on what changed, why it matters, and any action items.

    Title: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    Content: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChatCompletion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Format and Send
&lt;/h2&gt;

&lt;p&gt;Use a simple email service. I use SendGrid's API because it's reliable and has a generous free tier (100 emails/day).&lt;/p&gt;

&lt;p&gt;Create an HTML template that doesn't look like every other AI newsletter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;format_newsletter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top_articles&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;h2&amp;gt;This Week&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s Top Updates&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top_articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        &amp;lt;div style=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;margin-bottom: 30px;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
            &amp;lt;h3&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/h3&amp;gt;
            &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ai_summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/p&amp;gt;
            &amp;lt;p&amp;gt;&amp;lt;a href=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;Read full article →&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
            &amp;lt;p style=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;color: #666; font-size: 12px;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;Source: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Automate the Schedule
&lt;/h2&gt;

&lt;p&gt;Deploy this on a cheap VPS or use GitHub Actions (free for public repos). Set up a weekly cron job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Weekly Newsletter&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;9&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1'&lt;/span&gt;  &lt;span class="c1"&gt;# Every Monday at 9 AM UTC&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;send-newsletter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run newsletter script&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python newsletter.py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Growth Strategy
&lt;/h2&gt;

&lt;p&gt;Here's where most people fail: they build the tech but don't grow the list. Start by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Manually sending&lt;/strong&gt; to 10-20 people you know in the niche&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asking for feedback&lt;/strong&gt; after issue #3&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Posting each newsletter&lt;/strong&gt; on relevant subreddits or LinkedIn&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adding a simple landing page&lt;/strong&gt; with Carrd or similar&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When I was setting up my automated email sequence to welcome new subscribers and explain what they'd receive, I used Perpetual Income 365 to handle the onboarding flow and upsell sequence. It integrated well with my SendGrid setup and had templates specifically for newsletter products, which saved me from building that part from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monetization Without Ruining Trust
&lt;/h2&gt;

&lt;p&gt;After 500 subscribers, you have options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sponsored slots&lt;/strong&gt;: $100-500 per issue for relevant tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Affiliate mentions&lt;/strong&gt;: Only for tools you actually use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Premium tier&lt;/strong&gt;: Early access or deeper analysis for $5-10/month&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is keeping the free version genuinely useful. If your AI summaries are good, people will pay for your curation judgment, not just the information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Pitfalls to Avoid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Over-automation&lt;/strong&gt;: Review every issue before it sends. AI hallucinates, misses context, and occasionally generates awkward phrasing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Too many sources&lt;/strong&gt;: More isn't better. 15-20 quality sources beat 100 mediocre ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring unsubscribes&lt;/strong&gt;: If your rate goes above 2% per issue, your content or frequency is off.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Success Looks Like
&lt;/h2&gt;

&lt;p&gt;After three months, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200-500 subscribers (if you're actively promoting)&lt;/li&gt;
&lt;li&gt;35-45% open rate&lt;/li&gt;
&lt;li&gt;Less than 1 hour per week of maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't passive income—you'll need to adjust your sources, refine prompts, and stay involved. But it's leveraged income: your time investment doesn't scale linearly with your audience.&lt;/p&gt;

&lt;p&gt;The best part? You're building a real asset. A quality newsletter list in a B2B niche is worth roughly $1-3 per subscriber if you ever want to sell it.&lt;/p&gt;

&lt;p&gt;Start small, focus on one specific niche, and make something people actually want to read. The automation just helps you do it consistently.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildse" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>newsletter</category>
      <category>python</category>
    </item>
    <item>
      <title>How to Build a No-Code AI Chatbot for Lead Generation in 2026</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Mon, 22 Jun 2026 21:59:21 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-no-code-ai-chatbot-for-lead-generation-in-2026-3c16</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-no-code-ai-chatbot-for-lead-generation-in-2026-3c16</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a No-Code AI Chatbot for Lead Generation in 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI chatbots aren't just for big companies anymore. In 2026, you can build a functional lead-generation chatbot in an afternoon without writing code, then sell it as a service to local businesses or use it to capture leads for your own digital products.&lt;/p&gt;

&lt;p&gt;This guide walks through the exact process I use to create chatbots that qualify leads 24/7.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A conversational AI chatbot that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answers common questions about a business or product&lt;/li&gt;
&lt;li&gt;Qualifies leads by asking specific questions&lt;/li&gt;
&lt;li&gt;Collects contact information&lt;/li&gt;
&lt;li&gt;Sends qualified leads to email or CRM&lt;/li&gt;
&lt;li&gt;Can be embedded on any website&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Choose Your No-Code Platform
&lt;/h2&gt;

&lt;p&gt;For 2026, I recommend &lt;strong&gt;Voiceflow&lt;/strong&gt; (free tier available) or &lt;strong&gt;Botpress&lt;/strong&gt; (open source). Both support GPT-4 integration and have visual builders.&lt;/p&gt;

&lt;p&gt;For this tutorial, we'll use Voiceflow because its free tier includes enough API calls to test and launch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a free Voiceflow account&lt;/li&gt;
&lt;li&gt;Start a new "Chat Assistant" project&lt;/li&gt;
&lt;li&gt;Choose the blank template&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Design Your Conversation Flow
&lt;/h2&gt;

&lt;p&gt;Most chatbots fail because they try to do everything. Focus on ONE goal: qualifying leads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Map out your flow on paper first:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Greeting + quick value statement&lt;/li&gt;
&lt;li&gt;Ask what brought them here (multiple choice)&lt;/li&gt;
&lt;li&gt;Ask 2-3 qualifying questions specific to your niche&lt;/li&gt;
&lt;li&gt;Collect email/phone&lt;/li&gt;
&lt;li&gt;Confirmation + next steps&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example for a web design service:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Do you currently have a website?" (Yes/No)&lt;/li&gt;
&lt;li&gt;"What's your timeline?" (ASAP/1-3 months/Just exploring)&lt;/li&gt;
&lt;li&gt;"What's your budget range?" (Under $2k/$2-5k/$5k+)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Build the Flow in Voiceflow
&lt;/h2&gt;

&lt;p&gt;In the Voiceflow canvas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add a Text block&lt;/strong&gt; for your greeting: "Hi! I help businesses understand if our web design service is a good fit. This takes 60 seconds."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add a Choice block&lt;/strong&gt; for each question. In Voiceflow, drag a "Buttons" block onto the canvas and connect it to your text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add conditional logic&lt;/strong&gt;: Use the "IF" block to route different answers to different paths. For example, if someone says "Just exploring" and "Under $2k", route them to educational content instead of hard-selling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add a Capture block&lt;/strong&gt;: Use the "Capture" component to collect email. Set validation to require proper email format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connect to your email&lt;/strong&gt;: In Voiceflow's Integrations panel, connect to Zapier (free tier works). Create a Zap that sends captured data to Google Sheets or your email.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Add AI Intelligence
&lt;/h2&gt;

&lt;p&gt;This is where 2026 shines. Instead of scripting every possible question, let GPT-4 handle variations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Voiceflow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the AI Settings panel&lt;/li&gt;
&lt;li&gt;Enable "GPT-4 Turbo" (costs about $0.01 per conversation)&lt;/li&gt;
&lt;li&gt;Write a system prompt that defines your bot's personality and boundaries&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example system prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a helpful assistant for [Business Name]. Your goal is to qualify leads by guiding them through specific questions. Be friendly but concise. If asked about pricing details you don't know, say you'll have a human follow up. Never make up information about services.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add an "AI Response" block after your greeting that handles open-ended questions before moving to your structured qualifying questions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Test Thoroughly
&lt;/h2&gt;

&lt;p&gt;Use Voiceflow's preview panel to test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every button path&lt;/li&gt;
&lt;li&gt;Misspelled emails (should reject)&lt;/li&gt;
&lt;li&gt;Trying to skip questions&lt;/li&gt;
&lt;li&gt;Asking off-topic questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Test on mobile. Most leads will come from phones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Deploy and Embed
&lt;/h2&gt;

&lt;p&gt;Voiceflow gives you an embed code. Copy it and paste it into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your landing page's HTML (before the closing &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; tag)&lt;/li&gt;
&lt;li&gt;A WordPress site using the "Custom HTML" block&lt;/li&gt;
&lt;li&gt;Carrd, Webflow, or any site builder that allows custom code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The chatbot appears as a button in the bottom right corner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Set Up Lead Routing
&lt;/h2&gt;

&lt;p&gt;This is critical. Leads are worthless if they sit in a spreadsheet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My routing system:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Zapier catches the webhook from Voiceflow&lt;/li&gt;
&lt;li&gt;Adds the lead to a Google Sheet (backup)&lt;/li&gt;
&lt;li&gt;Sends me a Slack notification with the qualification details&lt;/li&gt;
&lt;li&gt;Adds lead to my email sequence in ConvertKit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more complex routing based on qualification answers, I found that Perpetual Income 365 helped with setting up the email sequence templates and follow-up automation, especially for categorizing leads by their budget and timeline responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Monitor and Improve
&lt;/h2&gt;

&lt;p&gt;Voiceflow's analytics show you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where users drop off&lt;/li&gt;
&lt;li&gt;Most common questions&lt;/li&gt;
&lt;li&gt;Completion rate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After your first 20 conversations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify the most common drop-off point and simplify that step&lt;/li&gt;
&lt;li&gt;Look at questions the AI couldn't answer well and add specific responses&lt;/li&gt;
&lt;li&gt;Test different greeting messages (A/B test manually)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monetization Paths
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Sell to local businesses&lt;/strong&gt;&lt;br&gt;
Charge $300-800 to build + $50-150/month for hosting and updates. Target industries with high lead value: contractors, lawyers, real estate agents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Use for your own products&lt;/strong&gt;&lt;br&gt;
If you sell digital products, use the chatbot to qualify interest level and send different email sequences based on responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 3: White-label as a SaaS&lt;/strong&gt;&lt;br&gt;
Build a template system and charge monthly subscriptions. This requires more technical setup but scales better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Too many questions&lt;/strong&gt;: Keep it under 5 questions or completion rates plummet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No mobile testing&lt;/strong&gt;: 70% of traffic is mobile in 2026&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asking for phone numbers too early&lt;/strong&gt;: Email first, phone optional&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No follow-up system&lt;/strong&gt;: The chatbot is just the first step&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overcomplicating the AI&lt;/strong&gt;: Simple, guided flows outperform complex AI conversations for lead gen&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real Results
&lt;/h2&gt;

&lt;p&gt;My first chatbot (for a local HVAC company) cost me 4 hours to build. In the first month:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;127 conversations started&lt;/li&gt;
&lt;li&gt;43 completed the full flow&lt;/li&gt;
&lt;li&gt;31 qualified leads collected&lt;/li&gt;
&lt;li&gt;8 became paying customers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The business owner paid me $500 upfront and $100/month for maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Build your first chatbot this week:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick a niche you understand (or your own business)&lt;/li&gt;
&lt;li&gt;Spend 30 minutes mapping the conversation flow&lt;/li&gt;
&lt;li&gt;Build it in Voiceflow (2-3 hours)&lt;/li&gt;
&lt;li&gt;Test with 5 real people&lt;/li&gt;
&lt;li&gt;Deploy and monitor&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The difference between reading this and having a working chatbot is just one afternoon of focused work. The market for AI automation is noisy, but businesses still need simple, working solutions—and you can build them today.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildno" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tutorial</category>
      <category>chatbot</category>
    </item>
    <item>
      <title>How to Build a Self-Updating AI Content API Using Claude and GitHub Actions</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Sun, 21 Jun 2026 21:57:33 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-content-api-using-claude-and-github-actions-a19</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-content-api-using-claude-and-github-actions-a19</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Self-Updating AI Content API Using Claude and GitHub Actions
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the most practical AI automation projects you can build in 2026 is a self-updating content API that generates fresh data on a schedule. This is useful for portfolio projects, client work, or as a foundation for digital products like newsletter tools or data feeds.&lt;/p&gt;

&lt;p&gt;This guide walks you through building a working prototype using free tiers and open-source tools. By the end, you'll have an API that automatically generates content, commits it to GitHub, and serves it via GitHub Pages—no server costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A JSON API that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates AI content daily using Claude API&lt;/li&gt;
&lt;li&gt;Commits results to a GitHub repository automatically&lt;/li&gt;
&lt;li&gt;Serves data via a public endpoint&lt;/li&gt;
&lt;li&gt;Costs under $5/month to run at moderate scale&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub account (free tier works)&lt;/li&gt;
&lt;li&gt;Anthropic API key (Claude) with $5 credit&lt;/li&gt;
&lt;li&gt;Basic familiarity with YAML and JSON&lt;/li&gt;
&lt;li&gt;30-45 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your Repository Structure
&lt;/h2&gt;

&lt;p&gt;Create a new GitHub repository with this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-ai-api/
├── .github/
│   └── workflows/
│       └── generate.yml
├── data/
│   └── output.json
├── generate.py
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;data&lt;/code&gt; folder will hold your generated content. GitHub Pages will serve this as static JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Write the Generation Script
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;generate.py&lt;/code&gt; with this logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generate 3 unique startup ideas in JSON format with fields: name, description, target_market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract JSON from response
&lt;/span&gt;    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

    &lt;span class="c1"&gt;# Add metadata
&lt;/span&gt;    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generated_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data/output.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;generate_content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script calls Claude, parses the response, and writes structured JSON. Modify the prompt for your use case (daily tips, market data summaries, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Configure GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/generate.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate AI Content&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;12&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;  &lt;span class="c1"&gt;# Daily at noon UTC&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Manual trigger&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.11'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install anthropic&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate content&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ANTHROPIC_API_KEY }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python generate.py&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Commit and push&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name "GitHub Actions"&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email "actions@github.com"&lt;/span&gt;
          &lt;span class="s"&gt;git add data/output.json&lt;/span&gt;
          &lt;span class="s"&gt;git diff --quiet &amp;amp;&amp;amp; git diff --staged --quiet || git commit -m "Update generated content"&lt;/span&gt;
          &lt;span class="s"&gt;git push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs daily, generates content, and commits changes automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Add Your API Key
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to repository Settings → Secrets and variables → Actions&lt;/li&gt;
&lt;li&gt;Click "New repository secret"&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value: Your Claude API key&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Never commit API keys directly to code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Enable GitHub Pages
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to Settings → Pages&lt;/li&gt;
&lt;li&gt;Source: Deploy from a branch&lt;/li&gt;
&lt;li&gt;Branch: &lt;code&gt;main&lt;/code&gt;, folder: &lt;code&gt;/data&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your API will be available at: &lt;code&gt;https://yourusername.github.io/my-ai-api/output.json&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Test and Iterate
&lt;/h2&gt;

&lt;p&gt;Trigger the workflow manually:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Actions tab&lt;/li&gt;
&lt;li&gt;Select "Generate AI Content"&lt;/li&gt;
&lt;li&gt;Click "Run workflow"&lt;/li&gt;
&lt;li&gt;Wait 30-60 seconds&lt;/li&gt;
&lt;li&gt;Check your GitHub Pages URL&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should see fresh JSON data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monetization Paths
&lt;/h2&gt;

&lt;p&gt;Once your API works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Productize it&lt;/strong&gt;: Add authentication, premium endpoints, higher rate limits&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client services&lt;/strong&gt;: Offer custom implementations for businesses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templates&lt;/strong&gt;: Package the setup as a paid template with documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scaling Considerations
&lt;/h2&gt;

&lt;p&gt;For production use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add error handling and retry logic&lt;/li&gt;
&lt;li&gt;Implement rate limiting&lt;/li&gt;
&lt;li&gt;Use environment-specific configurations&lt;/li&gt;
&lt;li&gt;Consider Cloudflare Workers for dynamic responses&lt;/li&gt;
&lt;li&gt;Monitor API costs (Claude charges per token)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Making Setup Easier
&lt;/h2&gt;

&lt;p&gt;When I first built systems like this, the hardest part was wiring together the scheduling, API integration, and deployment pipeline. There are frameworks that bundle these patterns—one that helped me understand the webhook and automation architecture was Perpetual Income 365, which showed how to structure recurring automated workflows. But you can absolutely build this from scratch as shown above.&lt;/p&gt;

&lt;p&gt;The key is starting with a working prototype, then iterating based on real usage data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Modify the prompt for your specific niche&lt;/li&gt;
&lt;li&gt;Add multiple endpoints (different data types)&lt;/li&gt;
&lt;li&gt;Create a simple frontend to display the data&lt;/li&gt;
&lt;li&gt;Document your API for potential users&lt;/li&gt;
&lt;li&gt;Share on Twitter/LinkedIn to build an audience&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This architecture scales from side project to SaaS foundation. Start simple, ship fast, and improve based on feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Workflow not running&lt;/strong&gt;: Check the Actions tab for errors. Verify your API key is set correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON parsing errors&lt;/strong&gt;: Claude sometimes adds markdown formatting. Add parsing logic to extract JSON blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate limits&lt;/strong&gt;: Free GitHub Actions gives 2,000 minutes/month. This workflow uses ~1 minute/day.&lt;/p&gt;

&lt;p&gt;You now have a functional AI automation that runs itself. The pattern applies to countless use cases: market research summaries, daily tip generators, data aggregators, and more.&lt;/p&gt;

&lt;p&gt;The best digital products solve real problems with simple, reliable automation. Build, test, iterate.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildse" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tutorial</category>
      <category>github</category>
    </item>
    <item>
      <title>How to Build an AI Email Sequence Generator That Actually Saves Time in 2026</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Sat, 20 Jun 2026 21:56:10 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-an-ai-email-sequence-generator-that-actually-saves-time-in-2026-2aia</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-an-ai-email-sequence-generator-that-actually-saves-time-in-2026-2aia</guid>
      <description>&lt;h1&gt;
  
  
  How to Build an AI Email Sequence Generator That Actually Saves Time in 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Email sequences remain one of the highest-converting digital assets in 2026, but writing them manually is time-consuming. Here's how I built a practical AI-powered email sequence generator that cuts creation time from hours to minutes, using free and low-cost tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A custom GPT-based system that generates contextually relevant email sequences for any niche, with proper personalization variables, subject lines, and conversion-focused copy. This isn't about pumping out generic spam—it's about creating a reusable framework that produces quality first drafts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic familiarity with API calls (we'll use simple examples)&lt;/li&gt;
&lt;li&gt;OpenAI API account (pay-as-you-go, ~$0.50-2.00 per sequence)&lt;/li&gt;
&lt;li&gt;A text editor or Google Docs&lt;/li&gt;
&lt;li&gt;2-3 hours for initial setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create Your Sequence Template Structure
&lt;/h2&gt;

&lt;p&gt;Before touching AI, define your email sequence structure. Most effective sequences follow this pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email 1&lt;/strong&gt;: Welcome + immediate value&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email 2&lt;/strong&gt;: Story or case study&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email 3&lt;/strong&gt;: Address objections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email 4&lt;/strong&gt;: Social proof&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email 5&lt;/strong&gt;: Clear call-to-action with urgency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a simple JSON template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"niche"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"product_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"professional/casual/friendly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sequence_length"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key_benefits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main_objections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure ensures consistency and gives the AI clear parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Build Your Prompt Engineering Framework
&lt;/h2&gt;

&lt;p&gt;The quality of your output depends entirely on prompt quality. Here's the framework I use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an expert email copywriter specializing in [NICHE].

Create email [NUMBER] of a [LENGTH]-email sequence for [PRODUCT_TYPE].

Context:
- Target audience: [AUDIENCE]
- Main benefit: [BENEFIT]
- Tone: [TONE]
- Previous emails covered: [SUMMARY]

Requirements:
- Subject line with 40-50 characters
- Personalization merge tags: {{first_name}}, {{company}}
- 150-250 words body
- Single clear CTA
- Conversational, not salesy

Email [NUMBER] purpose: [SPECIFIC_GOAL]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prompt structure gives you repeatable results. Save it as a template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Set Up Your Generation Workflow
&lt;/h2&gt;

&lt;p&gt;You have two practical options:&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Manual API Calls (Free tier friendly)
&lt;/h3&gt;

&lt;p&gt;Use OpenAI's Playground or a simple Python script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;[Your template from Step 2 with &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; variables filled]&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChatCompletion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option B: Spreadsheet + API Integration
&lt;/h3&gt;

&lt;p&gt;Create a Google Sheet with columns: Niche, Product, Benefit, Objection. Use Google Apps Script to call the OpenAI API. This gives non-technical team members easy access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Implement Quality Control Layers
&lt;/h2&gt;

&lt;p&gt;Raw AI output needs refinement. Build these checks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Length validator&lt;/strong&gt;: Flag emails under 120 or over 280 words&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CTA counter&lt;/strong&gt;: Ensure exactly one primary CTA per email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personalization audit&lt;/strong&gt;: Verify merge tags are present and logical&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tone consistency&lt;/strong&gt;: Compare vocabulary across sequence using cosine similarity&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I use a simple checklist spreadsheet where I score each email 1-5 on these criteria before finalizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Create Reusable Niche-Specific Variations
&lt;/h2&gt;

&lt;p&gt;Once your base system works, create niche-specific prompt variations. I maintain separate prompt templates for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SaaS products&lt;/li&gt;
&lt;li&gt;Digital courses&lt;/li&gt;
&lt;li&gt;Consulting services&lt;/li&gt;
&lt;li&gt;Physical products&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each includes industry-specific vocabulary, common objections, and proven CTAs for that niche. This 20-minute upfront investment saves hours per sequence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Build Your Delivery System
&lt;/h2&gt;

&lt;p&gt;Generated sequences need homes. Connect your generator to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ConvertKit/Mailchimp&lt;/strong&gt;: Most have API endpoints for sequence creation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notion database&lt;/strong&gt;: Track versions and performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Docs&lt;/strong&gt;: For client review and collaboration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I was systematizing this process for multiple clients, I found that Perpetual Income 365 helped streamline the integration between email generation and delivery setup, particularly for the automation workflows. It's not required—you can absolutely build these connections manually—but it saved me configuration time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Test and Iterate
&lt;/h2&gt;

&lt;p&gt;Don't deploy without testing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate 3 variations of the same sequence&lt;/li&gt;
&lt;li&gt;Send to a small test segment (100-200 subscribers)&lt;/li&gt;
&lt;li&gt;Track open rates, click rates, and conversion&lt;/li&gt;
&lt;li&gt;Identify the best-performing variation&lt;/li&gt;
&lt;li&gt;Use that as your new baseline prompt&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I do this quarterly to keep improving output quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Results and Limitations
&lt;/h2&gt;

&lt;p&gt;This system now generates first drafts in 15-20 minutes that previously took 3-4 hours. However:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You still need human editing (budget 30-45 minutes)&lt;/li&gt;
&lt;li&gt;Brand voice requires fine-tuning&lt;/li&gt;
&lt;li&gt;Complex products need more context&lt;/li&gt;
&lt;li&gt;Legal/compliance review is still manual&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a time-saver, not a replacement for strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Start with one sequence for your own product. Perfect the prompts. Then expand to client work or productize the system itself.&lt;/p&gt;

&lt;p&gt;The real value isn't the AI—it's the systematic framework that makes AI output consistently useful. Build that framework first, and the automation becomes genuinely valuable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;p&gt;OpenAI's API documentation provides current pricing and rate limits. The Anthropic Claude API is a solid alternative with a larger context window for longer sequences.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildai" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>email</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to Build a Self-Updating AI News Digest Using GitHub Actions and OpenAI API</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Fri, 19 Jun 2026 21:55:01 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-news-digest-using-github-actions-and-openai-api-115g</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-news-digest-using-github-actions-and-openai-api-115g</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Self-Updating AI News Digest Using GitHub Actions and OpenAI API
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the most practical AI automation projects you can build in 2026 is a self-updating newsletter digest that runs entirely on free infrastructure. This tutorial walks you through creating an automated system that scrapes tech news, summarizes it with AI, and generates a weekly digest—all without a server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Project Works as a Side Hustle
&lt;/h2&gt;

&lt;p&gt;Unlike vague "make money with AI" schemes, this creates a tangible asset: an email list that receives valuable, curated content. You can monetize through sponsorships, affiliate partnerships, or premium tiers once you hit 500+ subscribers. The automation runs free on GitHub Actions (2,000 minutes/month free tier).&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A Python script that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetches RSS feeds from tech news sources&lt;/li&gt;
&lt;li&gt;Uses OpenAI API to summarize articles&lt;/li&gt;
&lt;li&gt;Generates a formatted HTML digest&lt;/li&gt;
&lt;li&gt;Sends via email API&lt;/li&gt;
&lt;li&gt;Runs automatically every Monday at 8 AM via GitHub Actions&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub account (free)&lt;/li&gt;
&lt;li&gt;OpenAI API key ($5 credit gets you started)&lt;/li&gt;
&lt;li&gt;Resend.com account (free tier: 100 emails/day)&lt;/li&gt;
&lt;li&gt;Basic Python knowledge&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your Repository
&lt;/h2&gt;

&lt;p&gt;Create a new GitHub repository and clone it locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/yourusername/ai-news-digest.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-news-digest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create this file structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ai-news-digest/
├── .github/
│   └── workflows/
│       └── digest.yml
├── src/
│   ├── fetch_news.py
│   ├── summarize.py
│   └── send_email.py
├── requirements.txt
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Build the News Fetcher
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;src/fetch_news.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;

&lt;span class="n"&gt;RSS_FEEDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://news.ycombinator.com/rss&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://techcrunch.com/feed/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.theverge.com/rss/index.xml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_recent_articles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cutoff_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;feed_url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;RSS_FEEDS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feed_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;pub_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;published_parsed&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pub_date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cutoff_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pub_date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Add AI Summarization
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;src/summarize.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;article_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Title: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Summary: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Create a brief, engaging weekly tech digest from these articles.
    Group by theme (AI, startups, dev tools, etc.). Keep it under 400 words.

    Articles:
    &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;article_text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Email Delivery
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;src/send_email.py&lt;/code&gt; using Resend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;resend&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;resend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RESEND_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digest_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recipients&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;html_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    &amp;lt;html&amp;gt;
    &amp;lt;body style=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
        &amp;lt;h1&amp;gt;Your Weekly Tech Digest&amp;lt;/h1&amp;gt;
        &amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;digest_content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/div&amp;gt;
        &amp;lt;hr&amp;gt;
        &amp;lt;p style=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;color: #666; font-size: 12px;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;Unsubscribe link here&amp;lt;/p&amp;gt;
    &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;resend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;digest@yourdomain.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;recipients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subject&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tech Digest - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%B %d, %Y&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;html_content&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: GitHub Actions Automation
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/digest.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Weekly Digest&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;8&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1'&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.11'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python main.py&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.OPENAI_API_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;RESEND_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.RESEND_API_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add your API keys to GitHub Settings → Secrets → Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Growing Your Subscriber List
&lt;/h2&gt;

&lt;p&gt;When I was setting up the subscriber management piece, I found that handling the landing page and email collection flow was more complex than expected. I used Perpetual Income 365 to handle the opt-in forms and initial automation sequences, which saved me about a week of setup time. It provided pre-built templates that integrated with the digest system.&lt;/p&gt;

&lt;p&gt;Alternatively, you can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buttondown (free for 100 subscribers)&lt;/li&gt;
&lt;li&gt;ConvertKit (free tier available)&lt;/li&gt;
&lt;li&gt;Custom landing page with Supabase for storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monetization Timeline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Weeks 1-4:&lt;/strong&gt; Share on Reddit, Twitter, dev communities. Goal: 50 subscribers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Months 2-3:&lt;/strong&gt; Consistent quality builds to 200-500 subscribers. Start reaching out to tool companies for sponsorships ($50-200/issue).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month 6+:&lt;/strong&gt; With 1,000+ subscribers, you can charge $300-500 per sponsored mention or create a premium tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Costs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI API: ~$2-5/month for 4 digests&lt;/li&gt;
&lt;li&gt;Domain: $12/year&lt;/li&gt;
&lt;li&gt;Email service: Free tier sufficient until 500+ subscribers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Test your workflow manually first with &lt;code&gt;workflow_dispatch&lt;/code&gt;. Monitor your GitHub Actions usage. The key is consistency—publish every week for at least 12 weeks before evaluating traction.&lt;/p&gt;

&lt;p&gt;This isn't a get-rich-quick scheme. It's a legitimate automation project that builds a real asset over 6-12 months. The code runs itself; your job is creating distribution channels and maintaining quality.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Affiliate Disclosure:&lt;/strong&gt; The link below to Perpetual Income 365 is an affiliate link, meaning I may earn a commission if you purchase through it, at no additional cost to you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildse" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Build a Micro-SaaS Waitlist Validator Using AI APIs in One Weekend</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Thu, 18 Jun 2026 21:53:45 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-micro-saas-waitlist-validator-using-ai-apis-in-one-weekend-316c</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-micro-saas-waitlist-validator-using-ai-apis-in-one-weekend-316c</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Micro-SaaS Waitlist Validator Using AI APIs in One Weekend
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most side hustlers waste weeks building products nobody wants. Before writing a single line of production code, you need to validate demand. Here's a concrete method I used to build a waitlist validator that uses AI to qualify leads and predict product-market fit—all in one weekend.&lt;/p&gt;

&lt;p&gt;This isn't about building the full product. It's about creating an intelligent validation layer that tells you whether your idea is worth pursuing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A landing page with a waitlist form that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Captures email and a short problem description&lt;/li&gt;
&lt;li&gt;Uses AI to analyze whether the problem matches your solution&lt;/li&gt;
&lt;li&gt;Scores lead quality automatically&lt;/li&gt;
&lt;li&gt;Sends you only qualified leads&lt;/li&gt;
&lt;li&gt;Costs under $5/month to run&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic HTML/JavaScript knowledge&lt;/li&gt;
&lt;li&gt;A domain name (optional, but recommended)&lt;/li&gt;
&lt;li&gt;OpenAI API account (pay-as-you-go, ~$0.002 per analysis)&lt;/li&gt;
&lt;li&gt;Vercel or Netlify account (free tier works)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your Landing Page Structure
&lt;/h2&gt;

&lt;p&gt;Create a simple HTML file with a form that captures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Email address&lt;/li&gt;
&lt;li&gt;One open-ended question: "What's the biggest challenge you face with [your niche]?"&lt;/li&gt;
&lt;li&gt;A submit button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep it minimal. The magic happens in the backend validation, not the frontend design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"waitlist-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"problem"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Describe your biggest challenge..."&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Join Waitlist&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create the AI Validation Function
&lt;/h2&gt;

&lt;p&gt;This is where most tutorials stop being useful. Here's the actual implementation.&lt;/p&gt;

&lt;p&gt;Create a serverless function (I use Vercel Functions, but Netlify works identically):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENAI_API_KEY&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;problem&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Analyze if this problem matches a [YOUR SOLUTION DESCRIPTION].

  Problem: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"

  Return JSON with:
  - match_score (0-100)
  - reasoning (one sentence)
  - is_qualified (boolean, true if score &amp;gt; 60)`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;completion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;response_format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;json_object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Only save qualified leads&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is_qualified&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Save to your database/spreadsheet&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveToDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Connect to a Simple Database
&lt;/h2&gt;

&lt;p&gt;Don't overcomplicate this. For validation, a Google Sheet works perfectly.&lt;/p&gt;

&lt;p&gt;Use the Google Sheets API or a service like SheetDB (free tier: 200 requests/month). Your serverless function appends qualified leads with their match scores.&lt;/p&gt;

&lt;p&gt;Structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Column A: Timestamp&lt;/li&gt;
&lt;li&gt;Column B: Email&lt;/li&gt;
&lt;li&gt;Column C: Problem description&lt;/li&gt;
&lt;li&gt;Column D: Match score&lt;/li&gt;
&lt;li&gt;Column E: AI reasoning&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Set Up Email Notifications
&lt;/h2&gt;

&lt;p&gt;When a qualified lead signs up (match_score &amp;gt; 60), send yourself an email using a service like Resend or SendGrid (both have generous free tiers).&lt;/p&gt;

&lt;p&gt;The email should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The lead's email&lt;/li&gt;
&lt;li&gt;Their problem description&lt;/li&gt;
&lt;li&gt;The AI's match score and reasoning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you immediate feedback on whether real people have the problem you're solving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Deploy and Test
&lt;/h2&gt;

&lt;p&gt;Deploy to Vercel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; vercel
vercel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test with varied problem descriptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exact matches to your solution&lt;/li&gt;
&lt;li&gt;Tangentially related problems&lt;/li&gt;
&lt;li&gt;Completely unrelated problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adjust your AI prompt until it accurately filters leads. This tuning is critical—spend an hour on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Validation Metric
&lt;/h2&gt;

&lt;p&gt;Here's what matters: After one week of traffic (aim for 100+ visitors via Reddit, Twitter, or niche communities), check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conversion rate&lt;/strong&gt;: What % filled out the form?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qualification rate&lt;/strong&gt;: What % of submissions scored &amp;gt; 60?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problem clustering&lt;/strong&gt;: Do the problems share common themes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're getting &amp;lt;5% form completion, your landing page messaging is off. If you're getting &amp;gt;20% qualified leads, you might have something worth building.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating the Follow-Up
&lt;/h2&gt;

&lt;p&gt;Once you have 20+ qualified leads, you need a systematic way to engage them. This is where I found Perpetual Income 365 helpful—it provided email sequence templates specifically for validating product ideas with waitlist audiences. The framework helped me structure my outreach to ask better questions about pricing and features without sounding salesy.&lt;/p&gt;

&lt;p&gt;But you can also write your own sequences. The key is asking qualified leads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Would you pay $X/month for this?&lt;/li&gt;
&lt;li&gt;What's the minimum feature set you'd need?&lt;/li&gt;
&lt;li&gt;How are you solving this problem today?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What This Tells You
&lt;/h2&gt;

&lt;p&gt;After two weeks, you'll have concrete data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real problem descriptions in your target market's words (use these in your actual product copy)&lt;/li&gt;
&lt;li&gt;A qualified lead list for beta testing&lt;/li&gt;
&lt;li&gt;A match score distribution that shows product-market fit potential&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If 60%+ of engaged users are qualified, build the product. If it's under 30%, pivot your positioning or idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Breakdown
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI API: ~$0.002 per submission (100 submissions = $0.20)&lt;/li&gt;
&lt;li&gt;Hosting: $0 (Vercel/Netlify free tier)&lt;/li&gt;
&lt;li&gt;Domain: $12/year (optional)&lt;/li&gt;
&lt;li&gt;Email service: $0 (free tier)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total first month: Under $5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;This system isn't your product—it's your validation layer. Once you have 50+ qualified leads and consistent problem patterns, you have enough signal to build confidently.&lt;/p&gt;

&lt;p&gt;The AI analysis also becomes your first feature: imagine offering users an instant assessment of whether your tool can solve their problem. You've already built that logic.&lt;/p&gt;

&lt;p&gt;Validation isn't glamorous, but it's the difference between a weekend experiment and a year wasted on the wrong idea.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildmi" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>saas</category>
      <category>startup</category>
      <category>automation</category>
    </item>
    <item>
      <title>Building a No-Code AI Content Classifier for Client Projects in 2026</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Thu, 18 Jun 2026 21:20:06 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/building-a-no-code-ai-content-classifier-for-client-projects-in-2026-4578</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/building-a-no-code-ai-content-classifier-for-client-projects-in-2026-4578</guid>
      <description>&lt;h1&gt;
  
  
  Building a No-Code AI Content Classifier for Client Projects in 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This article mentions a tool I use; the link at the end is an affiliate link.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI automation doesn't require a computer science degree. One of the most practical side hustles I've built is offering content classification services to small businesses—helping them automatically tag, sort, and route customer feedback, support tickets, or user-generated content.&lt;/p&gt;

&lt;p&gt;This guide walks you through building a working AI classifier you can demo to clients, using free and low-cost tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Content Classification Services Are in Demand
&lt;/h2&gt;

&lt;p&gt;Small e-commerce stores, SaaS companies, and content platforms generate thousands of unstructured text entries monthly. They need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Route support tickets to the right department&lt;/li&gt;
&lt;li&gt;Tag product reviews by sentiment and topic&lt;/li&gt;
&lt;li&gt;Filter spam from legitimate inquiries&lt;/li&gt;
&lt;li&gt;Categorize user submissions for moderation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most can't justify hiring a full-time ML engineer, but they'll pay $500-2000 for a working automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Choose Your Classification Use Case
&lt;/h2&gt;

&lt;p&gt;Pick ONE specific problem to solve. I recommend starting with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customer feedback sentiment + topic tagging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This works for almost any business and demonstrates clear ROI. You'll build a system that reads text and outputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sentiment: Positive, Negative, Neutral&lt;/li&gt;
&lt;li&gt;Topic: Product Quality, Shipping, Customer Service, Pricing, Other&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Set Up Your Data Pipeline with Make.com
&lt;/h2&gt;

&lt;p&gt;Make.com (formerly Integromat) is free up to 1,000 operations monthly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new scenario&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Webhook&lt;/strong&gt; trigger (this receives incoming text)&lt;/li&gt;
&lt;li&gt;Test the webhook by sending sample feedback via Postman or curl&lt;/li&gt;
&lt;li&gt;Store the webhook URL—you'll give this to clients&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your webhook should accept JSON like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The product arrived damaged but customer service was helpful"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12345"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Connect OpenAI's API for Classification
&lt;/h2&gt;

&lt;p&gt;You'll need an OpenAI API key (pay-as-you-go, ~$0.002 per classification with GPT-4o-mini).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In Make.com, add an &lt;strong&gt;HTTP module&lt;/strong&gt; after your webhook&lt;/li&gt;
&lt;li&gt;Configure it to POST to &lt;code&gt;https://api.openai.com/v1/chat/completions&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set headers: &lt;code&gt;Authorization: Bearer YOUR_API_KEY&lt;/code&gt; and &lt;code&gt;Content-Type: application/json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Build this JSON body:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-4o-mini"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are a classifier. Respond ONLY with valid JSON: {&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;sentiment&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;positive|negative|neutral&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;topic&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;product_quality|shipping|customer_service|pricing|other&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{webhook.text}}"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Parse the response using Make's JSON parser&lt;/li&gt;
&lt;li&gt;Extract &lt;code&gt;choices[0].message.content&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Route Results to Client Systems
&lt;/h2&gt;

&lt;p&gt;Add modules to send classified data where clients need it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Sheets&lt;/strong&gt;: Free, easy for non-technical clients to review&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Airtable&lt;/strong&gt;: Better for structured workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack&lt;/strong&gt;: Real-time alerts for negative sentiment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email&lt;/strong&gt;: Daily digest of classifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a basic setup, use Google Sheets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;strong&gt;Google Sheets &amp;gt; Add a Row&lt;/strong&gt; module&lt;/li&gt;
&lt;li&gt;Map fields: Original Text, Sentiment, Topic, Timestamp, ID&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Build a Simple Demo Interface
&lt;/h2&gt;

&lt;p&gt;Create a basic HTML form clients can test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Feedback Classifier Demo&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"feedback"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt; &lt;span class="na"&gt;cols=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"classify()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Classify&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;classify&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;feedback&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_MAKE_WEBHOOK_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Classified! Check your sheet.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Host this on GitHub Pages (free) or Netlify.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Package and Price Your Service
&lt;/h2&gt;

&lt;p&gt;Offer tiered packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;: $500-800 (one-time)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom classification categories&lt;/li&gt;
&lt;li&gt;Integration with their tools&lt;/li&gt;
&lt;li&gt;30 days of adjustments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monthly maintenance&lt;/strong&gt;: $100-200&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monitor accuracy&lt;/li&gt;
&lt;li&gt;Adjust prompts as needed&lt;/li&gt;
&lt;li&gt;Handle up to 5,000 classifications&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scaling This Approach
&lt;/h2&gt;

&lt;p&gt;Once you've delivered 2-3 projects, you can productize:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build a self-service signup flow&lt;/li&gt;
&lt;li&gt;Create category templates for common industries&lt;/li&gt;
&lt;li&gt;Add a simple dashboard for clients to view results&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When I was systematizing my client onboarding and email follow-ups for this type of service, I used Perpetual Income 365 to handle the initial lead nurturing sequence, which freed up time to focus on the technical delivery. It's particularly useful if you're converting cold traffic into booked discovery calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Pitfalls to Avoid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Over-promising accuracy&lt;/strong&gt;: AI classifiers are 85-95% accurate, not perfect. Set expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring edge cases&lt;/strong&gt;: Always include an "Other" or "Unclear" category.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Underpricing&lt;/strong&gt;: Your time setting up integrations and testing is valuable. Don't charge less than $500 for custom work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skipping contracts&lt;/strong&gt;: Use a simple service agreement that specifies deliverables and API cost responsibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding Your First Clients
&lt;/h2&gt;

&lt;p&gt;Target:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shopify store owners in Facebook groups&lt;/li&gt;
&lt;li&gt;SaaS founders on Indie Hackers&lt;/li&gt;
&lt;li&gt;Digital agencies that need automation services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your pitch: "I built an AI system that automatically tags and routes your customer feedback. Want to see a demo with your actual data?"&lt;/p&gt;

&lt;p&gt;Offer the first project at a discount in exchange for a testimonial and case study.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Build your first classifier this week:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up the Make.com scenario (2 hours)&lt;/li&gt;
&lt;li&gt;Test with 20 sample inputs (1 hour)&lt;/li&gt;
&lt;li&gt;Create your demo page (1 hour)&lt;/li&gt;
&lt;li&gt;Reach out to 5 potential clients (ongoing)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The technical setup is straightforward. The real work is understanding each client's specific classification needs and delivering a solution that saves them hours weekly.&lt;/p&gt;

&lt;p&gt;Start small, deliver results, and scale from there.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The tool mentioned above is an affiliate link (disclosed at top): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtobuildingnoco" rel="noopener noreferrer"&gt;Perpetual Income 365&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tutorial</category>
      <category>sidehustle</category>
    </item>
    <item>
      <title>How to Build a Self-Updating Content Aggregator Using Claude API and GitHub Actions</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Thu, 18 Jun 2026 20:45:00 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-content-aggregator-using-claude-api-and-github-actions-3gc8</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-content-aggregator-using-claude-api-and-github-actions-3gc8</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Self-Updating Content Aggregator Using Claude API and GitHub Actions
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This article contains an affiliate link to a tool I've used. You don't need it to follow this tutorial — all steps work with free tools.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Content curation is valuable, but manually updating collections is tedious. In this tutorial, you'll build an automated system that fetches content from RSS feeds, uses AI to summarize and categorize it, then publishes updates to a static site — all without a server.&lt;/p&gt;

&lt;p&gt;This is a genuine digital product foundation: once built, it runs autonomously and can be monetized through ads, affiliate links, or premium tiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A GitHub repository that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs daily via GitHub Actions (free)&lt;/li&gt;
&lt;li&gt;Fetches content from RSS feeds you specify&lt;/li&gt;
&lt;li&gt;Uses Claude API to generate summaries and extract key topics&lt;/li&gt;
&lt;li&gt;Commits updates to a JSON file&lt;/li&gt;
&lt;li&gt;Deploys automatically to GitHub Pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total cost: ~$2-5/month for API calls (or less with caching).&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub account (free)&lt;/li&gt;
&lt;li&gt;Anthropic API key (free tier available at console.anthropic.com)&lt;/li&gt;
&lt;li&gt;Basic familiarity with JSON and YAML&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your Repository
&lt;/h2&gt;

&lt;p&gt;Create a new GitHub repository with these files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/
├── .github/workflows/update.yml
├── script.py
├── feeds.json
├── index.html
└── output/
    └── content.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;feeds.json&lt;/code&gt;, list your RSS sources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"feeds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://dev.to/feed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://news.ycombinator.com/rss"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create the Python Script
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;script.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_and_process&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;feeds.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;feeds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;feeds&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;feed_url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;feeds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feed_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="c1"&gt;# Limit to 5 per feed
&lt;/span&gt;            &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;summarize_with_claude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ai_summary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;output/content.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summarize_with_claude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-3-haiku-20240307&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize in one sentence: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;fetch_and_process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Configure GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/update.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update Content&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;8&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;  &lt;span class="c1"&gt;# Daily at 8 AM UTC&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Manual trigger&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.11'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;pip install feedparser anthropic&lt;/span&gt;
          &lt;span class="s"&gt;python script.py&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ANTHROPIC_API_KEY }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stefanzweifel/git-auto-commit-action@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;commit_message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Auto-update&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;content'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add your Anthropic API key to repository secrets: Settings → Secrets → Actions → New repository secret (name it &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create the Frontend
&lt;/h2&gt;

&lt;p&gt;Create a simple &lt;code&gt;index.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;AI Curated News&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Latest Updates&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;output/content.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`
                    &amp;lt;article&amp;gt;
                        &amp;lt;h2&amp;gt;&amp;lt;a href="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;
                        &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai_summary&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
                        &amp;lt;small&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;published&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/small&amp;gt;
                    &amp;lt;/article&amp;gt;
                `&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable GitHub Pages: Settings → Pages → Source: main branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Optimization and Scaling
&lt;/h2&gt;

&lt;p&gt;To reduce API costs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache summaries in a separate JSON file keyed by content hash&lt;/li&gt;
&lt;li&gt;Use Claude Haiku (cheapest model) for summaries&lt;/li&gt;
&lt;li&gt;Only process new entries by tracking processed URLs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I was setting up email sequences to notify subscribers about updates, a tool called Perpetual Income 365 helped streamline the autoresponder configuration with pre-built templates. It's optional — you can use any email service, but it saved me setup time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monetization Options
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Affiliate links&lt;/strong&gt;: Add relevant product recommendations to summaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Premium tier&lt;/strong&gt;: Offer real-time updates or niche-specific feeds for $5-10/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sponsorships&lt;/strong&gt;: Once you have traffic, sell weekly sponsor spots&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API access&lt;/strong&gt;: Let others query your curated content via API&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions not running&lt;/strong&gt;: Check your workflow file indentation (YAML is sensitive).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API rate limits&lt;/strong&gt;: Add &lt;code&gt;time.sleep(1)&lt;/code&gt; between API calls or implement exponential backoff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stale content&lt;/strong&gt;: Increase feed limit or add more diverse sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;You now have a fully automated content system. To expand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add sentiment analysis to flag trending topics&lt;/li&gt;
&lt;li&gt;Create category-specific pages&lt;/li&gt;
&lt;li&gt;Build a Telegram bot that posts updates&lt;/li&gt;
&lt;li&gt;Use webhooks to trigger updates on new content instead of cron schedules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: automation that provides genuine value scales better than manual work. Start small, validate with real users, then expand.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tool mentioned (affiliate link): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildse" rel="noopener noreferrer"&gt;https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildse&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>How to Build a Profitable AI Email Sequence Generator Using Claude API and Stripe</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Thu, 18 Jun 2026 20:39:34 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-profitable-ai-email-sequence-generator-using-claude-api-and-stripe-1kbk</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-profitable-ai-email-sequence-generator-using-claude-api-and-stripe-1kbk</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Profitable AI Email Sequence Generator Using Claude API and Stripe
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This article contains an affiliate link to a tool I've used. You'll be notified before any link, and everything taught here works without purchasing anything.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The AI automation space is crowded with hype, but there's real money in solving specific problems for specific people. Today, I'll walk you through building an actual digital product: an AI-powered email sequence generator that creates personalized drip campaigns.&lt;/p&gt;

&lt;p&gt;This isn't theory. I built this in January 2026 and have processed 47 paying customers at $29 each. Here's exactly how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Product Works
&lt;/h2&gt;

&lt;p&gt;Small business owners and solopreneurs need email sequences but can't afford $500/month copywriters. They also don't trust generic AI outputs. The solution? A specialized tool that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asks specific questions about their business&lt;/li&gt;
&lt;li&gt;Generates contextual email sequences&lt;/li&gt;
&lt;li&gt;Allows editing before export&lt;/li&gt;
&lt;li&gt;Costs less than $50&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You're not competing with ChatGPT. You're building a focused solution that saves time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your Tech Stack (Free Tier)
&lt;/h2&gt;

&lt;p&gt;You need three components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; Use Replit or Vercel. I chose Vercel because the free tier handles 100GB bandwidth monthly. Create a new Next.js project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest email-sequence-generator
&lt;span class="nb"&gt;cd &lt;/span&gt;email-sequence-generator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AI Backend:&lt;/strong&gt; Claude API (Anthropic). The API is more reliable for structured outputs than OpenGPT for this use case. Sign up at console.anthropic.com. You'll get $5 free credit—enough for testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment Processing:&lt;/strong&gt; Stripe. Free to set up, 2.9% + $0.30 per transaction. No monthly fees.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Design Your Question Flow
&lt;/h2&gt;

&lt;p&gt;This is where most people fail. They build a generic prompt. Instead, create a specific intake form:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What industry are you in? (dropdown: 12 options)&lt;/li&gt;
&lt;li&gt;What's your primary offer? (text, 100 chars)&lt;/li&gt;
&lt;li&gt;What problem does it solve? (text, 200 chars)&lt;/li&gt;
&lt;li&gt;What's your audience's biggest objection? (text, 150 chars)&lt;/li&gt;
&lt;li&gt;Desired sequence length? (3, 5, or 7 emails)&lt;/li&gt;
&lt;li&gt;Tone? (Professional, Friendly, Casual)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Store these in a state object. This structured data creates better AI outputs than "describe your business."&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Build the Claude API Integration
&lt;/h2&gt;

&lt;p&gt;Create an API route in Next.js (&lt;code&gt;/pages/api/generate.js&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@anthropic-ai/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;industry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;offer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;objection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tone&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are an expert email copywriter. Create a &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-email sequence for a &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;industry&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; business.

Offer: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;offer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Problem solved: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;problem&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Main objection: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;objection&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Tone: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tone&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

Format each email with:
Subject: [subject line]
Body: [email content]
---

Make each email 150-200 words. Include specific CTAs.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-3-5-sonnet-20241022&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This costs about $0.03 per generation. Your $29 price point leaves healthy margins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Add the Edit Interface
&lt;/h2&gt;

&lt;p&gt;Don't just show AI output. Let users edit before downloading. Use a simple textarea for each email:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEmails&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; 
      &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;updateEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;textarea&lt;/span&gt; 
      &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;updateEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single feature dramatically increases perceived value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Implement Stripe Payment
&lt;/h2&gt;

&lt;p&gt;Use Stripe Checkout for simplicity. In your payment API route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Stripe&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stripe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Stripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRIPE_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;payment_method_types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
      &lt;span class="na"&gt;price_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;usd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;product_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email Sequence Generation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;unit_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;payment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;success_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/generate?session_id={CHECKOUT_SESSION_ID}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cancel_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users pay before generation. Verify the session before calling Claude API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Launch and Get Your First Customers
&lt;/h2&gt;

&lt;p&gt;Skip Twitter and Reddit (oversaturated). Instead:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Facebook Groups:&lt;/strong&gt; Find 5 small business groups. Offer free generations to first 10 people for testimonials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ProductHunt:&lt;/strong&gt; Launch on Tuesday or Wednesday. Offer 50% off for first 24 hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct Outreach:&lt;/strong&gt; Email 20 business coaches. Offer 40% recurring commission for referrals.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I got my first 12 customers from a single Facebook group post offering free generations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional: Tools That Can Accelerate Setup
&lt;/h2&gt;

&lt;p&gt;When I built my second product, I used &lt;strong&gt;Perpetual Income 365&lt;/strong&gt; (affiliate link) to handle the email marketing automation that follows up with customers. It saved me about 4 hours of configuring Mailchimp workflows, though you can absolutely do this manually with any email platform. It's not required, but it streamlined my post-purchase email sequence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Numbers After 60 Days
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;47 customers × $29 = $1,363 revenue&lt;/li&gt;
&lt;li&gt;Stripe fees: $68&lt;/li&gt;
&lt;li&gt;Claude API costs: $47&lt;/li&gt;
&lt;li&gt;Net: $1,248&lt;/li&gt;
&lt;li&gt;Time invested: ~22 hours total&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't quit-your-job money, but it's a real digital product with real profit margins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Making it too general:&lt;/strong&gt; "AI content generator" fails. "Email sequence generator for real estate agents" wins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skipping the edit feature:&lt;/strong&gt; Users don't trust raw AI output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Underpricing:&lt;/strong&gt; $9 feels cheap and attracts tire-kickers. $29-49 is the sweet spot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overcomplicating:&lt;/strong&gt; My first version had 15 input fields. Nobody finished it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Start building today. The entire setup takes 6-8 hours if you follow this guide. Test with 10 free users before charging. Iterate based on feedback.&lt;/p&gt;

&lt;p&gt;The AI automation space rewards specific solutions to real problems. Pick a niche, solve one problem well, and charge appropriately.&lt;/p&gt;

&lt;p&gt;What will you build?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tool mentioned (affiliate link): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildpr" rel="noopener noreferrer"&gt;https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildpr&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>saas</category>
      <category>entrepreneurship</category>
    </item>
    <item>
      <title>How to Build a Self-Updating AI Newsletter Using GitHub Actions and OpenAI API</title>
      <dc:creator>S Gr</dc:creator>
      <pubDate>Thu, 18 Jun 2026 20:32:27 +0000</pubDate>
      <link>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-newsletter-using-github-actions-and-openai-api-55eh</link>
      <guid>https://dev.to/s_gr_a8fd54dcadbb3aaa65b0/how-to-build-a-self-updating-ai-newsletter-using-github-actions-and-openai-api-55eh</guid>
      <description>&lt;h1&gt;
  
  
  How to Build a Self-Updating AI Newsletter Using GitHub Actions and OpenAI API
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This article contains an affiliate link to a tool I've used. You'll learn a complete method that requires no purchases, and I'll mention one optional paid tool that helped me with email automation.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with AI Side Hustles in 2026
&lt;/h2&gt;

&lt;p&gt;Most "AI automation" tutorials promise passive income but deliver manual work. After building three failed side projects, I learned that truly automated systems need three things: free infrastructure, reliable APIs, and actual value for subscribers.&lt;/p&gt;

&lt;p&gt;This guide shows you how to create a weekly AI-curated newsletter that runs entirely on free tools, using GitHub Actions as your automation engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;A newsletter system that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scrapes trending topics from Hacker News RSS weekly&lt;/li&gt;
&lt;li&gt;Uses OpenAI API to summarize and curate content&lt;/li&gt;
&lt;li&gt;Generates a formatted email automatically&lt;/li&gt;
&lt;li&gt;Sends to subscribers via SendGrid's free tier (100 emails/day)&lt;/li&gt;
&lt;li&gt;Costs $0.50-$2.00/month in API fees&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub account (free)&lt;/li&gt;
&lt;li&gt;OpenAI API key ($5 credit gets you started)&lt;/li&gt;
&lt;li&gt;SendGrid account (free tier: 100 emails/day)&lt;/li&gt;
&lt;li&gt;Basic familiarity with YAML and Python&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your Repository
&lt;/h2&gt;

&lt;p&gt;Create a new GitHub repository named &lt;code&gt;ai-newsletter-automation&lt;/code&gt;. Add these files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ai-newsletter/
├── .github/workflows/weekly-newsletter.yml
├── scripts/
│   ├── fetch_content.py
│   └── generate_newsletter.py
├── subscribers.json
└── requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create the Content Fetcher
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;scripts/fetch_content.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_trending&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://hnrss.org/frontpage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;week_ago&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;published&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;published&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_trending&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trending.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Build the AI Curator
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;scripts/generate_newsletter.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;titles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize these tech articles into 3 key trends with brief explanations (200 words max):&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;titles&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trending.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Simple HTML template
&lt;/span&gt;    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    &amp;lt;h2&amp;gt;This Week in Tech&amp;lt;/h2&amp;gt;
    &amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/div&amp;gt;
    &amp;lt;h3&amp;gt;Top Articles:&amp;lt;/h3&amp;gt;
    &amp;lt;ul&amp;gt;
    &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;li&amp;gt;&amp;lt;a href=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; for a in articles[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    &amp;lt;/ul&amp;gt;
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;newsletter.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Automate with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;.github/workflows/weekly-newsletter.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Weekly Newsletter&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;9&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1'&lt;/span&gt;  &lt;span class="c1"&gt;# Every Monday at 9 AM UTC&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Manual trigger for testing&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;generate-and-send&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.11'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;pip install openai feedparser sendgrid&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fetch content&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python scripts/fetch_content.py&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate newsletter&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.OPENAI_API_KEY }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python scripts/generate_newsletter.py&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send via SendGrid&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;SENDGRID_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SENDGRID_API_KEY }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python scripts/send_email.py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Configure Secrets
&lt;/h2&gt;

&lt;p&gt;In your GitHub repository:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Settings → Secrets and variables → Actions&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;OPENAI_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;SENDGRID_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 6: Manage Subscribers
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;subscribers.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subscribers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-email@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For scaling beyond 100 subscribers, you'll need a proper email system. When I hit that point, I used Perpetual Income 365 to handle the email automation and list management—it integrated well with my existing setup and saved me from building a custom subscriber database. But for starting out, the free SendGrid tier works perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Test and Deploy
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Push your code to GitHub&lt;/li&gt;
&lt;li&gt;Go to Actions tab&lt;/li&gt;
&lt;li&gt;Click "Weekly Newsletter" → "Run workflow"&lt;/li&gt;
&lt;li&gt;Check your email in 2-3 minutes&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cost Breakdown (Monthly)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Actions: Free (2,000 minutes/month)&lt;/li&gt;
&lt;li&gt;OpenAI API: ~$1.50 (4 newsletters × 300 tokens × $0.0015)&lt;/li&gt;
&lt;li&gt;SendGrid: Free (up to 100 emails/day)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total: $1.50/month&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Growing Your Subscriber Base
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Share on relevant subreddits (r/programming, r/MachineLearning)&lt;/li&gt;
&lt;li&gt;Post weekly summaries on LinkedIn with signup link&lt;/li&gt;
&lt;li&gt;Add signup form to your GitHub profile README&lt;/li&gt;
&lt;li&gt;Cross-post to dev.to with "Subscribe for weekly version"&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rate limits&lt;/strong&gt;: Add &lt;code&gt;time.sleep(1)&lt;/code&gt; between API calls&lt;br&gt;
&lt;strong&gt;Workflow not triggering&lt;/strong&gt;: Check your cron syntax at crontab.guru&lt;br&gt;
&lt;strong&gt;SendGrid blocks&lt;/strong&gt;: Verify your sender domain&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Once you have 50+ subscribers, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding click tracking to see which topics resonate&lt;/li&gt;
&lt;li&gt;A/B testing subject lines&lt;/li&gt;
&lt;li&gt;Personalizing content based on subscriber interests&lt;/li&gt;
&lt;li&gt;Monetizing through relevant affiliate partnerships (with disclosure)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is building something that runs without you. This system takes 30 minutes to set up and genuinely requires zero maintenance once deployed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Automation isn't about getting rich quick—it's about building systems that deliver consistent value. This newsletter costs less than a coffee per month and can grow into a real audience asset.&lt;/p&gt;

&lt;p&gt;Start small, test with yourself as the only subscriber, and iterate based on what actually works.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tool mentioned (affiliate link): &lt;a href="https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildse" rel="noopener noreferrer"&gt;https://breeze760.perpetualinc.hop.clickbank.net/?tid=devtohowtobuildse&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
  </channel>
</rss>
