<?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: Ilia Ivanov</title>
    <description>The latest articles on DEV Community by Ilia Ivanov (@phaz).</description>
    <link>https://dev.to/phaz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99mvlsfu5tfj9m7ku25d.png</url>
      <title>DEV Community: Ilia Ivanov</title>
      <link>https://dev.to/phaz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phaz"/>
    <language>en</language>
    <item>
      <title>Cold email law changes at every border, so I put an open model in the browser to check my drafts</title>
      <dc:creator>Ilia Ivanov</dc:creator>
      <pubDate>Tue, 13 Oct 2026 11:40:01 +0000</pubDate>
      <link>https://dev.to/phaz/cold-email-law-changes-at-every-border-so-i-put-an-open-model-in-the-browser-to-check-my-drafts-2h4p</link>
      <guid>https://dev.to/phaz/cold-email-law-changes-at-every-border-so-i-put-an-open-model-in-the-browser-to-check-my-drafts-2h4p</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I'm 18, I live in Shenzhen and I do freelance web work. Last week I started sending cold emails to small online shops in Europe. Then I read the Spanish law and found out that a first marketing email there needs consent, even when you write to a company. I stopped and went to read the rest.&lt;/p&gt;

&lt;p&gt;I read the rules for 20 countries, one law at a time. They do not agree with each other. Germany, Spain and Italy want consent first. France lets you write to a professional if the offer relates to their job. The US wants a postal address and a way to opt out in every email. Sweden protects people but not companies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coldproof&lt;/strong&gt; checks a cold email draft against the law of the country it is going to.&lt;/p&gt;

&lt;p&gt;You pick the recipient's country and the kind of address, and paste your draft. You get three things back:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The legal verdict for that country, with a link to the law or the regulator.&lt;/li&gt;
&lt;li&gt;A checklist of what that country requires inside the email, with the exact words the model found in your draft for each item.&lt;/li&gt;
&lt;li&gt;A fixed version with the missing lines added, in the language of your email.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Who would pay for it: sales teams and outbound agencies that send to several countries at once. One wrong campaign can mean a fine or a burned domain, and nobody on the team has time to read 20 laws. A single draft is free. The page has a "for teams" offer at $19 per seat with a button that only counts interest, because I wanted to know if anyone cares before I build billing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://phazww.github.io/coldproof/" rel="noopener noreferrer"&gt;https://phazww.github.io/coldproof/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click "Try a sample" and then "Check my draft". The first run downloads the model once. After that a check takes about 10 seconds on my Mac with Gemma, and about 6 with the smaller Qwen model.&lt;/p&gt;

&lt;p&gt;It needs WebGPU, so use a recent Chrome, Edge or Safari on a computer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/phazww" rel="noopener noreferrer"&gt;
        phazww
      &lt;/a&gt; / &lt;a href="https://github.com/phazww/coldproof" rel="noopener noreferrer"&gt;
        coldproof
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Check a cold email against the law of the recipient's country. An open-weight model runs in your browser, the draft never leaves your machine.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Coldproof&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Check a cold email draft against the law of the recipient's country. An open-weight model runs in your browser through WebGPU, reads the draft and reports what it contains, quoting the exact words. The page compares that with checked rules for 20 countries and returns the missing pieces and a fixed version. The draft never leaves your machine.&lt;/p&gt;
&lt;p&gt;Live: &lt;a href="https://phazww.github.io/coldproof/" rel="nofollow noopener noreferrer"&gt;https://phazww.github.io/coldproof/&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it is built&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rules.js&lt;/code&gt;: per-country rules for the first unsolicited marketing email to a business recipient, each with its source. The research comes from my earlier project &lt;a href="https://github.com/phazww/can-i-cold-email" rel="noopener noreferrer"&gt;can-i-cold-email&lt;/a&gt;, checked against the law or the regulator on 10 and 11 October 2026.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.js&lt;/code&gt;: loads the model with &lt;a href="https://github.com/mlc-ai/web-llm" rel="noopener noreferrer"&gt;WebLLM&lt;/a&gt;, asks it for a JSON report with quotes, verifies that every quote is really in the draft, and assembles the fixed version from hand-written wording in 13 languages.&lt;/li&gt;
&lt;li&gt;Two open-weight models to choose from, both tested on…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/phazww/coldproof" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;No server, no API key, no build step. Three files: the rules, the page, and the script.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The default model is &lt;strong&gt;Gemma 4 E2B&lt;/strong&gt;, running locally in the browser through &lt;a href="https://github.com/mlc-ai/web-llm" rel="noopener noreferrer"&gt;WebLLM&lt;/a&gt; on WebGPU. There is a second option, &lt;strong&gt;Qwen 3.5 2B&lt;/strong&gt;, which is about 1 GB and quicker to get. Both are open-weight.&lt;/p&gt;

