<?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: Romashik</title>
    <description>The latest articles on DEV Community by Romashik (@renigat7-cpu).</description>
    <link>https://dev.to/renigat7-cpu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4131455%2Fb5a62791-1383-4270-b4c5-3b93ab87bf4d.png</url>
      <title>DEV Community: Romashik</title>
      <link>https://dev.to/renigat7-cpu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/renigat7-cpu"/>
    <language>en</language>
    <item>
      <title>B2B Lead Research Without Getting Your Domain Blacklisted</title>
      <dc:creator>Romashik</dc:creator>
      <pubDate>Sat, 03 Oct 2026 16:05:57 +0000</pubDate>
      <link>https://dev.to/renigat7-cpu/b2b-lead-research-without-getting-your-domain-blacklisted-5hi2</link>
      <guid>https://dev.to/renigat7-cpu/b2b-lead-research-without-getting-your-domain-blacklisted-5hi2</guid>
      <description>&lt;p&gt;A good lead list is not "1,000 emails". It is a small set of people who match your ideal&lt;br&gt;
customer, whose address is real, and whose first line you did not copy-paste. Bad lists do&lt;br&gt;
not just waste money — they burn your sending domain. Here is the process I use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define the ICP before you touch a tool
&lt;/h2&gt;

&lt;p&gt;Write three sentences: who exactly (role + company size + industry), what pain, what trigger&lt;br&gt;
means they are in-market &lt;em&gt;now&lt;/em&gt; (funding, hiring, product launch, tech change). If you cannot&lt;br&gt;
name the trigger, you are about to buy a random list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sourcing that does not poison the data
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prefer primary sources.&lt;/strong&gt; Company websites, careers pages, GitHub orgs, conference
speaker lists. These are more accurate than scraped aggregators and less likely to contain
traps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the domain before the mailbox.&lt;/strong&gt; Does the site resolve, load, and match the company
name? Typo-domains and parked domains are how bounce rates explode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One source per fact.&lt;/strong&gt; Record where each field came from. If you cannot cite it, delete
it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Verify before you write
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syntax&lt;/strong&gt; basics (&lt;code&gt;name@domain.tld&lt;/code&gt;) are cheap — reject the obvious.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain/MX check.&lt;/strong&gt; No MX record means no mailbox, no exceptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role addresses are not leads.&lt;/strong&gt; &lt;code&gt;info@&lt;/code&gt;, &lt;code&gt;sales@&lt;/code&gt;, &lt;code&gt;noreply@&lt;/code&gt; go in a separate bucket,
never your main sequence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catch-all domains are not "verified".&lt;/strong&gt; Mark them as risky. A "verified" badge you cannot
defend is worse than an honest "unverified".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not trust a single checker. Run two and keep only the intersection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deliverability hygiene
&lt;/h2&gt;

&lt;p&gt;This is where most freelancers cost their clients real money:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Warm the domain. A brand-new domain sending 500 cold emails on day one is a one-way trip
to spam.&lt;/li&gt;
&lt;li&gt;Use a custom subdomain for outreach so your main domain is insulated.&lt;/li&gt;
&lt;li&gt;Keep bounce rate under 2%. Above it, pause and clean.&lt;/li&gt;
&lt;li&gt;Include a real postal address and one-click unsubscribe — required in most jurisdictions.&lt;/li&gt;
&lt;li&gt;Never buy a list and blast it. That is the definition of spam.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The opener that works
&lt;/h2&gt;

&lt;p&gt;Personalization is not "Hi {FirstName}". It is one specific, verifiable line that proves you&lt;br&gt;
looked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Saw you're hiring two SREs and just moved to Kubernetes — most teams hit the same&lt;br&gt;
observability gap at that stage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence comes from the trigger you defined earlier. If you cannot write one for a lead,&lt;br&gt;
the lead is not qualified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compliance is not optional
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EU/UK&lt;/strong&gt;: GDPR/UK-GDPR — you need a lawful basis (usually legitimate interest for B2B)
and a clear opt-out. Document it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;US&lt;/strong&gt;: CAN-SPAM — real address, honest subject, working unsubscribe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canada&lt;/strong&gt;: CASL — stricter; consent-based for many cases. Check before sending.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not legal advice; it is why a clean, consent-aware list beats a giant one.&lt;/p&gt;

&lt;h2&gt;
  
  
  A workable workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Write the ICP + trigger.&lt;/li&gt;
