<?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: Meysam</title>
    <description>The latest articles on DEV Community by Meysam (@meysam81).</description>
    <link>https://dev.to/meysam81</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F256073%2F8de69fc4-50e8-4094-ae96-1d55b854ae44.jpg</url>
      <title>DEV Community: Meysam</title>
      <link>https://dev.to/meysam81</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/meysam81"/>
    <language>en</language>
    <item>
      <title>AI-Assisted Coding Killed My Joy of Programming</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Mon, 01 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/ai-assisted-coding-killed-my-joy-of-programming-5a54</link>
      <guid>https://dev.to/meysam81/ai-assisted-coding-killed-my-joy-of-programming-5a54</guid>
      <description>&lt;h2&gt;
  
  
  The Cheat Code Moment
&lt;/h2&gt;

&lt;p&gt;I remember when I was younger..&lt;/p&gt;

&lt;p&gt;any time I was playing a video game, and I discovered that they support activating cheat codes in the game..&lt;/p&gt;

&lt;p&gt;that I was initially way too excited.. I could finally bought that expensive house in uptown, one that I had my eye on for a while..&lt;/p&gt;

&lt;p&gt;I told myself, I'll just add some cheat codes for the money and then I'll get back to the normal game playing..&lt;/p&gt;

&lt;p&gt;it was simple, it was a promise to myself...&lt;/p&gt;

&lt;p&gt;it was a lie!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Slippery Slope
&lt;/h2&gt;

&lt;p&gt;I eventually ended up using more and more of the cheat codes...&lt;/p&gt;

&lt;p&gt;even the ones I initially set out not to use at all because I believed they'd ruin the game experience for me....&lt;/p&gt;

&lt;p&gt;I used them all! it did ruin the game for me.. I uninstalled the game after a few hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Coding Assistants Feel the Same Way
&lt;/h2&gt;

&lt;p&gt;honestly, working with AI assisted code editors give me the same feeling.. I initially get excited.&lt;/p&gt;

&lt;p&gt;I can now do more, achieve more, implement and design more and create better projects..&lt;/p&gt;

&lt;p&gt;I tell myself it'll only be for a specific business logic, or a specific file... and then I'll get back to normal coding..... I never do. I end up running the whole project through the AI coding editor.&lt;/p&gt;

&lt;p&gt;spoiler alert: it ruins my experience and takes away the joy of programming I initially started my whole career for!&lt;/p&gt;

&lt;h2&gt;
  
  
  When Coding Stops Being Fun
&lt;/h2&gt;

&lt;p&gt;then I end up doing what I ended up doing to my video games a few years back. I stop doing it.&lt;/p&gt;

&lt;p&gt;I close my laptop and go play my piano... because the coding is no longer fun.. it's no longer exciting..&lt;/p&gt;

&lt;p&gt;I am no longer solving any mentally-stimulating problems.. I am just copy-pasting code from an AI assistant.&lt;/p&gt;

&lt;p&gt;it no longer scratches any itch, no longer feels rewarding, no longer feels like an accomplishment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Emptiness After AI-Generated Code
&lt;/h2&gt;

&lt;p&gt;I feel dead inside afterwards. I feel like I hate myself, wasted hours for nothing... accomplished nothing.&lt;/p&gt;

&lt;p&gt;it pains me because I love that excitment, that joy of programming, the troubleshooting and banging my head against the&lt;br&gt;
wall for hours dealing with compiler errors, runtime errors, logic errors, bugs, edge cases and all that jazz.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Democratization of Code in 2025
&lt;/h2&gt;

&lt;p&gt;now that coding is democratized in 2025 with so many "agents", I no longer feel like I am special as a programmer.&lt;/p&gt;

&lt;p&gt;I feel useless to be honest. I feel like anyone can do what I do, and better, faster, cheaper and with less effort.&lt;/p&gt;

&lt;p&gt;you write one prompt, not even the most perfect and engineered one, and after 2-3 min you get a full-fledged, (near-)production-ready code.&lt;/p&gt;

&lt;p&gt;deploy it and forget about it and it'll run forever.&lt;/p&gt;

&lt;p&gt;experiment as much as you like because building is now no longer a bottleneck... some would argue that it never has been...&lt;/p&gt;

&lt;p&gt;some would say that marketing and distribution are the heavier lifts... I might agree to some extent.. I wrote about &lt;a href="https://dev.to/blog/no-competition-red-flag-solopreneur-validated-market"&gt;why distribution beats product&lt;/a&gt; when I launched my first SaaS to zero customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Miss the Grind
&lt;/h2&gt;

&lt;p&gt;I still miss that feeling though.&lt;/p&gt;

&lt;p&gt;I still want to do programming, use Ctrl + Space for auto-completion, not tab, tab, tab and you are done.&lt;/p&gt;

&lt;p&gt;I would've loved to stay a few years more into the years of Fortran, Cobol, C, C++, Java, Python, JavaScript, TypeScript, Rust, Go, Dart and all the other languages.&lt;/p&gt;

&lt;p&gt;grinding and learning how to deal with Rust macros (I never did!).&lt;/p&gt;

&lt;p&gt;pity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Losing Control of Your Own Codebase
&lt;/h2&gt;

&lt;p&gt;and when you run your whole codebase through AI, you are no longer in charge, AI is.&lt;/p&gt;

&lt;p&gt;you have no clue what is where, how to make the changes you want, how to debug issues, how to optimize performance, how to refactor code, how to scale the system.&lt;/p&gt;

&lt;p&gt;you tell AI to do all that and you're completely ignorant to it all. you are just a consumer of AI generated code.&lt;/p&gt;

&lt;p&gt;and if that's all that I can do, run a few prompts and sit there like an ugly duck, then what's the point of being a programmer?&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Left for Programmers?
&lt;/h2&gt;

&lt;p&gt;what's the point of me even being there to tell it what to do.&lt;/p&gt;

&lt;p&gt;it can already ideate, brainstorm, perform market research, competitor analysis, design systems architecture, design database schemas, write code, test code, deploy code, monitor code, fix bugs, optimize performance, refactor code, scale systems and do everything else that I used to do as a programmer.&lt;/p&gt;

&lt;p&gt;perhaps the ONLY thing it's not doing is customer discovery. the grind of calling people, reaching out to them,&lt;br&gt;
asking about their pain points in their workflows, understanding their needs and desires, and then building something for them. The same &lt;a href="https://dev.to/blog/no-competition-red-flag-solopreneur-validated-market"&gt;customer discovery I learned to prioritize&lt;/a&gt; after my first product failure.&lt;/p&gt;

&lt;p&gt;it's not far fetched to think that AI can do that too in the near future.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Craft Evolves
&lt;/h2&gt;

&lt;p&gt;programmers once felt this way about high-level languages replacing assembly. about IDEs replacing &lt;code&gt;vim&lt;/code&gt;. the craft evolves.. maybe the joy migrates too. I just haven't found where it moved yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Keep Going Back to My Piano
&lt;/h2&gt;

&lt;p&gt;at least the piano doesn't autocomplete my scales. maybe that's why I keep going back. some things should stay slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the Balance
&lt;/h2&gt;

&lt;p&gt;so here I am, caught between efficiency and joy. maybe you're here too. if you've found the balance, I'd genuinely love to hear how.&lt;/p&gt;

&lt;p&gt;leave a comment below and share your thoughts!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>indiehackers</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>WE'RE LIVE ON PRODUCT HUNT</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Sat, 29 Nov 2025 12:21:44 +0000</pubDate>
      <link>https://dev.to/meysam81/were-live-on-product-hunt-2n4</link>
      <guid>https://dev.to/meysam81/were-live-on-product-hunt-2n4</guid>
      <description>&lt;p&gt;WE'RE LIVE ON PRODUCT HUNT&lt;/p&gt;

&lt;p&gt;Awesome Directories: 300+ curated launch directories for indie hackers&lt;/p&gt;

