<?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: Bohdan Khomyn</title>
    <description>The latest articles on DEV Community by Bohdan Khomyn (@balabony).</description>
    <link>https://dev.to/balabony</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%2F4181682%2Fcc7cb93a-1e0b-4d70-97c5-9d0f442bcfdb.png</url>
      <title>DEV Community: Bohdan Khomyn</title>
      <link>https://dev.to/balabony</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/balabony"/>
    <language>en</language>
    <item>
      <title>We checked 71 clinic websites for email spoofing protection. Then we found the same hole in our own domain</title>
      <dc:creator>Bohdan Khomyn</dc:creator>
      <pubDate>Thu, 15 Oct 2026 09:32:08 +0000</pubDate>
      <link>https://dev.to/balabony/we-checked-71-clinic-websites-for-email-spoofing-protection-then-we-found-the-same-hole-in-our-own-3fll</link>
      <guid>https://dev.to/balabony/we-checked-71-clinic-websites-for-email-spoofing-protection-then-we-found-the-same-hole-in-our-own-3fll</guid>
      <description>&lt;p&gt;Clinics hold the most sensitive data there is: diagnoses, test results, appointments. Patients trust emails that come from their clinic's domain. So we asked a simple question: &lt;strong&gt;can anyone send an email that looks like it came from a private clinic?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We checked 71 private clinic websites in Lviv, Ukraine, in October 2026. Passive checks only: the home page, HTTP headers and public DNS records, exactly what any visitor or mail server sees. No scanning, no login attempts. We publish aggregate numbers only, no clinic names.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Not one of the 71 domains has DMARC set to block spoofed email.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;79% have no DMARC record at all.&lt;/li&gt;
&lt;li&gt;The rest have &lt;code&gt;p=none&lt;/code&gt;, which only monitors and blocks nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a patient, that means a fraudster can send "your test results are attached" or "pay for your appointment here" from the clinic's real address, and the inbox will not flag it.&lt;/p&gt;

&lt;p&gt;Other findings from the same scan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;80% send no HSTS header.&lt;/li&gt;
&lt;li&gt;89% have no Content-Security-Policy.&lt;/li&gt;
&lt;li&gt;15% load jQuery older than 3.5, which has known XSS issues.&lt;/li&gt;
&lt;li&gt;83% have images with no alt text; 31% of all images are undescribed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good news: all 71 use HTTPS and are mobile-friendly. The basics are there; the next step is missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then we checked ourselves
&lt;/h2&gt;

&lt;p&gt;Our studio domain, olbo.com.ua, had SPF and DKIM configured properly, and DMARC set to... &lt;code&gt;p=none&lt;/code&gt;. Exactly the gap we had just written about.&lt;/p&gt;

&lt;h2&gt;
  
  
  SPF, DKIM, DMARC in one paragraph each
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SPF&lt;/strong&gt; is a TXT record on your domain listing who may send mail for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v=spf1 include:zohomail.eu ~all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DKIM&lt;/strong&gt; is a signature on every message. Your mail provider signs with a private key; receivers verify with the public key published at &lt;code&gt;selector._domainkey.yourdomain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DMARC&lt;/strong&gt; tells receivers what to do when a message fails the checks, and where to send reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_dmarc.yourdomain  TXT  "v=DMARC1; p=quarantine; rua=mailto:reports@yourdomain"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;p=none&lt;/code&gt; = report only. &lt;code&gt;p=quarantine&lt;/code&gt; = spam folder. &lt;code&gt;p=reject&lt;/code&gt; = don't deliver. &lt;strong&gt;Only the last two actually protect anyone.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How we switched without breaking our own mail
&lt;/h2&gt;

&lt;p&gt;The risk with &lt;code&gt;p=quarantine&lt;/code&gt; is that your &lt;em&gt;legitimate&lt;/em&gt; mail starts landing in spam. The usual culprit is a service you forgot sends mail as you: a contact form, a newsletter tool, a CRM, an invoicing system.&lt;/p&gt;

&lt;p&gt;Our list was short:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zoho Mail&lt;/strong&gt; for people (hello@). DKIM key &lt;code&gt;zmail._domainkey&lt;/code&gt;, included in SPF.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resend&lt;/strong&gt; for the website: form notifications and report emails, sent as &lt;a href="mailto:forms@"&gt;forms@&lt;/a&gt;. DKIM key &lt;code&gt;resend._domainkey&lt;/code&gt;; the return path is on a subdomain, which still aligns under DMARC's default relaxed mode.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both already had DKIM, so the change was one edit: &lt;code&gt;p=none&lt;/code&gt; → &lt;code&gt;p=quarantine&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we verified with real messages, not just DNS lookups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An email from hello@ to a Gmail inbox → "Show original": &lt;strong&gt;SPF PASS, DKIM PASS, DMARC PASS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A website form submission → arrived, not in spam.&lt;/li&gt;
&lt;li&gt;An automated report email sent through Resend → &lt;strong&gt;SPF, DKIM, DMARC: PASS&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total time: about 10 minutes. We'll move to &lt;code&gt;p=reject&lt;/code&gt; in 2–3 weeks after reading the aggregate reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking a domain yourself
&lt;/h2&gt;