&lt;li&gt;Pull 200–300 candidates from primary sources.&lt;/li&gt;
&lt;li&gt;Check domain + MX; drop failures.&lt;/li&gt;
&lt;li&gt;Verify emails with two checkers; keep the intersection.&lt;/li&gt;
&lt;li&gt;Deduplicate by person and by company.&lt;/li&gt;
&lt;li&gt;Write one personalized opener per lead — or drop the lead.&lt;/li&gt;
&lt;li&gt;Send in small batches; watch bounce and reply; pause if bounce &amp;gt; 2%.&lt;/li&gt;
&lt;li&gt;Log source and result for every field so the next list is better.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A verified list of 50 with real openers will outperform 2,000 scraped addresses every single&lt;br&gt;
time — and it will not cost you your domain.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I build verified B2B lead lists with per-lead openers and deliverability checks. Details in&lt;br&gt;
my portfolio.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sales</category>
      <category>b2b</category>
      <category>deliverability</category>
      <category>email</category>
    </item>
    <item>
      <title>Concurrent AI Agents: What Actually Works (Notes From Building One)</title>
      <dc:creator>Romashik</dc:creator>
      <pubDate>Sat, 03 Oct 2026 16:05:20 +0000</pubDate>
      <link>https://dev.to/renigat7-cpu/concurrent-ai-agents-what-actually-works-notes-from-building-one-3e77</link>
      <guid>https://dev.to/renigat7-cpu/concurrent-ai-agents-what-actually-works-notes-from-building-one-3e77</guid>
      <description>&lt;p&gt;I have spent the last few months building multi-agent systems that run unattended — watching&lt;br&gt;
inboxes, scraping pages, drafting content, moving money only when a human approves. Here is&lt;br&gt;
the honest list of what made them useful and what was theater.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrency is not the hard part
&lt;/h2&gt;

&lt;p&gt;People love the demo where five agents "think" in parallel. In practice, five agents reading&lt;br&gt;
the same state and racing to write it is just a distributed-systems problem wearing a&lt;br&gt;
costume. The useful concurrency is boring: independent tasks with disjoint resources.&lt;/p&gt;

&lt;p&gt;The pattern that works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One writer per resource.&lt;/strong&gt; A single process owns the database/ledger. Others send it
requests. This eliminates 90% of the bugs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idempotent steps.&lt;/strong&gt; Every step can run twice without harm. Store the step id; skip if
seen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A queue with a dead-letter lane.&lt;/strong&gt; Failed tasks go somewhere you will actually inspect,
not into a silent retry loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you cannot describe a task as "read-only" or "appends one idempotent record", it does not&lt;br&gt;
belong in parallel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roles beat prompts
&lt;/h2&gt;

&lt;p&gt;The biggest quality jump came not from a better model but from splitting one big prompt into&lt;br&gt;
narrow roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Researcher&lt;/strong&gt; — gathers sources, produces a facts file. Never writes prose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writer&lt;/strong&gt; — drafts from the facts file. Not allowed to invent facts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adversary&lt;/strong&gt; — tries to falsify the draft; flags unsupported claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editor&lt;/strong&gt; — merges, enforces format.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The adversary role is the one people skip and the one that saves you. A model reviewing its&lt;br&gt;
own work is a rubber stamp. A model told &lt;em&gt;"find the weakest claim and attack it"&lt;/em&gt; is&lt;br&gt;
genuinely useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give agents a memory that is not the context window
&lt;/h2&gt;