&lt;p&gt;The first version let the model do everything: read the draft, decide what was wrong, rewrite it. It looked great on the English sample. Then I tested a French email. The model was asked to add an opt-out line and wrote, in polite French, "if you would like to receive information about our services, please reply to this message". That is the opposite of an opt-out. For a tool about the law, that is the worst possible bug, because it looks correct.&lt;/p&gt;

&lt;p&gt;So I took jobs away from the model until it had only the one it is good at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The model reads.&lt;/strong&gt; It gets the draft and returns a JSON report: the sender's name, the sender's company, whether there is a way to say stop, a postal address, a plain commercial offer, and what language the email is in. For every "yes" it must quote the exact words. WebLLM's JSON schema mode keeps the output in shape.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The page checks the quotes.&lt;/strong&gt; If the model says "yes, there is an opt-out" but the quoted words are not in the draft, the page counts it as missing and says so. The quoted sentence also has to look like an opt-out. A small model cannot talk its way past this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The law is not the model's job.&lt;/strong&gt; Which elements each country requires comes from a rules file. I built that research last weekend for another project of mine, &lt;a href="https://github.com/phazww/can-i-cold-email" rel="noopener noreferrer"&gt;can-i-cold-email&lt;/a&gt;, and checked each country against the law text or the regulator. The app in this post was built this week on top of that data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The legal lines are fixed wording.&lt;/strong&gt; The opt-out sentence and the other added lines exist in 13 languages and are fixed in advance, not generated when you run a check. The model only tells the page which language the email is in. I do not speak all 13, so corrections are welcome.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The subject check is plain code.&lt;/strong&gt; A first email that starts with "Re:" is pretending to be a reply. That does not need a model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consent countries get a stop sign.&lt;/strong&gt; If the country requires consent before the first email, the page says so and does not offer a rewrite. No wording fixes that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ran the same five drafts through both models: a bad English one, a clean English one, French, Finnish, and a trap. The trap is an email that says "most small firms tell us they cannot unsubscribe from their old payroll vendor". It contains the word "unsubscribe" and has no opt-out at all.&lt;/p&gt;

&lt;p&gt;Gemma got all five right. The smaller Qwen model made two mistakes on the trap. It accepted the signature "Sam" as identifying the sender, with no company anywhere. And in one run it pointed to "We make switching free." as the opt-out. Both are now caught: the sender check asks for the name and the company separately, and the opt-out quote has to contain opt-out wording. After that both models pass all five, and Gemma became the default.&lt;/p&gt;

&lt;p&gt;I worked with an AI coding agent the whole way. The bug with the French sentence was found by testing real drafts in the browser, not by reading the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;A cold email draft is a list of things a company does not want to leak: who they are targeting, what they are offering, sometimes a customer's name. A lead list is personal data. The whole point of this tool is to help people respect privacy law. Sending that data to someone else's API to check it would be a strange way to do that.&lt;/p&gt;

&lt;p&gt;An open-weight model lets the check run on the user's own graphics card. Nothing is uploaded. There is no account, no key and no server for me to pay for, which matters when you are 18 and your hosting budget is zero. It also means the tool keeps working if I disappear.&lt;/p&gt;

&lt;p&gt;And open weights let anyone see exactly which model made the call, swap it for a better one, and test it on their own language. A closed API would have hidden the French bug behind a nicer average.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overall&lt;/li&gt;
&lt;li&gt;Best Use of Gemma: Gemma 4 E2B is the default model and runs locally in the browser. It was the only one of the two that got every test draft right on its own.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