&lt;p&gt;→ Free forever&lt;br&gt;
→ Open source (Apache-2.0)&lt;br&gt;
→ Built in 3 weeks&lt;br&gt;
→ $0 revenue (it's free, but who cares)&lt;/p&gt;

&lt;p&gt;🔗 Link below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.producthunt.com/products/awesome-directories" rel="noopener noreferrer"&gt;https://www.producthunt.com/products/awesome-directories&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever wasted time researching "best startup directories," this might save you 20 hours&lt;/p&gt;

&lt;p&gt;That's it. That's the pitch.&lt;/p&gt;

&lt;p&gt;I'm responding to EVERY comment on PH today&lt;/p&gt;

&lt;p&gt;Ask me anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tech stack&lt;/li&gt;
&lt;li&gt;Why I built this&lt;/li&gt;
&lt;li&gt;Why it's free&lt;/li&gt;
&lt;li&gt;What I learned building in public&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll answer everything.&lt;/p&gt;

&lt;p&gt;3-week journey:&lt;/p&gt;

&lt;p&gt;Week 1: Built MVP&lt;br&gt;
Week 2: Shipped features based on feedback&lt;br&gt;
Week 3: Panicked about launch (just kidding… kind of)&lt;/p&gt;

&lt;p&gt;Building in public with zero audience was humbling.&lt;/p&gt;

&lt;p&gt;But here we are.&lt;/p&gt;

&lt;p&gt;How you can help:&lt;br&gt;
→ Upvote if you find it useful (not charity)&lt;br&gt;
→ Comment with your directory experience&lt;br&gt;
→ Share with a founder friend&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;No gimmicks.&lt;/p&gt;

&lt;p&gt;No "I'll upvote yours if you upvote mine" BS.&lt;/p&gt;

&lt;p&gt;Just: does this help you or not?&lt;/p&gt;

&lt;p&gt;I'll be here all day&lt;/p&gt;

&lt;p&gt;Responding.&lt;br&gt;
Sharing updates.&lt;br&gt;
Probably drinking lots of coffees.&lt;/p&gt;

&lt;p&gt;Let's goooo 🚀&lt;/p&gt;

&lt;h1&gt;
  
  
  buildinpublic
&lt;/h1&gt;

</description>
      <category>buildinpublic</category>
      <category>opensource</category>
      <category>productivity</category>
      <category>startup</category>
    </item>
    <item>
      <title>I Sent 200+ Cold Messages and Got Zero Calls: My Customer Discovery Reality Check</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Sat, 29 Nov 2025 12:21:38 +0000</pubDate>
      <link>https://dev.to/meysam81/i-sent-200-cold-messages-and-got-zero-calls-my-customer-discovery-reality-check-3m7p</link>
      <guid>https://dev.to/meysam81/i-sent-200-cold-messages-and-got-zero-calls-my-customer-discovery-reality-check-3m7p</guid>
      <description>&lt;p&gt;200+ cold messages.&lt;/p&gt;

&lt;p&gt;2-3 weeks of outreach.&lt;/p&gt;

&lt;p&gt;Zero calls booked.&lt;/p&gt;

&lt;p&gt;That's my customer discovery reality check.&lt;/p&gt;

&lt;p&gt;I could've waited to share this. Found a better story. Polished the numbers.&lt;/p&gt;

&lt;p&gt;But here's what I've learned building in public:&lt;/p&gt;

&lt;p&gt;The failures are the story.&lt;/p&gt;

&lt;p&gt;After my first SaaS flopped (2-3 months building, 0 customers, $0 revenue), I made myself a promise: no code until someone's ready to pay.&lt;/p&gt;

&lt;p&gt;So I'm doing customer discovery the hard way.&lt;/p&gt;

&lt;p&gt;Cold LinkedIn outreach to strangers who don't know me, don't owe me anything, and mostly ignore me.&lt;/p&gt;

&lt;p&gt;Response rate? Abysmal.&lt;br&gt;
Conversion to calls? Zero.&lt;/p&gt;

&lt;p&gt;Giving up? Not a chance.&lt;br&gt;
My mamma didn't raise no quitter.&lt;/p&gt;

&lt;p&gt;What I'm learning:&lt;br&gt;
→ Consistency beats perfection (I'm seeing more engagement after 2-3 weeks of daily posts)&lt;br&gt;
→ The work you do when nobody's watching compounds&lt;br&gt;
→ Sharing losses builds more trust than curated wins&lt;/p&gt;

&lt;p&gt;This week was a loss by any metric.&lt;/p&gt;

&lt;p&gt;But there's only one way to go from here: forward.&lt;/p&gt;

&lt;p&gt;Full breakdown on my blog (link in comments).&lt;/p&gt;

&lt;p&gt;What's your cold outreach experience been like?&lt;/p&gt;

&lt;p&gt;I'd genuinely love to hear; especially from folks who figured out what I'm clearly missing.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>marketing</category>
      <category>startup</category>
    </item>
    <item>
      <title>48 hours until Awesome Directories launches on Product Hunt</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Wed, 26 Nov 2025 15:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/48-hours-until-awesome-directories-launches-on-product-hunt-3ifd</link>
      <guid>https://dev.to/meysam81/48-hours-until-awesome-directories-launches-on-product-hunt-3ifd</guid>
      <description>&lt;p&gt;48 hours until Awesome Directories launches on Product Hunt&lt;/p&gt;

&lt;p&gt;Quick thread on what I learned building in public for 3 weeks 🧵&lt;/p&gt;

&lt;p&gt;(Spoiler: Follower count is a lie)&lt;/p&gt;

&lt;p&gt;I started with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;15k LinkedIn followers&lt;/li&gt;
&lt;li&gt;200 avg impressions (lol)&lt;/li&gt;
&lt;li&gt;150 X followers&lt;/li&gt;
&lt;li&gt;Zero engagement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I thought: "I have an audience. This will be easy."&lt;/p&gt;

&lt;p&gt;I was wrong.&lt;/p&gt;

&lt;p&gt;Week 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Posted announcement: 3 likes&lt;/li&gt;
&lt;li&gt;Posted tech stack: 12 likes&lt;/li&gt;
&lt;li&gt;Asked a question: 47 likes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lesson: People don't care about YOUR product. They care about THEIR problems.&lt;/p&gt;

&lt;p&gt;Questions &amp;gt; announcements.&lt;/p&gt;

&lt;p&gt;Week 2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shared daily build updates&lt;/li&gt;
&lt;li&gt;Posted polls&lt;/li&gt;
&lt;li&gt;Responded to EVERY comment&lt;/li&gt;
&lt;li&gt;Impressions doubled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lesson: Consistency beats perfection.&lt;/p&gt;

&lt;p&gt;5 posts/week with engagement &amp;gt;&amp;gt; 1 perfect post/week&lt;/p&gt;

&lt;p&gt;Week 3:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stopped saying "I built this"&lt;/li&gt;
&lt;li&gt;Started saying "This might help you"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lesson: Make it about them, not you.&lt;br&gt;
Nobody cares about your product.&lt;/p&gt;

&lt;p&gt;Building in public. Real failures, real lessons.&lt;br&gt;
Join 1,500+ → meysam.io&lt;br&gt;
They care about their problem.&lt;/p&gt;

&lt;p&gt;3-week stats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn impressions: 180 → 520 avg&lt;/li&gt;
&lt;li&gt;X impressions: 30 → 90 avg&lt;/li&gt;
&lt;li&gt;Early access signups: 2&lt;/li&gt;
&lt;li&gt;GitHub stars: 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not viral. But real.&lt;/p&gt;

&lt;p&gt;What I'd do differently:&lt;/p&gt;

&lt;p&gt;✓ Start asking questions Day 1&lt;br&gt;
✓ Share struggles sooner (vulnerability &amp;gt; polish)&lt;br&gt;
✓ Post 2x/day on X (once wasn't enough)&lt;br&gt;
✓ Use more GIFs/screenshots (visual &amp;gt; text)&lt;/p&gt;

&lt;p&gt;Friday 12:01am PST:&lt;/p&gt;

&lt;p&gt;We launch on Product Hunt&lt;/p&gt;

&lt;p&gt;I'll be there.&lt;br&gt;
Responding to comments.&lt;br&gt;
Sharing behind-the-scenes.&lt;br&gt;
Probably panicking.&lt;/p&gt;

&lt;p&gt;Link in the comments&lt;/p&gt;

&lt;p&gt;See you Friday 🚀&lt;/p&gt;

&lt;h1&gt;
  
  
  buildinpublic
&lt;/h1&gt;

</description>
      <category>buildinpublic</category>
      <category>opensource</category>
      <category>startup</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Awesome Directories launches on Product Hunt THIS FRIDAY</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Mon, 24 Nov 2025 15:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/awesome-directories-launches-on-product-hunt-this-friday-3cge</link>
      <guid>https://dev.to/meysam81/awesome-directories-launches-on-product-hunt-this-friday-3cge</guid>
      <description>&lt;p&gt;Awesome Directories launches on Product Hunt THIS FRIDAY&lt;/p&gt;

&lt;p&gt;Here's everything you need to know in one thread 🧵&lt;/p&gt;

&lt;p&gt;(And how you can help, if you want)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;300+ curated launch directories for indie hackers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free forever&lt;/li&gt;
&lt;li&gt;Open source (Apache-2.0)&lt;/li&gt;
&lt;li&gt;No sign-up required&lt;/li&gt;
&lt;li&gt;Built by a founder, for founders&lt;/li&gt;
&lt;li&gt;CLI available for nerds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why I built it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I wasted 20 hours researching directories for my last launch&lt;br&gt;
You shouldn't have to&lt;/p&gt;

&lt;p&gt;That's it. That's the reason.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filter by DR, dofollow, pricing&lt;/li&gt;
&lt;li&gt;Multi-select checklist export&lt;/li&gt;
&lt;li&gt;Community voting (wisdom of crowds)&lt;/li&gt;
&lt;li&gt;Real-time search&lt;/li&gt;
&lt;li&gt;Screenshot generator for social&lt;/li&gt;
&lt;li&gt;Submission tracking (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Launch day plan (Friday 12:01am PST):&lt;/p&gt;

&lt;p&gt;I'll be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responding to EVERY comment on PH&lt;/li&gt;
&lt;li&gt;Sharing behind-the-scenes on Twitter&lt;/li&gt;
&lt;li&gt;Probably drinking too much coffee&lt;/li&gt;
&lt;li&gt;Refreshing PH every 30 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How you can help (if you want):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✓ Upvote on Product Hunt (Friday morning)&lt;br&gt;
✓ Share your experience with directories (comment on PH)&lt;br&gt;
✓ Retweet this thread (help me reach founders)&lt;/p&gt;

&lt;p&gt;I'm not asking for charity. Only if you genuinely find it useful.&lt;/p&gt;

&lt;p&gt;Link in the first comment&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why am I building in public?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because 15k LinkedIn followers with 200 avg impressions taught me:&lt;/p&gt;

&lt;p&gt;Follower count means nothing.&lt;br&gt;
Trust means everything.&lt;/p&gt;

&lt;p&gt;Transparency &amp;gt; polish.&lt;/p&gt;

&lt;p&gt;See you Friday 🚀&lt;/p&gt;

&lt;p&gt;I'll be the guy nervously refreshing PH at 12:01am&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.producthunt.com/products/awesome-directories" rel="noopener noreferrer"&gt;https://www.producthunt.com/products/awesome-directories&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's goooo&lt;/p&gt;

&lt;h1&gt;
  
  
  buildinpublic #indiehacker #opensource
&lt;/h1&gt;

</description>
      <category>buildinpublic</category>
      <category>opensource</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>I Sent 200+ Cold Messages and Got Zero Calls: My Customer Discovery Reality Check</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/i-sent-200-cold-messages-and-got-zero-calls-my-customer-discovery-reality-check-17a6</link>
      <guid>https://dev.to/meysam81/i-sent-200-cold-messages-and-got-zero-calls-my-customer-discovery-reality-check-17a6</guid>
      <description>&lt;h1&gt;
  
  
  I spent that last 2-3 weeks sending 200-300 cold outreach
&lt;/h1&gt;

&lt;p&gt;I'm working on a new idea these days.&lt;/p&gt;

&lt;p&gt;I've identified my niche...&lt;/p&gt;

&lt;p&gt;researched the market...&lt;/p&gt;

&lt;p&gt;analyzed the trends...&lt;/p&gt;

&lt;p&gt;I've gathered some initial intel and aggregated some insights to help me navigate the next few steps.&lt;/p&gt;

&lt;p&gt;they are essentially just a starter for me.. nothing fancy.&lt;/p&gt;

&lt;p&gt;since I know from experience that &lt;em&gt;the things that you can't sell, are the things not worth building&lt;/em&gt;, I'm not writing code yet&lt;br&gt;
unless I know someone is taking out their credit card and paying for it with real money.&lt;/p&gt;

&lt;p&gt;that means that I am strongly bullish on customer discovery these days.&lt;/p&gt;

&lt;p&gt;I've sent out around a few hundreds so far&lt;/p&gt;

&lt;p&gt;the conversions are low, to say the least..&lt;/p&gt;

&lt;p&gt;but I'm locked in&lt;/p&gt;

&lt;p&gt;I'm no quitter. &lt;strong&gt;my mamma didn't raise no quitter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;we're just getting started.&lt;/p&gt;

&lt;p&gt;anyway, there's no crazy progress to share, only that I've been doing these cold outreach via LinkedIn and the response&lt;br&gt;
rate is abysmal.&lt;/p&gt;

&lt;p&gt;and so far, zero people got on a call.&lt;/p&gt;

&lt;p&gt;the day I get to talk to 5-10 people is what I'd call Christmas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons learned so far
&lt;/h2&gt;

&lt;p&gt;I've been building in public for the past 2-3 weeks, much more seriously than I've done so before.&lt;/p&gt;

&lt;p&gt;I shared my progress, my screenshots, my numbers and metrics publicly...&lt;/p&gt;

&lt;p&gt;and the lesson is that consistency is key.&lt;/p&gt;

&lt;p&gt;prior to this, I didn't get lots of impression nor engagement.&lt;/p&gt;

&lt;p&gt;but lately I'm seeing a few likes here and there, maybe 1 comment the lady luck is with me that day&lt;/p&gt;

&lt;p&gt;nothing to celebrate like a La Liga championship, but it is still progress&lt;/p&gt;

&lt;p&gt;and believe me, for a perfectionist, progress is hard to come by.&lt;/p&gt;

&lt;h2&gt;
  
  
  2nd Public Piano Performance
&lt;/h2&gt;

&lt;p&gt;last week I had my second public performance as a student learning to play piano.&lt;/p&gt;

&lt;p&gt;the result of that performance is available at the following YouTube link: &lt;a href="https://youtube.com/shorts/jgPCoNX3iGI" rel="noopener noreferrer"&gt;https://youtube.com/shorts/jgPCoNX3iGI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="/assets/2nd-public-performance.jpg" class="article-body-image-wrapper"&gt;&lt;img src="/assets/2nd-public-performance.jpg" alt="Piano Performance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am not going to include an embed because Google will slow down the page loading speed significantly, not to mention&lt;br&gt;
the massive tracking and privacy concerns it raises.&lt;/p&gt;

&lt;p&gt;it's like a leach on your website, sucking the life out of it, ruining the user experience and making your visitors miserable.&lt;/p&gt;

&lt;p&gt;this is another example of showing up consistently. small wins add up, whether in cold outreach, building in public, or learning an instrument.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launching soon
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;https://awesome-directories.com&lt;/a&gt; is fully live.. two weeks so far...&lt;/p&gt;

&lt;p&gt;we're live on Product Hunt this Friday: &lt;a href="https://www.producthunt.com/products/awesome-directories" rel="noopener noreferrer"&gt;https://www.producthunt.com/products/awesome-directories&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would appreciate if you could take the time to check it out and leave a comment or an upvote&lt;/p&gt;

&lt;p&gt;especially comments since those are a more serious signal of engagement than upvotes&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;I have a few ideas in mind&lt;/li&gt;
&lt;li&gt;some pre-baked products that need final touches&lt;/li&gt;
&lt;li&gt;more customer discovery to do&lt;/li&gt;
&lt;li&gt;learning my craft&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and most important of all, the thing that keeps me up at night is this:&lt;/p&gt;

&lt;p&gt;for every Monday, I map out a plan for my upcoming seven days, in a way that I have something to share as a key takeaway and/or&lt;br&gt;
lesson in the next week when sharing my build in public journey.&lt;/p&gt;

&lt;p&gt;this piece you're reading right now is a part of that plan.&lt;/p&gt;

&lt;p&gt;I hope to continue sharing vulnerable struggles and even losses.&lt;/p&gt;

&lt;p&gt;for example, this week and with hundreds of outreach and zero customer calls is a loss.&lt;/p&gt;

&lt;p&gt;onwards and upwards because there's only one way to go from here: forward.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>solopreneur</category>
      <category>indiehackers</category>
      <category>customerdiscovery</category>
    </item>
    <item>
      <title>I Built a Directory Aggregator in One Weekend (Then Made It Open Source)</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Mon, 17 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/i-built-a-directory-aggregator-in-one-weekend-then-made-it-open-source-1k1k</link>
      <guid>https://dev.to/meysam81/i-built-a-directory-aggregator-in-one-weekend-then-made-it-open-source-1k1k</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Directory Aggregator in One Weekend (Then Made It Open Source)
&lt;/h1&gt;

&lt;p&gt;I spent 15 hours last week clicking through outdated listicles and $127 PDFs trying to find decent directories to launch a SaaS. I got frustrated. So I built &lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;awesome-directories.com&lt;/a&gt; over the weekend.&lt;/p&gt;

&lt;p&gt;Total development time: ~10 hours spread across one weekend plus evening sessions this week. It's live. It's open source. It's free forever. And it's ready for beta users.&lt;/p&gt;

&lt;p&gt;Here's what I built, how I built it, and why I'm giving it away.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Nobody Solved Well
&lt;/h2&gt;

&lt;p&gt;Every founder I talk to has the same ritual: spending 2-3 days hunting for directories where they can launch their product. You click through blog posts from 2023 with half the links dead. You find "ultimate lists" with 300+ directories where maybe 10 actually matter. You discover paid spreadsheets charging $127-$6,999 for what amounts to a glorified CSV file.&lt;/p&gt;

&lt;p&gt;The existing solutions have three fundamental problems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dead links everywhere.&lt;/strong&gt; Most directory aggregators are one-time projects that never get maintained. Links rot. Sites shut down. Nobody updates them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signal-to-noise ratio is terrible.&lt;/strong&gt; When someone gives you 300 directories, that's not helpful—that's overwhelming. My research showed that 3-5 directories drive 90-95% of actual launch results. The other 295? Noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No context, no curation.&lt;/strong&gt; A URL and a name don't tell you what you actually need to know: Is it dofollow? Is it free? What's the Domain Rating? Is the site even active?&lt;/p&gt;

&lt;p&gt;I needed something better. So I built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;Awesome Directories&lt;/a&gt; is a curated directory aggregator that helps you find the top 20-30 directories worth your time in under 3 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;388+ manually curated directories (verified, not scraped)&lt;/li&gt;
&lt;li&gt;Real-time filtering by Domain Rating, category, pricing, dofollow status&lt;/li&gt;
&lt;li&gt;Instant search across names, descriptions, and categories&lt;/li&gt;
&lt;li&gt;Multi-select checklist with PDF/CSV export&lt;/li&gt;
&lt;li&gt;Weekly automated Domain Rating updates&lt;/li&gt;
&lt;li&gt;Community voting and reviews (authentication required)&lt;/li&gt;
&lt;li&gt;Lightning-fast performance (all Lighthouse scores above 90)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What makes it different:&lt;/strong&gt; Every directory is verified. I didn't scrape these from somewhere else. I went through each one, checked if it's active, verified the submission process works, and documented what actually matters: pricing, link type, Domain Rating.&lt;/p&gt;

&lt;p&gt;The filtering is instantaneous. You can search, filter by multiple criteria, and see results update in real-time without any lag. Select the directories that match your product, export to PDF or CSV, and you're done. Three minutes instead of three days.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It (The Technical Deep Dive)
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. I had one weekend and a constraint: zero ongoing costs. This forced some interesting architectural decisions that actually made the product better.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Astro v5 as the foundation.&lt;/strong&gt; Not React, not Next.js, not pure Vue. Astro lets me build statically generated pages that are SEO-optimized by default, with minimal JavaScript shipped to the client. The entire site is static HTML + CSS with tiny Vue islands for interactive components.&lt;/p&gt;

&lt;p&gt;Why Astro? Three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;pSEO capabilities.&lt;/strong&gt; Every directory could theoretically get its own optimized landing page. Static generation makes this trivial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance.&lt;/strong&gt; Astro ships zero JavaScript by default. You only get JS for the components that actually need interactivity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer experience.&lt;/strong&gt; Component-based like modern frameworks, but outputs plain HTML. Best of both worlds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Vue islands for interactivity.&lt;/strong&gt; The filtering, search, and checklist features? Those are small Vue components that hydrate on the client. Everything else is just HTML. This is why the Lighthouse scores are all above 90—there's barely any JavaScript to parse and execute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supabase for everything backend.&lt;/strong&gt; PostgreSQL database, authentication (Google and GitHub OAuth), and—here's the cool part—automated weekly updates via Supabase Edge Functions + the &lt;code&gt;pg_cron&lt;/code&gt; extension.&lt;/p&gt;

&lt;p&gt;Every Sunday at 2 AM UTC, a cron job triggers an Edge Function that fetches fresh Domain Rating scores from the Moz API and updates the database. No GitHub Actions. No external servers. It's all inside Supabase. Set it once, forget it forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Netlify for preview deployments.&lt;/strong&gt; GitHub Actions builds the static site (&lt;code&gt;bun run build&lt;/code&gt;), uploads the &lt;code&gt;dist&lt;/code&gt; folder to Netlify, and I get instant preview URLs for every commit. Zero cost. Instant feedback on every change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tailwind CSS for styling.&lt;/strong&gt; I needed to ship fast. Tailwind let me prototype rapidly without fighting CSS specificity or maintaining separate stylesheets. Is the design perfect? No. Is it functional and clean? Yes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture Decisions That Mattered
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Static-first architecture.&lt;/strong&gt; Everything that can be pre-rendered at build time is pre-rendered. The directory data lives in Supabase, gets fetched at build time, and baked into static HTML. Users get instant page loads. I get zero server costs.&lt;/p&gt;

&lt;p&gt;The only dynamic parts are authentication (handled by Supabase), voting (requires auth, hits Supabase realtime), and comments (Supabase database + auth). Everything else is static files served from a CDN.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication-gated interactions.&lt;/strong&gt; Initially, I considered IP-based voting. Simpler, no login friction. But it's gameable and doesn't build a real community. I pivoted: you need to authenticate (Google or GitHub OAuth via Supabase) to vote or comment.&lt;/p&gt;

&lt;p&gt;This does two things: it filters for engaged users, and it gives me a foundation for future features (saved lists, submission tracking, etc.). The friction is worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supabase for comments, not a third-party tool.&lt;/strong&gt; I could've integrated Giscus or Disqus. Instead, I built comments directly in Supabase. Why? Control. Data ownership. And honestly, it was faster than integrating and configuring a third-party service.&lt;/p&gt;

&lt;p&gt;Comments are stored in a PostgreSQL table with Row Level Security policies. Authentication is handled by Supabase. Realtime updates are built-in. I didn't need to build much—I just wired together Supabase primitives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance obsession.&lt;/strong&gt; All Lighthouse scores above 90. This wasn't an accident. Astro's static generation handles most of the heavy lifting, but I also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lazy-load images with proper &lt;code&gt;loading="lazy"&lt;/code&gt; attributes&lt;/li&gt;
&lt;li&gt;Minimize JavaScript hydration (only 3 Vue islands total)&lt;/li&gt;
&lt;li&gt;Use Tailwind's JIT compiler to ship minimal CSS&lt;/li&gt;
&lt;li&gt;Serve everything through Netlify's CDN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First contentful paint is under 1.2 seconds even on 3G.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Time Breakdown
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Saturday (5 hours):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up Astro project with Tailwind&lt;/li&gt;
&lt;li&gt;Design Supabase schema (directories table, votes, comments)&lt;/li&gt;
&lt;li&gt;Build core directory listing page with Vue island for filters&lt;/li&gt;
&lt;li&gt;Implement real-time search and filtering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sunday (3 hours):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-select checklist component&lt;/li&gt;
&lt;li&gt;PDF/CSV export (using jsPDF and Papa Parse)&lt;/li&gt;
&lt;li&gt;Deploy to Netlify, set up custom domain&lt;/li&gt;
&lt;li&gt;Configure Supabase authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 1 evenings (2 hours):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up Supabase Edge Function for weekly DR updates&lt;/li&gt;
&lt;li&gt;Configure &lt;code&gt;pg_cron&lt;/code&gt; for automated scheduling&lt;/li&gt;
&lt;li&gt;Fix edge cases in filtering logic&lt;/li&gt;
&lt;li&gt;Polish UI, fix responsive layout issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total: ~10 hours from zero to shipped product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Open Source (The Strategic Pivot)
&lt;/h2&gt;

&lt;p&gt;Here's where I need to be transparent.&lt;/p&gt;

&lt;p&gt;I originally planned to charge for this. I did market research, validated the problem with 40+ founder interviews, built pricing tiers—$9/month or $49/year. The pain point was real. People said they'd pay.&lt;/p&gt;

&lt;p&gt;Then I looked at the unit economics.&lt;/p&gt;

&lt;p&gt;At my scale—no existing audience, no email list, no distribution—customer acquisition cost would be $40-60. To break even, I'd need subscribers to stay for 6+ months. But this is a tool people use once or twice a year, max. The retention math was broken before I even launched.&lt;/p&gt;

&lt;p&gt;I could force a business model that doesn't make sense, or I could pivot to something that actually works at my scale: &lt;strong&gt;building credibility and audience through open source.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The real opportunity isn't $9/month from 100 people. It's recognition in the indie hacker space. This project is my credential. It's proof I can identify a problem, build a solution, and ship it fast. It's my way into conversations with other founders.&lt;/p&gt;

&lt;p&gt;Plus, I just wanted this to exist. If it helps other founders save 15+ hours of research hell, that's already worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Apache-2.0 license means for you:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fork it, modify it, self-host it&lt;/li&gt;
&lt;li&gt;Use it commercially&lt;/li&gt;
&lt;li&gt;No attribution required (though appreciated)&lt;/li&gt;
&lt;li&gt;No paywalls, ever&lt;/li&gt;
&lt;li&gt;No bait-and-switch to freemium&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is free forever because the business model isn't "charge users"—it's "build reputation in a space I care about."&lt;/p&gt;

&lt;h2&gt;
  
  
  Current State &amp;amp; What's Next
&lt;/h2&gt;

&lt;p&gt;The product is stable. Most of the early bugs are fixed. Authentication works reliably. Filtering is fast. Export works. Weekly DR updates run automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I need from beta users:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edge cases I haven't found yet&lt;/li&gt;
&lt;li&gt;Feature priority feedback (what actually matters to you?)&lt;/li&gt;
&lt;li&gt;Directory suggestions (know a high-quality one I'm missing?)&lt;/li&gt;
&lt;li&gt;Reviews and votes (helps surface signal for other users)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Launching on Product Hunt next Friday.&lt;/strong&gt; But I'm not waiting to get feedback. If you're launching a product soon, &lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;try it now&lt;/a&gt;. If something breaks or feels wrong, &lt;a href="https://github.com/awesome-directories/awesome-directories/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Immediate roadmap (shaped by community, not ego):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser extension for one-click directory submissions&lt;/li&gt;
&lt;li&gt;Verified badges for directory creators who engage&lt;/li&gt;
&lt;li&gt;More granular filtering (submission turnaround time, geographic focus)&lt;/li&gt;
&lt;li&gt;Public API for programmatic access&lt;/li&gt;
&lt;li&gt;Integration with popular launch checklists&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But honestly? The roadmap will be shaped by what you actually need, not what I think is cool.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Research saves time.&lt;/strong&gt; I spent almost as much time validating the problem and researching the market as I did coding. That research saved me from building a subscription product with broken unit economics. It informed the curation strategy (focus on the top 20-30, not 300+). It shaped the feature set (filtering and export, not social features).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static architecture = speed + zero costs.&lt;/strong&gt; Astro's static generation isn't just about performance—it's about economics. No server costs. No scaling concerns. No database read costs spiraling. Just static files on a CDN. This is how you build sustainable side projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supabase Edge Functions + pg_cron is criminally underutilized.&lt;/strong&gt; Everyone reaches for GitHub Actions or external cron services. But if you're already using Supabase, you have PostgreSQL's built-in cron scheduler. Write an Edge Function, schedule it with &lt;code&gt;pg_cron&lt;/code&gt;, and you have automated workflows that never leave your database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication-gated interactions filter for quality.&lt;/strong&gt; The friction of requiring login kills casual spam and builds a real community. Yes, you lose some engagement. But the engagement you keep is higher signal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open source can be your credential, not just your code.&lt;/strong&gt; This project won't make me money directly. But it's already opening doors. Conversations with other founders. Visibility in communities I care about. Proof I can ship. That's worth more than $9/month from 50 people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ship when it works, not when it's perfect.&lt;/strong&gt; The UI isn't polished. Some edge cases probably exist. The roadmap is incomplete. But it solves the core problem—finding quality directories fast—and that's enough to ship. Perfection is procrastination in disguise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Journey
&lt;/h2&gt;

&lt;p&gt;This is my first major public project as an indie hacker. I built it to solve my own problem, made it free because the unit economics made sense that way, and I'm documenting the journey because I'm learning as I go.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If you're launching a product and want to skip 15+ hours of directory research:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;Try awesome-directories.com&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If you think something could work better:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/awesome-directories/awesome-directories/issues" rel="noopener noreferrer"&gt;Open an issue&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If you want to contribute:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/awesome-directories/awesome-directories" rel="noopener noreferrer"&gt;Star the repo&lt;/a&gt; (helps with Product Hunt visibility)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Submit a PR for missing directories&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leave a review to help other founders&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built by indie hackers, for indie hackers. No VC funding. No growth hacking. Just solving real problems with good code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Launch on Product Hunt: Next Friday.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;See you there.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>opensource</category>
      <category>indiehackers</category>
      <category>supabase</category>
    </item>
    <item>
      <title>I Used AI to Write My Last Blog Post and HN Flagged It</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Fri, 14 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/i-used-ai-to-write-my-last-blog-post-and-hn-flagged-it-3opb</link>
      <guid>https://dev.to/meysam81/i-used-ai-to-write-my-last-blog-post-and-hn-flagged-it-3opb</guid>
      <description>&lt;h2&gt;
  
  
  What's all this fuss about AI-written content on Hacker News?
&lt;/h2&gt;

&lt;p&gt;so, this week, &lt;del&gt;I wrote&lt;/del&gt; AI wrote &lt;a href="https://dev.to/blog/no-competition-red-flag-solopreneur-validated-market"&gt;a blog post&lt;/a&gt; for me on Monday Nov 10th.&lt;/p&gt;

&lt;p&gt;I didn't submit it right away the same day, because I wanted a steady momentum from other social media platforms first.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Unexpected Viral Moment
&lt;/h3&gt;

&lt;p&gt;then on Thursday evening (my evening, EST/PST's morning)&lt;/p&gt;

&lt;p&gt;it got submitted and over the first half an hour of submission, it got a few upvotes and a few comments&lt;/p&gt;

&lt;p&gt;it was a clear and early sign of going "viral" on HN&lt;/p&gt;

&lt;p&gt;I say viral in quotes because I have never had a viral moments on HN, never before, not at this scale&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters to Small Creators
&lt;/h3&gt;

&lt;p&gt;now you might be a content creator who gets these numbers for lunch but for me it's a different story. for me these numbers matter&lt;/p&gt;

&lt;p&gt;cause my normal numbers are usually around 200 impressions (from 15k linkedin followers), maybe 1-2 likes and zero comments (from my 150 X followers), and generally, I never got any more than 2 upvotes for my personal blog posts on HN before&lt;/p&gt;

&lt;p&gt;so you can imagine this is a big deal for me. not for Elon Musk and others of course but I'm no billionaire, hell I'm not even a millionaire&lt;/p&gt;

&lt;p&gt;now, you can go ahead and read the subsmission for yourself, it's at the bottom of this page in the references section&lt;/p&gt;

&lt;p&gt;but here's my line of thoughts towards those folks who were calling me out, making me look like a villain&lt;/p&gt;

&lt;p&gt;here's the unfiltered, non-AI generated format of how I would like to speak to those individuals who were so blatantly against my submission&lt;/p&gt;

&lt;h2&gt;
  
  
  My raw, non-AI and unfiltered response to HN folks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Moral High Ground Problem
&lt;/h3&gt;

&lt;p&gt;what's all this moral high ground everyone takes?&lt;/p&gt;

&lt;p&gt;English is not my first language and HN is, let's face it, primarily for US and English speaking folks&lt;/p&gt;

&lt;p&gt;I, just like any other small creator, am just trying to submit my website, get a juicy backlink and increase my chance of survival over millions of billions of other webpages across the web, and hopefully get some discussions going, learn something and ideally I may even get some email subscribers to my newsletter&lt;/p&gt;

&lt;p&gt;which I DID&lt;/p&gt;

&lt;h3&gt;
  
  
  The Numbers Don't Lie
&lt;/h3&gt;

&lt;p&gt;now, let's talk numbers before I go deeper.&lt;/p&gt;

&lt;p&gt;in less than 12hr from submission, I got nearly 1200+ unique visitors to my website, &lt;a href="https://meysam.io" rel="noopener noreferrer"&gt;meysam.io&lt;/a&gt;, I even got 100% traffic increase to my other OSS project &lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;awesome-directories.com&lt;/a&gt; in the same timeframe&lt;/p&gt;

&lt;p&gt;that is not prejudice or bias, that is just pure data-driven outcome, or decision making framework if I may; out of those 1.2k, 4m avg duration spent on the website and 93% bounce rate from all around the glob and not just the USA (48%)&lt;/p&gt;

&lt;p&gt;I even got two new subscribers to my newsletter, which is the whole fucking point of writing and building in public in the first place&lt;/p&gt;

&lt;p&gt;here's the screenshot of my analytics page below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmeysam.io%2Fassets%2Fhn-submission-analytics.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmeysam.io%2Fassets%2Fhn-submission-analytics.png" alt="Analytics screenshot showing 1.2k unique visitors, 4m avg duration, and 93% bounce rate" width="800" height="723"&gt;&lt;/a&gt;&lt;br&gt;Fig.1 - Analytics screenshot showing 1.2k unique visitors, 4m avg duration, and 93% bounce rate
  &lt;/p&gt;

&lt;h3&gt;
  
  
  My Unapologetic Stance on Using AI
&lt;/h3&gt;

&lt;p&gt;now I am not denying that I didn't write the blog post entirely from AI&lt;/p&gt;

&lt;p&gt;I use AI daily for everything, development or marketing&lt;/p&gt;

&lt;p&gt;and I am not shy nor am I going to apologize to no-fucking-body&lt;/p&gt;

&lt;p&gt;I mean, technology is here to make our lives easier, more efficient and faster&lt;/p&gt;

&lt;p&gt;does anyone blame students for using calculator for performing their number churn?&lt;/p&gt;

&lt;p&gt;how about business worlds where we use tech everyday to speed up the revenue?&lt;/p&gt;

&lt;p&gt;I was using C++ back in the day, then python and then Go, and now AI.&lt;br&gt;
are you gonna cry about it? grow the fuck up.&lt;/p&gt;

&lt;p&gt;I am using AI. sue me.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI-Written Content Backlash
&lt;/h3&gt;

&lt;p&gt;why is there so many backlashes? what's the hate towards AI-written content?&lt;/p&gt;

&lt;p&gt;do you not see AI blog post generator these days popping out like mushrooms?&lt;br&gt;
I know a handful few and I'm not gonna drop names here but do you go out dismissing their entire business model because you don't like AI-fucking-writing-style?&lt;/p&gt;

&lt;h3&gt;
  
  
  It's Well-Written, Period
&lt;/h3&gt;

&lt;p&gt;I mean, the blog post is very well-written, &lt;a href="https://dev.to/blog/no-competition-red-flag-solopreneur-validated-market"&gt;read it&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;it is punchy, very engaging, it is breathtaking and you almost do not blink while you're reading it&lt;/p&gt;

&lt;p&gt;it is a very well-focused, high-engagement piece of article; a great storytelling, a solid narrative&lt;/p&gt;

&lt;p&gt;and it is not something that's fake or anything&lt;/p&gt;

&lt;p&gt;it's coming from my own raw thoughts&lt;/p&gt;

&lt;p&gt;I fed the AI with my thoughts and asked it to ask me questions, the answers of which will shape a high-engaging blog post with my tone, with my authenticitiy, with my own personal and emotional twist&lt;/p&gt;

&lt;h3&gt;
  
  
  The Time Reality Check
&lt;/h3&gt;

&lt;p&gt;and I am darn happy with the result because it has been written in a way I couldn't have done myself in a hundred years&lt;/p&gt;

&lt;p&gt;ok, maybe that's exaggeration and I could've written it better without AI slop in a more authentic manner&lt;/p&gt;

&lt;p&gt;but how long would that take me? months? years? with AI it only took minutes&lt;/p&gt;

&lt;p&gt;and I have personal life outside this fucking creator world that I need to manage&lt;/p&gt;

&lt;p&gt;I'm not even an influencer&lt;/p&gt;

&lt;p&gt;I just need a very well written piece of content that is engaging, brings in eyeballs, and makes sure to captures the essence of my thoughts and feelings and hopefully results in a few email subscribers at the end of the day&lt;/p&gt;

&lt;h3&gt;
  
  
  First Viral Moment Ever
&lt;/h3&gt;

&lt;p&gt;I have NEVER EVER in my life had any viral HN moment before and this "AI written slop" everyone is complaining about has gained 1.2k unique visitors in just half a day&lt;br&gt;
and what's wrong with that?&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Like It? Don't Read It
&lt;/h3&gt;

&lt;p&gt;EVERYONE is entitled to their opinion&lt;/p&gt;

&lt;p&gt;but frankly, if you don't like the styling dude? don't fucking read it.&lt;/p&gt;

&lt;p&gt;I'm not here to please you or any other motherfucker.&lt;/p&gt;

&lt;p&gt;I'm sharing this stuff publicly, free of charge, in a democratized internet out to the world where things are shared freely without any regard to gender, race, or any other discrimination factor&lt;/p&gt;

&lt;p&gt;you don't appreciate this style and this content? don't fucking read it and stop fucking complaining about other people's free contents you pay zero dollar to read&lt;/p&gt;

&lt;h3&gt;
  
  
  The Open Web and Real Struggles
&lt;/h3&gt;

&lt;p&gt;it's a fucking democratized internet, the open web, the place where no idiotic politician prick is allowed to withhold me from entering the borders of a country because of my place of birth; any Iraninan citizen in the audience!? yeah, fuck, I can't even open a bank account (FATF, anyone?) in any part of the world without being slapped in the forehead that my country is sanctioned from all the eathly and non-earthly regions of this world.&lt;/p&gt;

&lt;h3&gt;
  
  
  This Is My Real Experience
&lt;/h3&gt;

&lt;p&gt;this blog post, the earlier ones, and all the ones that will SURELY come is my real experience&lt;/p&gt;

&lt;p&gt;real feelings&lt;/p&gt;

&lt;p&gt;every line of the blog post is my own personal life&lt;/p&gt;

&lt;p&gt;just written by AI in a high-engaging manner. not this one (for a reason).&lt;/p&gt;

&lt;p&gt;and now all of a sudden everyone gets on a moral high ground that I am the fucking villain? fuck you&lt;/p&gt;

&lt;h3&gt;
  
  
  The Experiment Begins
&lt;/h3&gt;

&lt;p&gt;I could never had done &lt;a href="https://dev.to/blog/no-competition-red-flag-solopreneur-validated-market"&gt;such a punchy masterpiece&lt;/a&gt; if I had written in an "authentic and genuine manner with my own tone and voice"&lt;/p&gt;

&lt;p&gt;nobody would've cared enough to fucking read it. are you reading this one? well, then I consider myself a lucky fucking bastard!&lt;/p&gt;

&lt;p&gt;for just a simple experiment, and just to test the waters, I will write the next few blog posts in the same tone and style as the one you're currently reading&lt;/p&gt;

&lt;p&gt;let's see if the aggregate of all the view counts in the sum of all those blog posts will match the one written by AI in my last blog post!&lt;/p&gt;

&lt;p&gt;let's see if any of those haters will come back to say &lt;em&gt;"you did great, I love your authentic voice, keep going and I will keep coming back to read your unpolished bullshit&lt;/em&gt;"&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The Experiment Begins&lt;/em&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>indiehacker</category>
      <category>solopreneur</category>
      <category>hackernews</category>
    </item>
    <item>
      <title>I Built an Open-Source Directory Aggregator So You Don't Waste 20+ Hours Researching Launch Platforms</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Wed, 12 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/i-built-an-open-source-directory-aggregator-so-you-dont-waste-20-hours-researching-launch-2ilo</link>
      <guid>https://dev.to/meysam81/i-built-an-open-source-directory-aggregator-so-you-dont-waste-20-hours-researching-launch-2ilo</guid>
      <description>&lt;h2&gt;
  
  
  The Problem I Got Tired Of
&lt;/h2&gt;

&lt;p&gt;Every founder I talk to has this same painful ritual: spending 2-3 days clicking through listicles, spreadsheets, and paid "ultimate guides" to find directories where they can launch their product. Most of these resources are either outdated, include 300+ low-quality directories, or cost $127-$6,999 for a glorified CSV file.&lt;/p&gt;

&lt;p&gt;I went through this myself and thought: there has to be a better way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;Awesome Directories&lt;/a&gt; is an open-source directory aggregator that helps you find the top 20-30 directories worth your time in under 3 minutes. Think of it as the antidote to directory overload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ 388+ curated directories (manually verified, not scraped)&lt;/li&gt;
&lt;li&gt;🔍 Advanced filtering by Domain Rating, category, pricing, dofollow status&lt;/li&gt;
&lt;li&gt;⚡ Real-time search across names, descriptions, and categories&lt;/li&gt;
&lt;li&gt;📋 Multi-select checklist with PDF/CSV export&lt;/li&gt;
&lt;li&gt;📊 Weekly automated DR updates via GitHub Actions&lt;/li&gt;
&lt;li&gt;💬 Community reviews via Giscus (GitHub Discussions)&lt;/li&gt;
&lt;li&gt;👍 IP-based voting system for quality signals&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;Built with a modern, performant stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend: Vue.js 3 (Composition API) + Vite + Tailwind CSS
Backend: Supabase (PostgreSQL + Auth + Realtime)
Hosting: GitHub Pages (100% static SPA)
Newsletter: Mautic (self-hosted)
Analytics: Pirsch (privacy-first)
CI/CD: GitHub Actions
APIs: Moz API for Domain Rating scores
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why Vue + Supabase? I needed something fast to build with, great DX, and Supabase's free tier is genuinely generous for an MVP. The entire app is a static SPA deployed on GitHub Pages, which means zero hosting costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Free Forever?
&lt;/h2&gt;

&lt;p&gt;Here's where I'll be transparent: I originally planned a subscription model. Did the market research, validated the pain point, built pricing tiers. Then I looked at the unit economics and realized something uncomfortable—the numbers didn't make sense for a sustainable business at my scale.&lt;/p&gt;

&lt;p&gt;Instead of forcing a business model that would compromise the value, I pivoted to open-source. The real opportunity isn't in charging $9/month—it's in building credibility and an audience in the indie hacker space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apache-2.0 License - fork it, modify it, self-host it&lt;/li&gt;
&lt;li&gt;No paywalls, ever&lt;/li&gt;
&lt;li&gt;No "freemium" bait-and-switch&lt;/li&gt;
&lt;li&gt;Community-driven feature development&lt;/li&gt;
&lt;li&gt;Transparent roadmap and development&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Weekly Automated DR Updates
&lt;/h3&gt;

&lt;p&gt;GitHub Actions runs every Sunday at 2 AM UTC to fetch fresh Domain Rating scores from the Moz API. This ensures the data stays current without manual intervention.&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="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;Update Domain Ratings&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;bun run scripts/update-dr.js&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;MOZ_API_ACCESS_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.MOZ_API_ACCESS_ID }}&lt;/span&gt;
    &lt;span class="na"&gt;MOZ_API_SECRET_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.MOZ_API_SECRET_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Privacy-First Architecture
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No tracking cookies&lt;/li&gt;
&lt;li&gt;IP-based voting (hashed, not stored)&lt;/li&gt;
&lt;li&gt;Optional authentication (Google/GitHub OAuth)&lt;/li&gt;
&lt;li&gt;All analytics via Pirsch (GDPR-compliant)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Static SPA Performance
&lt;/h3&gt;

&lt;p&gt;The entire app is pre-rendered and served as static assets. First contentful paint under 1.2s, even on 3G.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Community-Driven Reviews
&lt;/h3&gt;

&lt;p&gt;Instead of building yet another commenting system, I integrated Giscus. Every directory gets a dedicated GitHub Discussion thread. Developers already use GitHub—why make them create another account?&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Research matters more than I thought:&lt;/strong&gt; I spent almost as much time validating the problem and researching the market as I did coding. That research saved me from building a subscription product nobody would pay for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 80/20 rule is extreme:&lt;/strong&gt; In my research, I found that just 3-5 directories drive 90-95% of actual results for most launches. The rest is noise. This informed the entire curation strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Hunt isn't what it used to be:&lt;/strong&gt; Featured launch rates dropped from 60-98% (2023) to only 10% (2024). The conventional wisdom around launches is often outdated or wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open-source can be a business strategy:&lt;/strong&gt; Even if this never makes a dollar directly, the credibility and audience it builds has measurable value for future projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  How You Can Contribute
&lt;/h2&gt;

&lt;p&gt;This is genuinely community-driven. Here's how you can help:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Star the repo:&lt;/strong&gt; &lt;a href="https://github.com/awesome-directories/awesome-directories" rel="noopener noreferrer"&gt;github.com/awesome-directories/awesome-directories&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Submit directories:&lt;/strong&gt; Know a high-quality directory? PR welcome.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report issues:&lt;/strong&gt; Found a broken link? Open an issue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve the code:&lt;/strong&gt; See something that could be better? Fork and PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share your experience:&lt;/strong&gt; Leave a review via Giscus.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Contributing Guidelines
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add directories with DR &amp;gt; 60 preferred&lt;/li&gt;
&lt;li&gt;Verify links are active before submitting&lt;/li&gt;
&lt;li&gt;Include description, categories, and pricing info&lt;/li&gt;
&lt;li&gt;Follow the existing data format in &lt;code&gt;supabase/seed-data.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start for Developers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone and install&lt;/span&gt;
git clone https://github.com/awesome-directories/awesome-directories.git
&lt;span class="nb"&gt;cd &lt;/span&gt;awesome-directories
bun &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Set up environment variables&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# Edit .env with your Supabase credentials&lt;/span&gt;

&lt;span class="c"&gt;# Run the migration in Supabase SQL Editor&lt;/span&gt;
&lt;span class="c"&gt;# Then seed the database with supabase/seed-data.json&lt;/span&gt;

&lt;span class="c"&gt;# Start dev server&lt;/span&gt;
bun run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full setup instructions in the &lt;a href="https://github.com/awesome-directories/awesome-directories#readme" rel="noopener noreferrer"&gt;README&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verified reviewer badges for directory creators&lt;/li&gt;
&lt;li&gt;More granular filtering (submission type, turnaround time)&lt;/li&gt;
&lt;li&gt;Browser extension for one-click submissions&lt;/li&gt;
&lt;li&gt;Public API for programmatic access&lt;/li&gt;
&lt;li&gt;Integration with popular launch checklists&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But honestly? The roadmap will be shaped by what the community actually needs, not what I think is cool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reality Check
&lt;/h2&gt;

&lt;p&gt;This isn't going to solve all your launch problems. It won't guarantee you'll get featured on Product Hunt. It won't make your product go viral. What it will do is save you 20+ hours of manual research and give you a fighting chance at focusing on the directories that actually matter.&lt;/p&gt;

&lt;p&gt;If that sounds useful, &lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;give it a try&lt;/a&gt;. If you find it valuable, star the repo. If you think something should work differently, open an issue or PR.&lt;/p&gt;

&lt;p&gt;Built by indie hackers, for indie hackers. No VC funding. No growth hacking. Just trying to solve a real problem with good code.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Live Site:&lt;/strong&gt; &lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;awesome-directories.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/awesome-directories/awesome-directories" rel="noopener noreferrer"&gt;github.com/awesome-directories/awesome-directories&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;License:&lt;/strong&gt; Apache-2.0&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Made with ❤️ (and probably too much coffee) by &lt;a href="https://meysam.io" rel="noopener noreferrer"&gt;Meysam&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>startup</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>No Competition? That's Usually a Red Flag for Solopreneurs (I Learned the Hard Way)</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Mon, 10 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/no-competition-thats-usually-a-red-flag-for-solopreneurs-i-learned-the-hard-way-29ih</link>
      <guid>https://dev.to/meysam81/no-competition-thats-usually-a-red-flag-for-solopreneurs-i-learned-the-hard-way-29ih</guid>
      <description>&lt;p&gt;&lt;strong&gt;I spent two months building FindForce. Perfect architecture. Clean code. Zero customers. Zero revenue.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The moment that broke me wasn't the empty dashboard. It wasn't the crickets after launch. It was staring at my payment provider page showing &lt;strong&gt;$0.00&lt;/strong&gt; in revenue—the only metric that actually mattered.&lt;/p&gt;

&lt;p&gt;All that beautiful infrastructure? All those nights and weekends? All that SRE expertise I'd spent 8 years cultivating?&lt;/p&gt;

&lt;p&gt;Meant nothing.&lt;/p&gt;

&lt;p&gt;Because nobody was paying.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "No Competition" Trap I Fell Into
&lt;/h2&gt;

&lt;p&gt;I built FindForce as a business email finder Chrome extension. Simple premise: help sales teams find and verify emails with 95% accuracy.&lt;/p&gt;

&lt;p&gt;When I started researching the market, I found giants: Hunter, Apollo, dozens of others. My first reaction? &lt;strong&gt;Fear&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;"How can I compete with them? They have teams. They have funding. They have thousands of customers."&lt;/p&gt;

&lt;p&gt;So I looked for an angle. A gap. Something &lt;em&gt;they weren't doing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I found one: flat-rate pricing. Exceptional customer support. Speed.&lt;/p&gt;

&lt;p&gt;Here's what I missed: &lt;strong&gt;Those competitors weren't obstacles. They were validation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thousands of companies were already &lt;strong&gt;paying&lt;/strong&gt; for email finding tools. The demand was proven. The problem was real. People had budget allocated.&lt;/p&gt;

&lt;p&gt;My job wasn't to invent a new category. My job was to do it better for a specific segment.&lt;/p&gt;

&lt;p&gt;But I was too busy being proud of my "unique approach" to see it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How My SRE Background Betrayed Me
&lt;/h2&gt;

&lt;p&gt;I spent 8 years as a SRE engineer. I built internal tools for dev teams. Kubernetes clusters. CI/CD pipelines. Infrastructure automation.&lt;/p&gt;

&lt;p&gt;Here's the thing about internal tools: if you build them well, people use them. There's clear communication. Defined requirements. Immediate feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I had the wrong mental model.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I thought: &lt;em&gt;"If I build it excellently, they will come."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That works when your customers are coworkers in the next room. It doesn't work when your customers are strangers on the internet who've never heard of you.&lt;/p&gt;

&lt;p&gt;I was &lt;strong&gt;two layers removed&lt;/strong&gt; from real end users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal tools serve dev teams&lt;/li&gt;
&lt;li&gt;Dev teams serve external customers&lt;/li&gt;
&lt;li&gt;I never had to think about external customers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I optimized for 10,000 users before I had 10. I built for scale before I had demand. I perfected the infrastructure before I validated the problem.&lt;/p&gt;

&lt;p&gt;Classic engineer mistake.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reddit Post That Changed Everything
&lt;/h2&gt;

&lt;p&gt;Last week, frustrated and processing the FindForce failure, I wrote a post on X:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Unpopular opinion: if nobody's doing your startup idea, that's usually a red flag, not an opportunity."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Got some traction. Felt bold. Tried it on Reddit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;160+ upvotes. 60+ comments. 48,000+ views.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most viral moment of my 30 years on this planet.&lt;/p&gt;

&lt;p&gt;Here's what I argued:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No competition often means:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No demand exists&lt;/li&gt;
&lt;li&gt;Customer acquisition costs are too high&lt;/li&gt;
&lt;li&gt;Market education burden is too heavy for small teams&lt;/li&gt;
&lt;li&gt;Regulatory barriers make it unviable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The sweet spot isn't an empty market. It's a crowded market with broken execution.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The responses were fascinating. Some agreed violently. Others called me out on exceptions: Airbnb, Uber, blue ocean strategies.&lt;/p&gt;

&lt;p&gt;They were both right.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Nuance Nobody Talks About (Solopreneur Reality)
&lt;/h2&gt;

&lt;p&gt;Here's what I should have said in that Reddit post:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For VC-backed teams with deep pockets, blue ocean strategies can work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can afford:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GTM team to educate the market&lt;/li&gt;
&lt;li&gt;Designers and engineers to iterate quickly&lt;/li&gt;
&lt;li&gt;Geographic advantages (SF networking, warm intros)&lt;/li&gt;
&lt;li&gt;Multiple attempts before running out of runway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For solopreneurs, immigrants, new parents with limited time and zero network? Different game entirely.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm all three. Iranian immigrant. New father. Building from home. No alumni network. No conference circuit. No warm intros.&lt;/p&gt;

&lt;p&gt;I have to do &lt;strong&gt;cold DM and cold email outreach&lt;/strong&gt; for every. single. customer conversation.&lt;/p&gt;

&lt;p&gt;Last week I sent &lt;strong&gt;40 cold LinkedIn messages&lt;/strong&gt; to my ICP. Got &lt;strong&gt;9 responses&lt;/strong&gt;. Booked &lt;strong&gt;1 customer discovery call&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's the reality. Not 100 interviews. Not warm intros through YC. Not a network from Stanford or MIT.&lt;/p&gt;

&lt;p&gt;Just me, a spreadsheet, and a lot of rejection.&lt;/p&gt;

&lt;h2&gt;
  
  
  When "No Competition" Might Actually Work
&lt;/h2&gt;

&lt;p&gt;I'm not saying blue ocean strategies never work for solopreneurs. But you need specific conditions:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ You MIGHT pursue a no-competition idea if:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. You have deep domain expertise&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're not flying blind&lt;/li&gt;
&lt;li&gt;You understand the problem intimately&lt;/li&gt;
&lt;li&gt;You've lived it for years&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. You've done 10+ customer interviews&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They're actively complaining about the pain&lt;/li&gt;
&lt;li&gt;They're already trying to solve it (badly)&lt;/li&gt;
&lt;li&gt;They have budget allocated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. The market shift just happened&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New regulation created the need&lt;/li&gt;
&lt;li&gt;New technology made it possible&lt;/li&gt;
&lt;li&gt;Timing is everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. You have an existing audience&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're not starting from zero&lt;/li&gt;
&lt;li&gt;You have distribution built-in&lt;/li&gt;
&lt;li&gt;Think: YouTuber launching a SaaS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. It's a niche too small for VCs, too big to ignore&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not venture-scale&lt;/li&gt;
&lt;li&gt;But sustainable for one person&lt;/li&gt;
&lt;li&gt;Examples: specific industry tools&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Don't pursue no-competition ideas if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You're learning the industry as you build&lt;/li&gt;
&lt;li&gt;You have no audience or network&lt;/li&gt;
&lt;li&gt;You need quick revenue to survive&lt;/li&gt;
&lt;li&gt;The market education would take years&lt;/li&gt;
&lt;li&gt;You're a solo technical founder with zero sales experience (hi, that was me)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'm Doing Differently Now (Build in Public)
&lt;/h2&gt;

&lt;p&gt;I'm done building in a vacuum. Here's my new playbook:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Distribution First, Product Second
&lt;/h3&gt;

&lt;p&gt;I just launched &lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;awesome-directories.com&lt;/a&gt; — a curated directory aggregator for indie hackers. &lt;strong&gt;300+ directories, open source, Apache-2 license, completely free.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;opposite&lt;/strong&gt; of FindForce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FindForce: Built product → tried to find users&lt;/li&gt;
&lt;li&gt;awesome-directories: Build for community → recognition → audience → monetize later (maybe even not!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why? Because &lt;strong&gt;people listen to you when you give first.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm not charging. No paywall. No "freemium" trap. Just pure value.&lt;/p&gt;

&lt;p&gt;If people subscribe to my newsletter or buy me a coffee, great. If not, I'm still building trust and recognition.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ruthless Customer Discovery
&lt;/h3&gt;

&lt;p&gt;Before I write a single line of code for my next SaaS, I'm doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;200 cold LinkedIn DMs&lt;/strong&gt; (sent 40 last week)&lt;/li&gt;
&lt;li&gt;Aiming for &lt;strong&gt;6+ booked customer discovery calls&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Asking about their &lt;strong&gt;last painful experience&lt;/strong&gt; with the problem&lt;/li&gt;
&lt;li&gt;Checking if they're &lt;strong&gt;already paying for a solution&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Understanding &lt;strong&gt;why&lt;/strong&gt; they're not satisfied&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm doing &lt;strong&gt;A/B testing on my outreach messages&lt;/strong&gt;. Data-driven iteration. Engineer's approach to sales.&lt;/p&gt;

&lt;p&gt;Does it hurt when 31 out of 40 people ignore me? Yes.&lt;/p&gt;

&lt;p&gt;Do I keep going? Also yes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resilience and persistence are founder prerequisites.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Value-First, Always
&lt;/h3&gt;

&lt;p&gt;Every piece of content. Every tool. Every interaction.&lt;/p&gt;

&lt;p&gt;Give, give, give. Ask little.&lt;/p&gt;

&lt;p&gt;That's how you build an audience as an unknown immigrant founder with no network.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Framework: Should You Pursue Your "No Competition" Idea?
&lt;/h2&gt;

&lt;p&gt;Here's my decision tree for solopreneurs:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Count the Competitors
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;0-1 competitors:&lt;/strong&gt; 🚩 High risk. Proceed with extreme caution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2-10 competitors:&lt;/strong&gt; ✅ Good. Demand is validated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10+ competitors:&lt;/strong&gt; ⚠️ Can you differentiate? Do you have unfair advantage?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Talk to Customers FIRST
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before writing code:&lt;/strong&gt; 10+ customer interviews minimum&lt;/li&gt;
&lt;li&gt;Ask: "Tell me about the last time you had this problem"&lt;/li&gt;
&lt;li&gt;Ask: "What are you currently using to solve it?"&lt;/li&gt;
&lt;li&gt;Ask: "What do you hate about current solutions?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red flag:&lt;/strong&gt; If they're not actively searching for solutions, problem isn't big enough&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Check Your Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time:&lt;/strong&gt; Can you afford 6-12 months of market education?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Money:&lt;/strong&gt; Can you survive without revenue during that period?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network:&lt;/strong&gt; Can you reach your ICP without paid ads?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expertise:&lt;/strong&gt; Do you understand this domain deeply?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you answered "no" to 2+ questions, choose a validated market.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Look for These Green Flags
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Competitors exist but execution is broken&lt;/li&gt;
&lt;li&gt;✅ Customers complaining publicly about current solutions&lt;/li&gt;
&lt;li&gt;✅ You have an unfair advantage (expertise, audience, speed)&lt;/li&gt;
&lt;li&gt;✅ Clear, specific niche you can dominate&lt;/li&gt;
&lt;li&gt;✅ People are actively searching for solutions (Google/Reddit evidence)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Make the Call
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blue ocean:&lt;/strong&gt; Only if you have resources, network, or deep expertise&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validated market:&lt;/strong&gt; Default choice for bootstrapped solopreneurs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crowded market:&lt;/strong&gt; Your best bet—demand is proven, execution is improvable&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Honest Truth: I'm Still Figuring This Out
&lt;/h2&gt;

&lt;p&gt;I haven't cracked the code. I'm not writing this from a yacht.&lt;/p&gt;

&lt;p&gt;I'm writing this from my home office, with a 4-month-old son in the next room, trying to build something that matters while doing cold outreach to strangers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But here's what I know for sure:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Competition validates demand.&lt;/strong&gt; I was scared of Hunter and Apollo. I should have been grateful they existed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Technical excellence means nothing without customers.&lt;/strong&gt; My clean code didn't matter. My 95% accuracy didn't matter. Nothing mattered until someone paid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distribution &amp;gt; Product.&lt;/strong&gt; Always. The best product that nobody knows about is worthless.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solopreneurs can't afford to educate markets.&lt;/strong&gt; Leave blue oceans to funded teams. You need validated demand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Give first, ask later.&lt;/strong&gt; Build trust through value. awesome-directories is my bet on this strategy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What Happens Next
&lt;/h2&gt;

&lt;p&gt;I'm continuing the 200 cold DM experiment. I'll share the results—success or failure.&lt;/p&gt;

&lt;p&gt;I'm building awesome-directories in public, documenting everything.&lt;/p&gt;

&lt;p&gt;I'm doing customer discovery the right way this time. Every conversation. Every pattern. Every insight.&lt;/p&gt;

&lt;p&gt;And I'm accepting that &lt;strong&gt;progress beats perfection&lt;/strong&gt; every single time.&lt;/p&gt;

&lt;p&gt;Will it work? I don't know.&lt;/p&gt;

&lt;p&gt;But I'm showing up. I'm pushing through. I'm learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's the only way forward.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways for Solopreneurs
&lt;/h2&gt;

&lt;p&gt;If you only remember three things from this post:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Competition = Validation&lt;/strong&gt;&lt;br&gt;
If nobody's doing it, ask "why" before assuming you found a gap. Most gaps exist because there's no demand or prohibitive barriers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Talk to Customers Before Building&lt;/strong&gt;&lt;br&gt;
10+ interviews minimum. Ask about their past behavior, not hypothetical future. "Would you use this?" is a worthless question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Distribution First&lt;/strong&gt;&lt;br&gt;
Build audience through free value (tools, content, templates). Trust compounds. Then sell to people who already know and like you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stay Connected
&lt;/h2&gt;

&lt;p&gt;I'm documenting this entire journey in public. Every lesson, every mistake, every breakthrough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick your platform:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📧 &lt;a href="https://meysam.io" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt; — Weekly deep-dives (1,500+ readers)&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://awesome-directories.com" rel="noopener noreferrer"&gt;awesome-directories&lt;/a&gt; — Free tools for indie hackers&lt;/li&gt;
&lt;li&gt;𝕏 &lt;a href="https://x.com/meysamazing" rel="noopener noreferrer"&gt;@meysamazing&lt;/a&gt; — Daily updates and real-time insights&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No fluff. No overnight success stories. Just raw documentation from the trenches.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What's your take? Am I wrong about the "no competition" trap? Have you succeeded in a blue ocean as a solopreneur? Reply and let me know—I read every message.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>learning</category>
      <category>startup</category>
    </item>
    <item>
      <title>Self-hosting Listmonk: From ConvertKit to €12/month infrastructure</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Mon, 03 Nov 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/meysam81/stop-renting-your-audience-run-your-own-newsletter-with-listmonk-25lb</link>
      <guid>https://dev.to/meysam81/stop-renting-your-audience-run-your-own-newsletter-with-listmonk-25lb</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://meysam.io/blog/own-your-newsletter-with-listmonk" rel="noopener noreferrer"&gt;meysam.io/blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When Medium hid subscriber counts in April 2025, I had already solved that problem six months earlier by moving my newsletter to self-hosted infrastructure. Here's how I run a newsletter for 1,500+ subscribers on a €12/month server.&lt;/p&gt;

&lt;p&gt;On April 2025, &lt;a href="https://meysam.io/blog/medium-hid-subscribers-own-your-audience" rel="noopener noreferrer"&gt;Medium hid everyone's subscriber counts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wasn't surprised. I was prepared.&lt;/p&gt;

&lt;p&gt;Because six months earlier, I'd already moved my newsletter off platforms I don't control. Not because I predicted Medium's move specifically, but because I'd learned the hard way: if you're building in public and your audience is on someone else's platform, you're building on rented land.&lt;/p&gt;

&lt;p&gt;When Medium announced the change, I checked my email list. 1,500+ subscribers. All mine. Real email addresses I can reach directly, regardless of what any platform decides to do tomorrow.&lt;/p&gt;

&lt;p&gt;That peace of mind? Worth the setup effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters (And Why I'm Sharing This Now)
&lt;/h2&gt;

&lt;p&gt;Look, I get it. Self-hosting sounds intimidating. Kubernetes sounds like overkill. "Just use ConvertKit or Buttondown," your brain says. "They're made for this."&lt;/p&gt;

&lt;p&gt;They are. And they're great. Until they're not.&lt;/p&gt;

&lt;p&gt;Until they change pricing.&lt;br&gt;
Until they add features you don't want but have to pay for.&lt;br&gt;
Until they get acquired and shut down.&lt;br&gt;
Until they decide your content violates their new policies.&lt;/p&gt;

&lt;p&gt;I'm not against using SaaS tools. I use plenty. But for your audience—the people who chose to hear from you—I believe you should own that relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The calculation is simple:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managed newsletter service: $30-100/month (and rising with subscribers)&lt;/li&gt;
&lt;li&gt;Self-hosted Listmonk: €12/month (flat, forever, unlimited subscribers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's not the only reason though. It's about control. It's about data. It's about not waking up one day to find the rules changed while you weren't looking.&lt;/p&gt;
&lt;h2&gt;
  
  
  What You're Actually Building
&lt;/h2&gt;

&lt;p&gt;Listmonk is an open-source newsletter and mailing list manager. Think Mailchimp or ConvertKit, but you run it on your own server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full control of your subscriber data&lt;/li&gt;
&lt;li&gt;Unlimited subscribers (you only pay for server costs)&lt;/li&gt;
&lt;li&gt;No platform risk&lt;/li&gt;
&lt;li&gt;Modern UI (actually good)&lt;/li&gt;
&lt;li&gt;API for automation&lt;/li&gt;
&lt;li&gt;Campaign analytics&lt;/li&gt;
&lt;li&gt;Subscriber segmentation&lt;/li&gt;
&lt;li&gt;Template customization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you're giving up:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Someone else handling the servers&lt;/li&gt;
&lt;li&gt;One-click setup&lt;/li&gt;
&lt;li&gt;Built-in deliverability reputation (use a good SMTP service!?)&lt;/li&gt;
&lt;li&gt;Hand-holding support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that trade-off makes sense to you, keep reading.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites: Are You Ready for This?
&lt;/h2&gt;

&lt;p&gt;This guide assumes you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know what Docker/containers are (even if you've never deployed one)&lt;/li&gt;
&lt;li&gt;Can SSH into a server without panicking&lt;/li&gt;
&lt;li&gt;Are comfortable copying and pasting commands&lt;/li&gt;
&lt;li&gt;Have ~2 hours to dedicate to setup&lt;/li&gt;
&lt;li&gt;Have €12/month for hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You don't need:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To be a DevOps expert&lt;/li&gt;
&lt;li&gt;To understand every line of YAML&lt;/li&gt;
&lt;li&gt;To have Kubernetes experience (I'll explain what matters)&lt;/li&gt;
&lt;li&gt;To know Go or VueJS (Listmonk's languages)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're thinking "I barely know Docker"—that's fine. I'll walk you through it. The whole point is making this accessible.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Architecture (Without the Jargon)
&lt;/h2&gt;

&lt;p&gt;Here's what we're building:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A small server&lt;/strong&gt; (Hetzner CCX13: 2 vCPUs, 8GB RAM, €12/month)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;K3s&lt;/strong&gt; (lightweight Kubernetes—it's easier than you think)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listmonk&lt;/strong&gt; (your newsletter app)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; (database for subscribers/campaigns)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated backups&lt;/strong&gt; (to Hetzner Object Storage)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why Kubernetes for a newsletter app? Valid question.&lt;/p&gt;

&lt;p&gt;Because once you have K3s running, adding other self-hosted tools is trivial. Want analytics? Add Plausible. Want a CRM? Add Twenty. Want uptime monitoring? Add Uptime Kuma.&lt;/p&gt;

&lt;p&gt;It's infrastructure that scales with you, not just for this one app.&lt;/p&gt;

&lt;p&gt;But we'll start simple.&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 1: Get a Server Running
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Buy the Server (5 minutes)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://console.hetzner.cloud" rel="noopener noreferrer"&gt;console.hetzner.cloud&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create an account (if you don't have one)&lt;/li&gt;
&lt;li&gt;Create a new project (call it "newsletter" or whatever)&lt;/li&gt;
&lt;li&gt;Click "Add Server"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Server specs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Choose closest to your audience (I use Nuremberg, Germany)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image:&lt;/strong&gt; Ubuntu 24.04&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; CCX13 (2 vCPU, 8GB RAM, 80GB SSD)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking:&lt;/strong&gt; Public IPv4 + IPv6&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH Key:&lt;/strong&gt; Add your public key (generate one if needed: &lt;code&gt;ssh-keygen -t ed25519&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;newsletter-1&lt;/code&gt; or similar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; €12.09/month&lt;/p&gt;

&lt;p&gt;Click "Create &amp;amp; Buy Now."&lt;/p&gt;

&lt;p&gt;Wait 60 seconds. You now have a server.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Initial Server Setup (5 minutes)
&lt;/h3&gt;

&lt;p&gt;SSH into your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@&amp;lt;your-server-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update packages and set up firewall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update system&lt;/span&gt;
apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Install required tools&lt;/span&gt;
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl wget git ufw

&lt;span class="c"&gt;# Configure firewall&lt;/span&gt;
ufw allow 22/tcp   &lt;span class="c"&gt;# SSH&lt;/span&gt;
ufw allow 80/tcp   &lt;span class="c"&gt;# HTTP&lt;/span&gt;
ufw allow 443/tcp  &lt;span class="c"&gt;# HTTPS&lt;/span&gt;
ufw allow 6443/tcp &lt;span class="c"&gt;# Kubernetes API&lt;/span&gt;
ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for basic server setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Install K3s (10 minutes)
&lt;/h2&gt;

&lt;p&gt;K3s is Kubernetes, but stripped down to essentials. Perfect for single-server setups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install K3s&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://get.k3s.io | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;INSTALL_K3S_CHANNEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;stable &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;INSTALL_K3S_EXEC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--secrets-encryption"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  sh -

&lt;span class="c"&gt;# Verify it's running&lt;/span&gt;
k3s kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see your node in "Ready" status.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set up kubectl access&lt;/strong&gt; (so you don't need to type &lt;code&gt;k3s&lt;/code&gt; before every command):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/rancher/k3s/k3s.yaml
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"export KUBECONFIG=/etc/rancher/k3s/k3s.yaml"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see your node listed, K3s is running. You now have a Kubernetes cluster on a €12 server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: Install CloudNativePG Operator (5 minutes)
&lt;/h2&gt;

&lt;p&gt;We need a PostgreSQL database for Listmonk. We'll use CloudNativePG—an operator that manages PostgreSQL for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install CloudNativePG operator&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;--server-side&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.27/releases/cnpg-1.27.1.yaml

&lt;span class="c"&gt;# Wait for it to be ready&lt;/span&gt;
kubectl rollout status deployment &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; cnpg-system cnpg-controller-manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. PostgreSQL management is handled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: Set Up External Secrets Operator (10 minutes)
&lt;/h2&gt;

&lt;p&gt;We need a way to store sensitive data (database passwords, etc.) securely. We'll use AWS Systems Manager Parameter Store (it's free for our usage).&lt;/p&gt;

&lt;h3&gt;
  
  
  Install External Secrets Operator
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add external-secrets https://charts.external-secrets.io
helm repo update

helm &lt;span class="nb"&gt;install &lt;/span&gt;external-secrets &lt;span class="se"&gt;\&lt;/span&gt;
  external-secrets/external-secrets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; external-secrets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--version&lt;/span&gt; 0.20.x &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--create-namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up AWS credentials
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create an IAM user in AWS Console with &lt;code&gt;AmazonSSMReadOnlyAccess&lt;/code&gt; permission&lt;/li&gt;
&lt;li&gt;Generate access keys&lt;/li&gt;
&lt;li&gt;Create a secret in K8s:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret generic aws-credentials &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;access-key-id&lt;span class="o"&gt;=&lt;/span&gt;YOUR_ACCESS_KEY &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret-access-key&lt;span class="o"&gt;=&lt;/span&gt;YOUR_SECRET_KEY &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; external-secrets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a ClusterSecretStore:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;external-secrets.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterSecretStore&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;aws-parameter-store&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;aws&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ParameterStore&lt;/span&gt;
      &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;eu-central-1&lt;/span&gt; &lt;span class="c1"&gt;# Frankfurt - change if needed&lt;/span&gt;
      &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;accessKeyIDSecretRef&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;aws-credentials&lt;/span&gt;
            &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;access-key-id&lt;/span&gt;
            &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;external-secrets&lt;/span&gt;
          &lt;span class="na"&gt;secretAccessKeySecretRef&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;aws-credentials&lt;/span&gt;
            &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secret-access-key&lt;/span&gt;
            &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;external-secrets&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; ClusterSecretStore.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Store your secrets in AWS Parameter Store
&lt;/h3&gt;

&lt;p&gt;Go to AWS Console → Systems Manager → Parameter Store and create these parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/listmonk/db/username&lt;/code&gt; → &lt;code&gt;listmonk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/listmonk/db/password&lt;/code&gt; → (generate strong password)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/listmonk/db/superuser/username&lt;/code&gt; → &lt;code&gt;postgres&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/listmonk/db/superuser/password&lt;/code&gt; → (generate strong password)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All as SecureString type.&lt;/p&gt;

&lt;p&gt;Alternatively, use AWS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm put-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; /listmonk/db/username &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"listmonk"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; SecureString &lt;span class="nt"&gt;--overwrite&lt;/span&gt;
aws ssm put-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; /listmonk/db/password &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"your-strong-password"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; SecureString &lt;span class="nt"&gt;--overwrite&lt;/span&gt;
aws ssm put-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; /listmonk/db/superuser/username &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; SecureString &lt;span class="nt"&gt;--overwrite&lt;/span&gt;
aws ssm put-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; /listmonk/db/superuser/password &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"your-superuser-password"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; SecureString &lt;span class="nt"&gt;--overwrite&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 5: Deploy PostgreSQL (5 minutes)
&lt;/h2&gt;

&lt;p&gt;Create a namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create namespace listmonk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the database configuration files. I'm using the exact setup I run in production—tuned for the CCX13 specs:&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="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql.cnpg.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cluster&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;pg-listmonk&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;initdb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
      &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
      &lt;span class="na"&gt;secret&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;postgres-listmonk&lt;/span&gt;
  &lt;span class="na"&gt;instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;postgresql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;effective_cache_size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;6144MB&lt;/span&gt;
      &lt;span class="na"&gt;maintenance_work_mem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;512MB&lt;/span&gt;
      &lt;span class="na"&gt;max_connections&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100"&lt;/span&gt;
      &lt;span class="na"&gt;shared_buffers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2048MB&lt;/span&gt;
      &lt;span class="na"&gt;work_mem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;16MB&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8Gi&lt;/span&gt;
    &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;4Gi&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;40Gi&lt;/span&gt;
  &lt;span class="na"&gt;superuserSecret&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;postgres-listmonk-superuser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;external-secrets.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ExternalSecret&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;postgres-listmonk-superuser&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;remoteRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/db/superuser/username&lt;/span&gt;
      &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;username&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;remoteRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/db/superuser/password&lt;/span&gt;
      &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
  &lt;span class="na"&gt;refreshInterval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24h&lt;/span&gt;
  &lt;span class="na"&gt;secretStoreRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterSecretStore&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;aws-parameter-store&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes.io/basic-auth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;external-secrets.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ExternalSecret&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;postgres-listmonk&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;remoteRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/db/username&lt;/span&gt;
      &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;username&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;remoteRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/db/password&lt;/span&gt;
      &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
  &lt;span class="na"&gt;refreshInterval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24h&lt;/span&gt;
  &lt;span class="na"&gt;secretStoreRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterSecretStore&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;aws-parameter-store&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes.io/basic-auth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; postgres/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for PostgreSQL to be ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ready &lt;span class="se"&gt;\&lt;/span&gt;
  cluster/pg-listmonk &lt;span class="nt"&gt;-n&lt;/span&gt; listmonk &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 6: Deploy Listmonk (10 minutes)
&lt;/h2&gt;

&lt;p&gt;Create the Listmonk configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[app]&lt;/span&gt;
&lt;span class="py"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.0.0.0:9000"&lt;/span&gt;
&lt;span class="py"&gt;root_url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://newsletter.yourdomain.com"&lt;/span&gt;
&lt;span class="py"&gt;site_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Your Newsletter"&lt;/span&gt;

&lt;span class="nn"&gt;[db]&lt;/span&gt;
&lt;span class="py"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pg-listmonk-rw"&lt;/span&gt;
&lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;
&lt;span class="py"&gt;database&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"listmonk"&lt;/span&gt;
&lt;span class="py"&gt;ssl_mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"disable"&lt;/span&gt;
&lt;span class="py"&gt;max_open&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="py"&gt;max_idle&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="py"&gt;max_lifetime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1h"&lt;/span&gt;
&lt;span class="py"&gt;params&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"application_name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;listmonk&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Etc/UTC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configMapRef&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;listmonk-envs&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&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;listmonk-secrets&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk/listmonk&lt;/span&gt;
          &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
              &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
            &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
            &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
            &lt;span class="na"&gt;successThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
            &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&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;listmonk&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9000&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;http&lt;/span&gt;
          &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
            &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
              &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
            &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
            &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
            &lt;span class="na"&gt;successThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
            &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
          &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/uploads&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;uploads&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/config.toml&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;listmonk-config&lt;/span&gt;
              &lt;span class="na"&gt;subPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;config.toml&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp&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;tmp&lt;/span&gt;
      &lt;span class="na"&gt;initContainers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./listmonk&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--idempotent"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--upgrade"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--yes"&lt;/span&gt;
          &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configMapRef&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;listmonk-envs&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&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;listmonk-secrets&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk/listmonk&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;migrations&lt;/span&gt;
          &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/uploads&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;uploads&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/config.toml&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;listmonk-config&lt;/span&gt;
              &lt;span class="na"&gt;subPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;config.toml&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;emptyDir&lt;/span&gt;&lt;span class="pi"&gt;:&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;tmp&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configMap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;defaultMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0400&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;listmonk-config&lt;/span&gt;
            &lt;span class="na"&gt;optional&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;listmonk-config&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;uploads&lt;/span&gt;
          &lt;span class="na"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;claimName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk-uploads&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;listmonk&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&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;http&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9000&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;external-secrets.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ExternalSecret&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;listmonk-secrets&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;remoteRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/db/username&lt;/span&gt;
      &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LISTMONK_db__user&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;remoteRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/listmonk/db/password&lt;/span&gt;
      &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LISTMONK_db__password&lt;/span&gt;
  &lt;span class="na"&gt;refreshInterval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24h&lt;/span&gt;
  &lt;span class="na"&gt;secretStoreRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterSecretStore&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;aws-parameter-store&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;listmonk-uploads&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;accessModes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ReadWriteOnce&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cert-manager.io/cluster-issuer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;letsencrypt-prod&lt;/span&gt;
    &lt;span class="na"&gt;traefik.ingress.kubernetes.io/router.middlewares&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default-redirect-https@kubernetescrd&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;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ingressClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;traefik&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;newsletter.yourdomain.com&lt;/span&gt;
      &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;service&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;listmonk&lt;/span&gt;
                &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
            &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
  &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;newsletter.yourdomain.com&lt;/span&gt;
      &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk-tls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kustomize.config.k8s.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Kustomization&lt;/span&gt;

&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deployment.yml&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;externalsecret.yml&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ingress.yml&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pvc.yml&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;service.yml&lt;/span&gt;

&lt;span class="na"&gt;configMapGenerator&lt;/span&gt;&lt;span class="pi"&gt;:&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;listmonk-config&lt;/span&gt;
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;config.toml&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;listmonk-envs&lt;/span&gt;
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;configs.env&lt;/span&gt;

&lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-k&lt;/span&gt; listmonk/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for Listmonk to be ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ready &lt;span class="se"&gt;\&lt;/span&gt;
  pod &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;listmonk &lt;span class="nt"&gt;-n&lt;/span&gt; listmonk &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 7: Expose Listmonk to the Internet (15 minutes)
&lt;/h2&gt;

&lt;p&gt;We'll use Traefik as our ingress controller (it comes with K3s).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install cert-manager for SSL:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://github.com/cert-manager/cert-manager/releases/download/v1.19.1/cert-manager.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cert-manager.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIssuer&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;letsencrypt-prod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;acme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-email@example.com&lt;/span&gt;
    &lt;span class="na"&gt;privateKeySecretRef&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;letsencrypt-prod&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://acme-v02.api.letsencrypt.org/directory&lt;/span&gt;
    &lt;span class="na"&gt;solvers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http01&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;traefik&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; ClusterIssuer.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Point your domain DNS:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an A record: &lt;code&gt;newsletter.yourdomain.com&lt;/code&gt; → &lt;code&gt;&amp;lt;your-server-ip&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait 5-10 minutes for DNS propagation and SSL certificate issuance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 8: Access and Configure Listmonk
&lt;/h2&gt;

&lt;p&gt;Navigate to &lt;code&gt;https://newsletter.yourdomain.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Login with the credentials from &lt;code&gt;LISTMONK_db__user&lt;/code&gt; &amp;amp; &lt;code&gt;LISTMONK_db__user&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username: &lt;code&gt;listmonk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Password: &lt;code&gt;your-strong-password&lt;/code&gt; (you did change this, right?)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  First-time setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Settings → General:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update site name&lt;/li&gt;
&lt;li&gt;Add your logo&lt;/li&gt;
&lt;li&gt;Set timezone&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Settings → SMTP:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a transactional email service (I recommend &lt;a href="https://maileroo.com" rel="noopener noreferrer"&gt;Maileroo&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Or use your own mail server&lt;/li&gt;
&lt;li&gt;Test the configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lists:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create your first list (e.g., "Weekly Newsletter")&lt;/li&gt;
&lt;li&gt;Set double opt-in (recommended for deliverability)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Templates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customize the default template&lt;/li&gt;
&lt;li&gt;Match your brand colors&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Part 9: Set Up Automated Backups (10 minutes)
&lt;/h2&gt;

&lt;p&gt;Your database is the most critical part. Let's back it up to Hetzner Object Storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a bucket in Hetzner:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://console.hetzner.cloud" rel="noopener noreferrer"&gt;console.hetzner.cloud&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Object Storage → Create bucket&lt;/li&gt;
&lt;li&gt;Name it (e.g., &lt;code&gt;newsletter-backups&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Create access keys&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Configure CloudNativePG backup:&lt;/strong&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="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barmancloud.cnpg.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ObjectStore&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;pg-listmonk&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;configuration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;compression&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bzip2&lt;/span&gt;
    &lt;span class="na"&gt;destinationPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3://newsletter-backups/postgres/&lt;/span&gt;
    &lt;span class="na"&gt;endpointURL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://fsn1.your-objectstorage.com&lt;/span&gt;
    &lt;span class="na"&gt;s3Credentials&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;accessKeyId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ACCESS_KEY_ID&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;hetzner-blob-storage&lt;/span&gt;
      &lt;span class="na"&gt;secretAccessKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ACCESS_SECRET_KEY&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;hetzner-blob-storage&lt;/span&gt;
    &lt;span class="na"&gt;wal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;compression&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bzip2&lt;/span&gt;
  &lt;span class="na"&gt;retentionPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;7d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the secret:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret generic hetzner-blob-storage &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-access-key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;ACCESS_SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-secret-key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; listmonk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql.cnpg.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ScheduledBackup&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;pg-listmonk&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listmonk&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cluster&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;pg-listmonk&lt;/span&gt;
  &lt;span class="na"&gt;immediate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;plugin&lt;/span&gt;
  &lt;span class="na"&gt;pluginConfiguration&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;barman-cloud.cloudnative-pg.io&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0 0 * * *&lt;/span&gt; &lt;span class="c1"&gt;# Daily at midnight&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; postgres/objectstore.yml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; postgres/scheduledbackup.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your database now backs up daily to object storage. If your server explodes, you can restore from these backups.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Just Built
&lt;/h2&gt;

&lt;p&gt;Let's recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Self-hosted newsletter platform&lt;/li&gt;
&lt;li&gt;✅ Unlimited subscribers (only limited by server resources)&lt;/li&gt;
&lt;li&gt;✅ PostgreSQL database with automated backups&lt;/li&gt;
&lt;li&gt;✅ SSL certificates (auto-renewing)&lt;/li&gt;
&lt;li&gt;✅ Modern UI for managing campaigns&lt;/li&gt;
&lt;li&gt;✅ API for automation&lt;/li&gt;
&lt;li&gt;✅ Full control of your data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Monthly cost:&lt;/strong&gt; €12 for server + ~€0-5 for backups + transactional email costs (starts at ~$0.4 per 1,000 emails with Maileroo)&lt;/p&gt;

&lt;p&gt;Compare that to ConvertKit at $33/month for 1,000 subscribers, scaling to $50/month for 3,000.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trade-Offs (Let's Be Honest)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What you gained:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full ownership of subscriber data&lt;/li&gt;
&lt;li&gt;No platform risk&lt;/li&gt;
&lt;li&gt;Predictable costs&lt;/li&gt;
&lt;li&gt;Unlimited scale potential&lt;/li&gt;
&lt;li&gt;Learning experience&lt;/li&gt;
&lt;li&gt;Infrastructure for other tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you gave up:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managed infrastructure (you're responsible for updates)&lt;/li&gt;
&lt;li&gt;Built-in deliverability reputation (you'll need to warm up your domain)&lt;/li&gt;
&lt;li&gt;One-click features (you configure everything)&lt;/li&gt;
&lt;li&gt;Hand-holding support (you're on your own or rely on community)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, it's worth it. Your mileage may vary.&lt;/p&gt;

&lt;p&gt;If you send one newsletter a week and have 500 subscribers, maybe ConvertKit makes more sense. If you're serious about building a long-term relationship with your audience and want to minimize dependencies, this setup pays for itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Doing This
&lt;/h2&gt;

&lt;p&gt;Setting up Listmonk forced me to stay sharp in my Kubernetes game. That knowledge paid off immediately when I wanted to add other self-hosted tools.&lt;/p&gt;

&lt;p&gt;Now my €12 server runs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Listmonk (newsletter)&lt;/li&gt;
&lt;li&gt;Plausible (analytics)&lt;/li&gt;
&lt;li&gt;Uptime Kuma (monitoring)&lt;/li&gt;
&lt;li&gt;A few internal tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That same infrastructure would cost $100+/month across different SaaS providers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The biggest lesson:&lt;/strong&gt; Self-hosting isn't as scary as it seems. The initial setup is the hardest part. Maintenance is mostly hands-off.&lt;/p&gt;

&lt;p&gt;I spend ~30 minutes per month on server updates. That's it.&lt;/p&gt;

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

&lt;p&gt;If you followed this guide, you now have a running newsletter platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Immediate tasks:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure your SMTP settings (Maileroo recommended)&lt;/li&gt;
&lt;li&gt;Import existing subscribers (if you have them)&lt;/li&gt;
&lt;li&gt;Create your first campaign template&lt;/li&gt;
&lt;li&gt;Send a test email&lt;/li&gt;
&lt;li&gt;Set up a subscription form on your website&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Within the first week:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Warm up your domain (start with small sends)&lt;/li&gt;
&lt;li&gt;Monitor deliverability (check spam folders)&lt;/li&gt;
&lt;li&gt;Create a consistent sending schedule 9. Add analytics tracking (optional)&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Regular server updates (&lt;code&gt;apt update &amp;amp;&amp;amp; apt upgrade&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Monitor backup status&lt;/li&gt;
&lt;li&gt;Scale server as needed (upgrade CCX type if you grow)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Real Reason I'm Sharing This
&lt;/h2&gt;

&lt;p&gt;When Medium hid subscriber counts, a bunch of indie hackers panicked in my DMs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"How do I know if anyone cares?"&lt;/li&gt;
&lt;li&gt;"Should I just quit?"&lt;/li&gt;
&lt;li&gt;"All my metrics disappeared."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your entire metric system lives on someone else's platform, you're vulnerable.&lt;/p&gt;

&lt;p&gt;I can't control what Medium does. Or X. Or LinkedIn. Or any platform.&lt;/p&gt;

&lt;p&gt;But I can control my email list. I know exactly how many people subscribed. I can email them directly, right now, without asking permission or paying per subscriber.&lt;/p&gt;

&lt;p&gt;That's not about paranoia. It's about sustainability.&lt;/p&gt;

&lt;p&gt;If you're building something long-term—a product, a community, a body of work—own the relationship with your audience. Rent the amplification platforms (social media), but own the foundation (email list).&lt;/p&gt;

&lt;p&gt;This setup is my foundation. It took a Saturday afternoon to set up. It'll run for years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You don't have to use Kubernetes.&lt;/strong&gt; You could run Listmonk with Docker Compose on the same Hetzner server for even less complexity. I chose K8s because I wanted room to grow.&lt;/p&gt;

&lt;p&gt;The point isn't the specific tech stack.&lt;/p&gt;

&lt;p&gt;The point is: stop renting your audience.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Running this setup in production? Stuck somewhere? &lt;a href="mailto:meysam@meysam.io"&gt;Email me&lt;/a&gt;. I read every message.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building in public? Subscribe to my newsletter where I share lessons like this every week: &lt;a href="https://meysam.io" rel="noopener noreferrer"&gt;meysam.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>selfhosted</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Medium Hid My Subscribers: Why You Must Own Your Audience</title>
      <dc:creator>Meysam</dc:creator>
      <pubDate>Fri, 31 Oct 2025 13:53:20 +0000</pubDate>
      <link>https://dev.to/meysam81/medium-hid-my-subscribers-why-you-must-own-your-audience-4p1h</link>
      <guid>https://dev.to/meysam81/medium-hid-my-subscribers-why-you-must-own-your-audience-4p1h</guid>
      <description>&lt;h2&gt;
  
  
  Medium Just Made Your Audience Invisible
&lt;/h2&gt;

&lt;p&gt;Let me tell you about the email I can't send.&lt;/p&gt;

&lt;p&gt;I've been writing on Medium for five years. Built up a decent following—nothing spectacular, but real people who clicked that "notify me by email" button because they wanted to hear from me specifically.&lt;/p&gt;

&lt;p&gt;Then one morning in April 2025, Medium changed the rules. Quietly. No announcement. No migration plan. Just a single line buried in their help docs:&lt;/p&gt;

&lt;p&gt;"Email addresses are no longer shared with writers when readers subscribe to receive email notifications about stories from a writer."&lt;/p&gt;

&lt;p&gt;Just like that, everyone who subscribed after April became invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moment I Realized What Happened
&lt;/h2&gt;

&lt;p&gt;I was setting up my own newsletter. Not to leave Medium—I still valued the platform—but to have my own channel. A backup. A direct line.&lt;/p&gt;

&lt;p&gt;You know, like every creator is supposed to do.&lt;/p&gt;

&lt;p&gt;I went to export my subscriber list. The one I'd spent five years building. The people who explicitly said "yes, I want to hear from you."&lt;/p&gt;

&lt;p&gt;The export worked. I got a CSV file.&lt;/p&gt;

&lt;p&gt;But it only had my old subscribers. Everyone from before April 2025. Everyone after? Gone. Hidden. Locked behind Medium's wall.&lt;/p&gt;

&lt;p&gt;Not deleted. Medium still has those emails. They still use them to send my posts. They just won't let me see them.&lt;/p&gt;

&lt;h2&gt;
  
  
  This Isn't About Privacy
&lt;/h2&gt;

&lt;p&gt;Medium's excuse? "Privacy protection."&lt;/p&gt;

&lt;p&gt;Let me be clear: I care deeply about reader privacy. I don't want to spam people. I don't want to sell email lists. I want to communicate with people who asked to hear from me.&lt;/p&gt;

&lt;p&gt;But here's the thing about Medium's "privacy" argument—it's bullshit.&lt;/p&gt;

&lt;p&gt;Substack gives writers email addresses. ConvertKit does. Ghost does. Every newsletter platform that respects both readers and writers does. And they all comply with GDPR, CAN-SPAM, and every other privacy regulation.&lt;/p&gt;

&lt;p&gt;How? By making the subscription terms clear. By requiring double opt-in. By giving readers easy unsubscribe options. By treating email as what it actually is: a communication channel with clear consent on both sides.&lt;/p&gt;

&lt;p&gt;Medium isn't protecting reader privacy. They're protecting their own control.&lt;/p&gt;

&lt;p&gt;They have your subscribers' emails. They use them. They send newsletters with advanced tools you can't access. They segment audiences. They optimize delivery.&lt;/p&gt;

&lt;p&gt;You? You get nothing. Not the emails. Not the names. Not even basic metadata about who these people are or when they subscribed.&lt;/p&gt;

&lt;p&gt;Just a subscriber count. A vanity metric. A number that goes up while your actual connection to those readers gets weaker.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern I Should Have Seen Coming
&lt;/h2&gt;

&lt;p&gt;This isn't Medium's first move like this.&lt;/p&gt;

&lt;p&gt;They killed custom domains for non-paying writers. Then they killed the Partner Program for most people. Then they made it harder to drive external traffic. Each change optimized for Medium's business model while extracting value from writers.&lt;/p&gt;

&lt;p&gt;I justified each one. "They need to make money." "It's their platform." "They're trying to create quality."&lt;/p&gt;

&lt;p&gt;But the subscriber email change is different. It's not about improving quality. It's not about sustainable business models.&lt;/p&gt;

&lt;p&gt;It's about making sure you can never truly own your audience. Even when that audience explicitly chose to follow you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Export File Reveals
&lt;/h2&gt;

&lt;p&gt;I exported my "legacy" list—the subscribers from before April who I can still access.&lt;/p&gt;

&lt;p&gt;The CSV file is bare bones: just email addresses, no names, no subscription dates, no context about what they're interested in or which posts brought them in.&lt;/p&gt;

&lt;p&gt;More importantly? It came with zero documentation about consent. Under GDPR, I'm supposed to be able to prove these people opted in. Medium gives me no way to do that.&lt;/p&gt;

&lt;p&gt;So even the emails I can export are legally questionable to use. They're compliant enough for Medium to send to, but not documented enough for me to migrate anywhere else without risk.&lt;/p&gt;

&lt;p&gt;That's not an accident. That's by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Emails I Can't Send
&lt;/h2&gt;

&lt;p&gt;Here's what I can't do now:&lt;/p&gt;

&lt;p&gt;I can't invite my subscribers to follow my journey beyond Medium. I can't tell them about projects I'm building. I can't share early access to tools I create. I can't ask them for feedback on new directions.&lt;/p&gt;

&lt;p&gt;Not because they don't want to hear from me. But because Medium won't let me reach them directly.&lt;/p&gt;

&lt;p&gt;Every new subscriber after April 2025 is stuck in Medium's ecosystem. They think they're following me. They're actually following Medium's curated version of me.&lt;/p&gt;

&lt;p&gt;And if Medium changes their algorithm tomorrow? If they decide my content doesn't fit their new priorities? If they shut down?&lt;/p&gt;

&lt;p&gt;Those subscribers disappear. Forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters (Even If You're Not on Medium)
&lt;/h2&gt;

&lt;p&gt;You might be thinking: "I don't write on Medium, so this doesn't affect me."&lt;/p&gt;

&lt;p&gt;Wrong.&lt;/p&gt;

&lt;p&gt;This is about the fundamental relationship between creators and platforms. About who owns the audience. About whether you're building a business or just renting space in someone else's.&lt;/p&gt;

&lt;p&gt;Medium is just the latest example. Twitter locked down API access. Instagram killed chronological feeds. YouTube changed monetization requirements overnight. TikTok bans accounts without explanation.&lt;/p&gt;

&lt;p&gt;Every platform follows the same playbook:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make it easy to grow an audience&lt;/li&gt;
&lt;li&gt;Wait until you're invested&lt;/li&gt;
&lt;li&gt;Change the rules to extract more value&lt;/li&gt;
&lt;li&gt;Justify it with vague appeals to "community" or "safety"&lt;/li&gt;
&lt;li&gt;Watch creators scramble to adapt&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The email change is Medium admitting what we should have known all along: you were never building your audience. You were building theirs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Doing Now
&lt;/h2&gt;

&lt;p&gt;I'm not leaving Medium immediately. The distribution is still valuable. The writing interface is still good. But I'm treating it differently now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every new post starts with a clear CTA:&lt;/strong&gt; "I write a weekly newsletter at &lt;a href="https://meysam.io" rel="noopener noreferrer"&gt;meysam.io&lt;/a&gt;. This is where I share lessons Medium won't let me talk about. Where I build in public. Where I can actually reach you if Medium changes the rules again."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'm aggressive about moving people to my own platform:&lt;/strong&gt; Not spammy. Not manipulative. Just honest: "If you want the unfiltered version of this journey, here's where to find it."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'm treating Medium like what it is:&lt;/strong&gt; A discovery platform, not a home. A place to meet readers, not keep them.&lt;/p&gt;

&lt;p&gt;And I'm exporting everything I can while I still can. Because if Medium changed subscriber policies this quietly, what's next? When do they lock down even the legacy lists?&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Actually Did It (The Technical Part)
&lt;/h2&gt;

&lt;p&gt;Setting up my own newsletter wasn't as hard as I thought it'd be.&lt;/p&gt;

&lt;p&gt;I'm running Listmonk—an open-source newsletter platform—on a €12/month server. It took one Saturday afternoon to set up. Now I have unlimited subscribers, full control of my data, and zero platform risk.&lt;/p&gt;

&lt;p&gt;No monthly fees that scale with my list size. No terms of service that can change overnight. No company that can decide my subscribers are actually their subscribers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The whole setup:&lt;/strong&gt; PostgreSQL database, automated backups, SSL certificates, modern UI for managing campaigns. All self-hosted. All mine.&lt;/p&gt;

&lt;p&gt;I'm writing a complete guide on how to replicate this setup—every command, every configuration file, every decision point. Not because self-hosting is the only answer, but because you should know it's possible. Because "too technical" shouldn't be the reason you stay dependent on platforms that don't have your interests at heart.&lt;/p&gt;

&lt;p&gt;If you want to own your audience infrastructure the way I do, that guide drops next week.&lt;/p&gt;

&lt;p&gt;It's detailed. It's tested in production. And it assumes you're smart enough to follow along even if you've never touched Kubernetes before.&lt;/p&gt;

&lt;h2&gt;
  
  
  For the Subscribers I Can't Reach
&lt;/h2&gt;

&lt;p&gt;If you subscribed to my Medium updates after April 2025, I want you to know something:&lt;/p&gt;

&lt;p&gt;You chose to follow my work. Not Medium's work. Mine.&lt;/p&gt;

&lt;p&gt;But I can't reach you directly anymore. I can't tell you about projects I'm building. I can't share early access to tools. I can't ask for your feedback on new ideas.&lt;/p&gt;

&lt;p&gt;Not because I don't want to. But because Medium won't let me.&lt;/p&gt;

&lt;p&gt;If you're reading this on Medium right now, and you care about staying connected beyond this platform, here's what you can do: &lt;a href="https://meysam.io" rel="noopener noreferrer"&gt;visit my website&lt;/a&gt; and sign up there. It takes 30 seconds. And it means I can actually reach you—on my terms, on your terms—not Medium's.&lt;/p&gt;

&lt;p&gt;No pressure. No manipulation. Just an honest ask: if you want a direct connection, here's how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lesson I'm Learning Too Late
&lt;/h2&gt;

&lt;p&gt;Five years ago, when I started on Medium, someone told me: "Own your audience. Build your email list. Never rely on any single platform."&lt;/p&gt;

&lt;p&gt;I nodded. I agreed. Then I ignored it because Medium was working and building my own platform felt like too much work.&lt;/p&gt;

&lt;p&gt;Now I understand what they meant.&lt;/p&gt;

&lt;p&gt;It's not that Medium is evil. It's that they have different incentives than you do. They optimize for engagement and revenue. You optimize for connection and sustainability.&lt;/p&gt;

&lt;p&gt;Those goals aligned for a while. Now they don't.&lt;/p&gt;

&lt;p&gt;The subscriber email change isn't a bug. It's a feature. It's Medium telling you exactly where you stand: you're valuable to them as content supply, not as an independent creator.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Should Do
&lt;/h2&gt;

&lt;p&gt;If you're writing on Medium—or any platform you don't own—here's what I wish I'd done earlier:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start your own newsletter today.&lt;/strong&gt; Not next month. Not when you "have time." Today. Substack, Ghost, ConvertKit, hell even just a simple email list through your website. Doesn't matter. Just start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Put a clear CTA in every post.&lt;/strong&gt; Not buried at the end. Not subtle. Obvious. "I send a weekly email about [thing]. Sign up at [place]."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be honest about why.&lt;/strong&gt; Don't pretend you're doing readers a favor. Tell them the truth: "I'm building on platforms I don't control. If you want to stay connected regardless of what those platforms decide, here's where to find me."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Export everything you can, now.&lt;/strong&gt; Whatever access you have to subscriber data, export it today. Back it up. Document it. Because if platforms are tightening control, assume it's going to get worse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treat platforms like what they are.&lt;/strong&gt; Discovery channels. Traffic sources. Not homes. You're renting, not owning.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Part That Hurts
&lt;/h2&gt;

&lt;p&gt;I'm not mad at Medium. I'm mad at myself.&lt;/p&gt;

&lt;p&gt;I saw the signs. I heard the warnings. I knew better.&lt;/p&gt;

&lt;p&gt;But I got comfortable. I liked watching that subscriber count go up. I liked the validation of "X people want to hear from you."&lt;/p&gt;

&lt;p&gt;I just didn't realize that "X people" wasn't mine. It was Medium's. And when they decided to stop sharing, I had no recourse.&lt;/p&gt;

&lt;p&gt;Zero customers taught me that distribution matters more than product.&lt;/p&gt;

&lt;p&gt;Hidden subscribers taught me that audience access matters more than audience size.&lt;/p&gt;

&lt;p&gt;Both lessons cost me months of work. Both are obvious in hindsight.&lt;/p&gt;

&lt;p&gt;I'm sharing this now because someone reading this is making the same mistake I made. You're building on a platform. You're comfortable. It's working.&lt;/p&gt;

&lt;p&gt;Until it isn't.&lt;/p&gt;

&lt;p&gt;And by the time you realize you should have owned your audience, it's too late to export the emails they hid.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you subscribed to my Medium updates after April 2025 and you're reading this, I genuinely wish I could reach you directly. If you want to stay connected beyond Medium's decisions, visit &lt;a href="https://meysam.io" rel="noopener noreferrer"&gt;meysam.io&lt;/a&gt;. That's the only place I can actually promise you'll hear from me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Everyone else: learn from my mistake. Own your audience. Today.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>medium</category>
      <category>platforms</category>
      <category>contentcreation</category>
    </item>
  </channel>
</rss>