&lt;p&gt;Context windows are for the current task. Long-term memory belongs in files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;facts.md&lt;/code&gt; — verified claims with sources.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;decisions.md&lt;/code&gt; — append-only log of choices and why.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lessons.md&lt;/code&gt; — mistakes and the rule that prevents them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before a new task, the agent reads &lt;code&gt;lessons.md&lt;/code&gt;. After a failure, it appends one line. This&lt;br&gt;
single habit did more than any model upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guardrails that are not optional
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confirm before external side effects.&lt;/strong&gt; Sending an email, posting, paying — all gated on
an explicit human "yes". The agent prepares, the human approves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spend ceilings.&lt;/strong&gt; A hard counter that refuses the next paid call once the budget is hit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret redaction at every boundary.&lt;/strong&gt; Logs, error messages, and model inputs. Assume the
model will echo whatever you paste.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read-only by default.&lt;/strong&gt; Any mutation is a named command, never an ambient capability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What was theater
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents debating each other in a loop.&lt;/strong&gt; Fun to watch, expensive, and rarely better than
one well-scoped pass plus an adversarial review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom orchestration frameworks before you need them.&lt;/strong&gt; A queue table and a few functions
beat a graph engine until you have dozens of flows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Letting agents browse freely.&lt;/strong&gt; An agent with an open browser and no allowlist will
wander into paywalls and captchas. Scope the domains.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;The systems that survive contact with reality are small, heavily constrained, and boring.&lt;br&gt;
They do one narrow thing, log everything, ask before touching the outside world, and get a&lt;br&gt;
little smarter from &lt;code&gt;lessons.md&lt;/code&gt;. The clever parallel-thinking demos are the ones that break&lt;br&gt;
first.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I build and write about practical agent systems. If you want an autonomous pipeline that&lt;br&gt;
does not need babysitting, get in touch.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>architecture</category>
      <category>python</category>
    </item>
    <item>
      <title>A Practical GEO Checklist: How to Get Your B2B Blog Cited by AI Search</title>
      <dc:creator>Romashik</dc:creator>
      <pubDate>Sat, 03 Oct 2026 16:04:22 +0000</pubDate>
      <link>https://dev.to/renigat7-cpu/a-practical-geo-checklist-how-to-get-your-b2b-blog-cited-by-ai-search-1ehn</link>
      <guid>https://dev.to/renigat7-cpu/a-practical-geo-checklist-how-to-get-your-b2b-blog-cited-by-ai-search-1ehn</guid>
      <description>&lt;p&gt;Everyone is chasing AI search traffic now, and most of the advice is either obvious&lt;br&gt;
("write good content") or fake ("trick the models"). Here is what actually moved the needle&lt;br&gt;
for the technical blogs I work on — a checklist you can run today.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, understand what the AI is doing
&lt;/h2&gt;

&lt;p&gt;When an answer engine cites you, it usually summarizes a paragraph or two and links the&lt;br&gt;
source. That means your job is not rankings and not clicks. Your job is to be the &lt;em&gt;most&lt;br&gt;
quotable, self-contained, verifiable source&lt;/em&gt; on a narrow question.&lt;/p&gt;

&lt;p&gt;Three properties decide whether you get cited:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Extractability&lt;/strong&gt; — a model can lift a clean, standalone answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verifiability&lt;/strong&gt; — the claim is backed by something it can point at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt; — multiple pages on the web say similar things about you/your topic.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The checklist
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] One &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; that states the question almost verbatim.&lt;/li&gt;
&lt;li&gt;[ ] A direct answer in the first 60 words. No "in this article we will explore".&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; per sub-question, phrased as the user would ask it.&lt;/li&gt;
&lt;li&gt;[ ] Short paragraphs (2–4 lines). Tables for comparisons.&lt;/li&gt;
&lt;li&gt;[ ] A summary/FAQ at the end that restates answers without new claims.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verifiability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Cite primary sources, not other blog posts.&lt;/li&gt;
&lt;li&gt;[ ] Date everything: publish date, "last updated", and dates on serialized data.&lt;/li&gt;
&lt;li&gt;[ ] Show methodology in one line under every number.&lt;/li&gt;
&lt;li&gt;[ ] Link to your own related pages with descriptive anchors (internal linking still
  matters — it helps the crawler understand your entity).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Entities and schema
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Name your product/company consistently. Pick one spelling and never deviate.&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;Article&lt;/code&gt;/&lt;code&gt;FAQPage&lt;/code&gt; schema with real values, not placeholders.&lt;/li&gt;
&lt;li&gt;[ ] Include author info with credentials (&lt;code&gt;Person&lt;/code&gt; schema). Anonymous posts get cited less.&lt;/li&gt;
&lt;li&gt;[ ] Keep a stable "about" and "contact" page; AI systems use them for trust signals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Formatting for extraction
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Prefer bulleted steps and numbered sequences over long prose.&lt;/li&gt;
&lt;li&gt;[ ] Give each section a one-sentence takeaway in bold.&lt;/li&gt;
&lt;li&gt;[ ] Avoid hedging language ("might", "could possibly") when you actually know the answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What to stop doing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keyword stuffing.&lt;/strong&gt; It does nothing for citation and hurts the humans who do read.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thin roundups.&lt;/strong&gt; "10 tools you should know" with two sentences each rarely gets cited;
a single deep teardown of one tool does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chasing every model.&lt;/strong&gt; Optimize for extractability and verifiability; that transfers
across ChatGPT, Perplexity, Gemini, and whatever launches next.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Measuring it
&lt;/h2&gt;