&lt;p&gt;From a terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig +short TXT yourdomain.com | &lt;span class="nb"&gt;grep &lt;/span&gt;spf1
dig +short TXT _dmarc.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in Node, which is roughly what our checker does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dns&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:dns&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolveTxt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;v=spf1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dmarc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`_dmarc.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;/^v=DMARC1/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dmarc&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;p=&lt;/span&gt;&lt;span class="se"&gt;(\w&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;)?.[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;spf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dmarc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;protected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;spf&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;quarantine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;join('')&lt;/code&gt;: long TXT records come back split into 255-byte chunks.&lt;/p&gt;

&lt;p&gt;If you'd rather not open a terminal, or want to send something to a non-technical client, we made the same check into a free page with a plain-language answer and no sign-up: &lt;a href="https://olbo.com.ua/en/dmarc-checker?src=devto" rel="noopener noreferrer"&gt;olbo.com.ua/en/dmarc-checker&lt;/a&gt;. We don't store the domains people enter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;If you build sites for small businesses, add one line to your handover checklist: &lt;strong&gt;"DMARC at quarantine or reject, tested with a real email."&lt;/strong&gt; It's an hour of work and closes one of the easiest ways to impersonate your client.&lt;/p&gt;

&lt;p&gt;The full clinic study, including the four steps we recommend to clinic managers, is here: &lt;a href="https://olbo.com.ua/en/articles/clinic-website-security-study?src=devto" rel="noopener noreferrer"&gt;Clinic website security: a study of 71 clinic sites&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>How we built a free 13-point website checker in Lviv</title>
      <dc:creator>Bohdan Khomyn</dc:creator>
      <pubDate>Tue, 13 Oct 2026 09:01:39 +0000</pubDate>
      <link>https://dev.to/balabony/how-we-built-a-free-13-point-website-checker-in-lviv-6ek</link>
      <guid>https://dev.to/balabony/how-we-built-a-free-13-point-website-checker-in-lviv-6ek</guid>
      <description>&lt;p&gt;Small business owners have asked me the same question again and again: "Is my website OK, or do I need a new one?" Existing tools answer only part of it. PageSpeed shows speed, SSL Labs shows the certificate, another service checks email. Nobody puts it all into one clear answer.&lt;/p&gt;

&lt;p&gt;So we built OLBO Website Checker: 13 checks in about a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it checks
&lt;/h2&gt;

&lt;p&gt;Hosting, HTTPS and security headers, email protection (SPF, DMARC), the platform and its version, outdated components, known vulnerabilities, Google blacklists, site age, basic accessibility (European Accessibility Act), privacy (GDPR), Google search, AI search readiness (does the site let GPTBot and ClaudeBot in, is there an llms.txt) and mobile speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three decisions that matter for website owners
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The check runs live.&lt;/strong&gt; The server streams results one item at a time, so people see the program actually working instead of a pre-drawn template. That builds more trust than any description.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Don't take our word for it."&lt;/strong&gt; Next to the first results there are links to independent free tools (SSL Labs, MXToolbox, BuiltWith), so anyone can verify us.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No database.&lt;/strong&gt; We don't store which websites were checked. A paid report opens through a signed link that works for 30 days and for one website only.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Data sources
&lt;/h2&gt;

&lt;p&gt;IP registries (RDAP, IPinfo), endoflife.date for support dates, the OSV vulnerability database, Google Safe Browsing, PageSpeed Insights and the Wayback Machine. Public data only: we don't hack anything and don't log in anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Next.js on Vercel. A headless Chrome on the server generates the PDF report. There is also a Telegram bot.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it compares
&lt;/h2&gt;

&lt;p&gt;There are great tools out there, and we use them ourselves. The difference is in what one check covers and what it costs.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What one check covers&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Google PageSpeed Insights&lt;/td&gt;
&lt;td&gt;Speed, basic SEO and accessibility&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GTmetrix&lt;/td&gt;
&lt;td&gt;Speed and performance&lt;/td&gt;
&lt;td&gt;Free; PRO from $4.99/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sucuri SiteCheck&lt;/td&gt;
&lt;td&gt;Malware, blacklists, outdated software&lt;/td&gt;
&lt;td&gt;Free; protection plans paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semrush Site Audit&lt;/td&gt;
&lt;td&gt;Deep technical SEO across many pages&lt;/td&gt;
&lt;td&gt;From $139/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OLBO Website Checker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;13 areas: hosting, security, email, platform, vulnerabilities, accessibility, GDPR, Google, AI search, speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Score free; full report €25 once&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Prices as of October 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What we do differently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Everything in one place.&lt;/strong&gt; Speed, security, email protection, accessibility, GDPR and AI search readiness in a single run. Usually that takes four or five different tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One payment, no subscription.&lt;/strong&gt; The full report is €25 once. You don't have to pay monthly to read one result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Written for the owner, not only the developer.&lt;/strong&gt; Every finding explains what it means for the business, and the fix list is a ready task for your developer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We check the new things.&lt;/strong&gt; Few free tools look at the European Accessibility Act or at whether ChatGPT and Claude can read your site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To be fair about the limits: our check is automated and approximate. It doesn't replace a deep SEO audit of thousands of pages (that's what Semrush is for) or a full manual accessibility audit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honestly about me
&lt;/h2&gt;

&lt;p&gt;I'm not a programmer. I'm a publisher with 23 years of experience. I wrote the code together with an AI assistant, with advice from programmer friends. My part was the product: what to check, how to explain it to a website owner in plain words, and where the line of honesty is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;The overall score and the colour of each of the 13 checks are free. The full report with explanations and step-by-step fixes for your developer costs €25. Part of the revenue supports Balabony, our Ukrainian story platform that is accessible to people with disabilities.&lt;/p&gt;

&lt;p&gt;Check your website: &lt;a href="https://olbo.com.ua/en/website-checker?utm_source=devto" rel="noopener noreferrer"&gt;https://olbo.com.ua/en/website-checker?utm_source=devto&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tell me which check is missing and what is worth improving. Thank you!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>seo</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