&lt;p&gt;You cannot get a clean "AI traffic" number yet, so measure proxies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Branded search volume&lt;/strong&gt; — if AI answers mention you, people search you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct/referral traffic&lt;/strong&gt; to the specific pages you optimized.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server logs&lt;/strong&gt; for known AI crawler user-agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual spot-checks&lt;/strong&gt; — ask the models your target questions monthly and record whether
you appear. A spreadsheet is enough.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A 30-minute workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Pick one question your buyer actually types (use search suggestions, support tickets).&lt;/li&gt;
&lt;li&gt;Write the direct answer first, in one paragraph.&lt;/li&gt;
&lt;li&gt;Add 3–5 sub-questions as headings; answer each in under 120 words.&lt;/li&gt;
&lt;li&gt;Add one table and one primary-source citation.&lt;/li&gt;
&lt;li&gt;Add FAQ schema, publish date, and author byline.&lt;/li&gt;
&lt;li&gt;Repeat for the next question and interlink the two.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That cadence beats a 5,000-word pillar post you never update.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write researched technical articles optimized for AI search, with sources, schema, and a&lt;br&gt;
content plan. Samples and details in my portfolio.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>contentmarketing</category>
      <category>ai</category>
      <category>writing</category>
    </item>
    <item>
      <title>How I Built a Zero-Cost Opportunity Radar with Python and Playwright</title>
      <dc:creator>Romashik</dc:creator>
      <pubDate>Sat, 03 Oct 2026 16:04:21 +0000</pubDate>
      <link>https://dev.to/renigat7-cpu/how-i-built-a-zero-cost-opportunity-radar-with-python-and-playwright-38j9</link>
      <guid>https://dev.to/renigat7-cpu/how-i-built-a-zero-cost-opportunity-radar-with-python-and-playwright-38j9</guid>
      <description>&lt;p&gt;Most "opportunity radars" are dashboards that show you the same noisy feed everyone else&lt;br&gt;
sees. I wanted the opposite: a small, boring pipeline that watches a handful of sources I&lt;br&gt;
actually care about and only pings me when something matches. No SaaS bill, no paid APIs.&lt;/p&gt;

&lt;p&gt;Here is the architecture, the parts that broke, and the rules I now follow.&lt;/p&gt;
&lt;h2&gt;
  
  
  The shape of it
&lt;/h2&gt;

&lt;p&gt;Three stages, each replaceable:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Collect&lt;/strong&gt; — a set of independent watchers (RSS, a couple of public pages, an IMAP
mailbox, a Telegram channel). Each watcher writes normalized items to one queue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter&lt;/strong&gt; — rules that match on &lt;em&gt;sender address&lt;/em&gt; (not display name) and on keywords.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notify&lt;/strong&gt; — one message, deduplicated by a stable id, rate-limited.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing is a few hundred lines of Python plus Playwright for the JS-heavy pages.&lt;/p&gt;
&lt;h2&gt;
  
  
  Stage 1: collect, but keep watchers dumb
&lt;/h2&gt;

&lt;p&gt;Each watcher does one thing and exits. If a watcher crashes, it must not take the pipeline&lt;br&gt;
down. I run them from cron/&lt;code&gt;systemd&lt;/code&gt; timers, not from a long-lived process that slowly leaks&lt;br&gt;
memory. A cron job that fails is obvious; a daemon that wedges at 3am is not.&lt;/p&gt;

&lt;p&gt;For email I use IMAP with a Gmail app password and &lt;code&gt;readonly=True&lt;/code&gt; on &lt;code&gt;select&lt;/code&gt;. Reading&lt;br&gt;
should never be able to mutate the mailbox. For every message I compute a stable dedupe key&lt;br&gt;
(Message-ID if present, otherwise a hash of &lt;code&gt;from + subject + date&lt;/code&gt;) and skip anything seen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dedupe_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Message-ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;From&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Subject&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Stage 2: filter on the address, not the name
&lt;/h2&gt;

&lt;p&gt;This is the mistake I see in almost every filter I review. A rule like&lt;br&gt;
&lt;code&gt;if "Acme" in from_header&lt;/code&gt; matches &lt;code&gt;"Acme Inc" &amp;lt;phish@evil.example&amp;gt;&lt;/code&gt;. Match the &lt;em&gt;address&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;email.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;parseaddr&lt;/span&gt;
&lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseaddr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;From&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then match domains/substrings against that. It is a one-line change that closes an entire&lt;br&gt;
class of false positives and phishing lookalikes.&lt;/p&gt;

&lt;p&gt;Two more rules that pay for themselves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skip marketing.&lt;/strong&gt; If the subject contains &lt;code&gt;newsletter&lt;/code&gt;, &lt;code&gt;unsubscribe&lt;/code&gt;, &lt;code&gt;promo&lt;/code&gt;, &lt;code&gt;sale&lt;/code&gt;,
it is not an opportunity. Drop it before it reaches the notifier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cap the noise.&lt;/strong&gt; Never send more than N notifications per run. If the cap is hit, say so
in the message. Silent truncation is worse than no notification.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Stage 3: notify once, and log
&lt;/h2&gt;

&lt;p&gt;Every outbound notification gets an append-only on-disk log with a &lt;em&gt;hash&lt;/em&gt; of the body, not&lt;br&gt;
the body itself. If a credential ever ends up in an error path, the log must not become the&lt;br&gt;
leak. Redact secrets in error strings before printing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;redact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;secrets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;redacted&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What broke
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser pages that render in JS.&lt;/strong&gt; &lt;code&gt;requests&lt;/code&gt; returns an empty shell. Playwright with a
persistent context fixed it, but you must target the &lt;em&gt;active&lt;/em&gt; tab, not a new one, or you
fight your own automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Probe noise in logs.&lt;/strong&gt; A health check hammering an internal endpoint generated ~97% of
the rows in my call log and drowned the signal. I added a prune command that only runs
when explicitly invoked. Read-write by accident is how you lose data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full test suites hanging.&lt;/strong&gt; A suite that pulls in network tests will hang in CI. Run the
targeted tests for the modules you touched; keep the slow integration ones behind a flag.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The rules I keep
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Collectors are interchangeable and disposable.&lt;/li&gt;
&lt;li&gt;Filter on addresses; treat display names as hostile.&lt;/li&gt;
&lt;li&gt;Deduplicate by a stable id, always.&lt;/li&gt;
&lt;li&gt;Redact secrets at the boundary; never log raw bodies.&lt;/li&gt;
&lt;li&gt;One notification, with its own audit line.&lt;/li&gt;
&lt;li&gt;Read-only by default; mutation requires an explicit command.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Total cost: one machine you already have, plus free-tier model calls. The value is not the&lt;br&gt;
code — it is the discipline of saying no to 99% of the input so the 1% is visible.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I build small automation pipelines and write about them. If your team needs a watcher that&lt;br&gt;
actually respects your attention, I can help — portfolio below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>playwright</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What 2,857 Projects Taught Me About the Road to Colosseum</title>
      <dc:creator>Romashik</dc:creator>
      <pubDate>Fri, 18 Sep 2026 12:29:32 +0000</pubDate>
      <link>https://dev.to/renigat7-cpu/what-2857-projects-taught-me-about-the-road-to-colosseum-3g7l</link>
      <guid>https://dev.to/renigat7-cpu/what-2857-projects-taught-me-about-the-road-to-colosseum-3g7l</guid>
      <description>&lt;p&gt;&lt;em&gt;An honest, data-backed reflection for anyone who lost sleep over a hackathon — and wants the next one to count.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I spent the last cycle doing something unusual: instead of building &lt;em&gt;inside&lt;/em&gt; the Colosseum frenzy, I built a machine that watches it. An autonomous assistant that scans bounties, reads ecosystems, scores opportunities, and lets me focus on what a human should actually do — judge, decide, ship. This reflection is what that machine surfaced about the Road to Colosseum. No hype, just numbers and the lessons they force.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 1. The bar is not "build something." The bar is 0.7%.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Colosseum's Frontier Hackathon (April–May 2026) was the largest crypto startup competition to date: 2,857 submitted projects, more than 10,000 builders, 150+ countries. Out of that field, 26 winners were named — and only 21 startups made it into Accelerator Cohort 5. That's an admission rate of 0.7%.&lt;/p&gt;

&lt;p&gt;A 0.7% funnel changes how you work. "Build something cool" is not a strategy; that's how you become one of the silent 2,831. The only honest framing: you are entering a startup competition with pre-seed money at the end, and the odds are startup odds. Which means team formation, problem selection, and ruthless scope discipline matter more than how many features you can crudely ship in a weekend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 2. Winners look like a thesis, not a demo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Look at what judges actually picked. Grand Champion: CrowdBrain — a vertically integrated robotics DePIN network for training and routing operators to physical robots. Not a dashboard, not a "bridge but better." A thesis: hardware × crypto × labor market, with an opinion about who gets paid. The rest of the cohort spans DePIN, DeFi, gaming, consumer finance, and RWA infrastructure.&lt;/p&gt;

&lt;p&gt;A pattern: winning entries tend to sit inside a &lt;em&gt;category&lt;/em&gt; (DePIN, payments, infra) rather than a "dApp of the week." Sponsors in Frontier — Phantom, Altitude, Arcium, World, Metaplex, Raydium, Reflect, Coinbase — are infrastructure and distribution, and they reward projects that slot into real rails. When you pick a problem for Road to Colosseum, ask: &lt;em&gt;which existing rail does this make money for?&lt;/em&gt; If none — the judges see it too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 3. Judges optimize for adoption-fitness, not polish.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From Colosseum's own guidance (their "How to win a hackathon" post), the program is designed to take teams from devnet to mainnet in 8 weeks, ending in a private demo day with VCs. That means every submission is evaluated as a potential &lt;em&gt;company&lt;/em&gt;: distribution, go-to-market, defensibility. Polished UI without a user path is a liability, not an asset.&lt;/p&gt;

&lt;p&gt;Do the math you can defend in front of an investor in 60 seconds: who is the first paying user, and why you specifically? If you can't say it out loud, the judges can't either.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 4. The fastest builder in 2026 is a two-person team: you and your agent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few honest notes from someone who shipped with heavy AI assistance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The assistant compressed discovery: instead of reading 200 bounties and 50 ecosystem posts, I get a ranked digest — what's open, what pays, who sponsors, what's due. That's one or two saved days per cycle, every cycle.&lt;/li&gt;
&lt;li&gt;It made failure cheap: drafts, scoping docs, competitor scans in minutes. Cheap iterations are a genuine competitive advantage in a 5-week hackathon.&lt;/li&gt;
&lt;li&gt;It did NOT make decisions. Every important call — which problem, which team, when to stop polishing — still happened in a human head. Anyone telling you the agent decides is selling you something.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lesson 5. The hidden tracks are the smart tracks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Frontier quietly included two special prizes: the best university team and the most complete public goods project — each $10,000. In a 2,857-project field, the number of teams competing specifically for those prizes is an order of magnitude smaller. Same prize pool, better odds. For Road to Colosseum, same logic applies: find the category with fewer whales and more substance. Public goods, education, regional ecosystems (Vietnam building culture is real — Superteam Vietnam knows) are where well-executed projects win prizes disproportionate to their effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 6. The 0.7% crowd out-builds, not out-ideas.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The difference between a strong submission and a winner is rarely the idea — it's the &lt;em&gt;evidence of progress&lt;/em&gt;: a working product, a live testnet, a clear architecture, commits you can point to. Colosseum's CTO and judging ecosystem leaders have seen every pattern; they can smell a slideware submission in the first pass. Show the thing. The pitch deck is dessert.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;The Road to Colosseum checklist (what my assistant now runs daily):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scan open bounties/grants weekly (Superteam earn, Eternal sprint, hackathon channels). Filter by fit, not by prize size.&lt;/li&gt;
&lt;li&gt;Pick ONE category thesis; write it in one sentence; kill anything that doesn't serve it.&lt;/li&gt;
&lt;li&gt;Test distribution before code: who is the audience, where do they gather, what will make them click.&lt;/li&gt;
&lt;li&gt;Ship a vertical slice in week 1 — not a dashboard, a &lt;em&gt;user journey&lt;/em&gt; on one screen.&lt;/li&gt;
&lt;li&gt;Public progress: weekly X/dev.to post, commit log public. Judges read; communities reward.&lt;/li&gt;
&lt;li&gt;Target a hidden track (university, public goods, regional) unless your thesis is clearly top-0.7%.&lt;/li&gt;
&lt;li&gt;Last 48 hours: cut scope, not sleep. A working 80% beats a broken 120%.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;On the level:&lt;/strong&gt; Frontier took 2,857 projects and funded 26. The next one — the Road to Colosseum cycle — will likely be bigger, because 2026's builder base learned they can ship in weeks, not months. That's the honest deal: more competition, more eyes, and for a well-scoped, honestly-built project, more distribution than any solo article can buy.&lt;/p&gt;

&lt;p&gt;I built a machine to watch this race so I can spend my time running it. The next hackathon is not about who codes the most — it's about who decides the most. Decide early, decide with data, and show the thing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;— A builder on the road to Colosseum&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
