<?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: Rustamjon Akhmedov</title>
    <description>The latest articles on DEV Community by Rustamjon Akhmedov (@proga100).</description>
    <link>https://dev.to/proga100</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%2F1222113%2Fdde8a9e5-08ea-4fe2-9494-66b6569f2b31.jpeg</url>
      <title>DEV Community: Rustamjon Akhmedov</title>
      <link>https://dev.to/proga100</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/proga100"/>
    <language>en</language>
    <item>
      <title>AIAuditFrauds: Building a Human-in-the-Loop AI Auditor on Qwen Cloud</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Wed, 08 Jul 2026 06:51:55 +0000</pubDate>
      <link>https://dev.to/proga100/aiauditfrauds-building-a-human-in-the-loop-ai-auditor-on-qwen-cloud-3aig</link>
      <guid>https://dev.to/proga100/aiauditfrauds-building-a-human-in-the-loop-ai-auditor-on-qwen-cloud-3aig</guid>
      <description>&lt;p&gt;For the Global AI Hackathon Series with Qwen Cloud (Track 4 · Autopilot Agent) I built &lt;strong&gt;AIAuditFrauds&lt;/strong&gt;: a multi-agent AI that automates a corporate finance audit end-to-end — semantic search over 1,558 invoices, rule detectors, OFAC sanctions screening, a written report — while a human approves every consequential action. 100% on the Qwen stack: &lt;strong&gt;qwen-max + text-embedding-v4 (DashScope), AgentScope, DashVector, deployed on Alibaba Cloud ECS.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/RVi0Vh_mm_w"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aiauditfrauds.flance.info" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Try the Live Demo of AIAuditFrauds&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: AI you can trust with money
&lt;/h2&gt;

&lt;p&gt;Corporate finance teams drown in invoices, and fraud hides in the noise: the same invoice paid twice, a "vendor" that doesn't exist, an amount that quietly breaks policy, a wire pushed through at 3 a.m., a payee on a sanctions list. No human can eyeball tens of thousands of rows.&lt;/p&gt;

&lt;p&gt;But finance is exactly where you &lt;strong&gt;cannot&lt;/strong&gt; let an AI act on its own. An LLM that hallucinates a paragraph is embarrassing; an LLM that flags the wrong vendor as fraudulent — or misses a sanctioned payee — is a lawsuit. So the design goal became the whole product: &lt;strong&gt;automate the workflow end-to-end, but put a human checkpoint in front of every consequential action.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And one architectural rule I never broke:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The deterministic detectors decide the audit outcome. Qwen plans, narrates and answers questions.&lt;/strong&gt; If the model is ever down, the audit still runs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What it does — one mission, two human gates
&lt;/h2&gt;

&lt;p&gt;You type an ambiguous, free-text mission: "find duplicate vendor payments and suspicious spending this quarter."&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcnsjgrgx6b03h2d1456.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcnsjgrgx6b03h2d1456.png" alt="AIAuditFrauds mission console where the auditor types a free-text audit mission" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 1 — the plan.&lt;/strong&gt; Qwen (qwen-max via DashScope) interprets the mission and drafts a concrete audit plan. Nothing runs until the auditor approves, edits, or rejects it.&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxsg7450vxq9mwi1afyi.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxsg7450vxq9mwi1afyi.png" alt="Gate 1 showing the Qwen-generated audit plan awaiting human approval" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence.&lt;/strong&gt; A team of AgentScope specialists takes over, each step attributed live in the timeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Screening&lt;/strong&gt; → semantic search in &lt;strong&gt;DashVector&lt;/strong&gt; over Qwen text-embedding-v4 vectors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spend Analysis&lt;/strong&gt; → SQL aggregation in PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk Triage&lt;/strong&gt; → deterministic detectors (exact/near duplicates, policy limits, ghost vendors, off-hours payments) + live screening against the &lt;strong&gt;US Treasury OFAC&lt;/strong&gt; sanctions list&lt;/li&gt;
&lt;/ul&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3c0d47su6zce62ox9gh9.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3c0d47su6zce62ox9gh9.png" alt="Agent timeline showing each specialist agent's step during the audit run" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The run above flagged &lt;strong&gt;595 suspicious invoices worth $33M&lt;/strong&gt; — each with reasons and evidence you can drill into:&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvr84c85gamyhzhdbktg.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvr84c85gamyhzhdbktg.png" alt="Invoice evidence review panel listing flagged invoices with reasons" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate 2 — the human decides.&lt;/strong&gt; The auditor approves or rejects items one by one. Only approved invoices are written — a single idempotent, audited transaction. The AI never touches the ledger.&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kzx0hskihb84zhppc4j.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kzx0hskihb84zhppc4j.png" alt="Gate 2 human decision screen where the auditor approves or rejects flagged invoices" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Report.&lt;/strong&gt; Qwen writes the closing narrative, and an Audit Assistant answers follow-up questions grounded in the actual evidence ("Which flagged invoice is the most urgent to verify, and why?").&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F803s4bk5exauijvtma44.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F803s4bk5exauijvtma44.png" alt="Closing report with the Audit Assistant answering a follow-up question" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture
&lt;/h2&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0am7dd7hr08f4ivyz20.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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0am7dd7hr08f4ivyz20.png" alt="System architecture diagram of AIAuditFrauds on the Qwen Cloud stack" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything hinges on one seam: a typed Server-Sent-Events contract — plan → gate 1 → tools → proposal → gate 2 → gated write → report → done. The frontend, store and API depend only on that event sequence, so the model, agent and data layers could evolve freely underneath while 124 contract tests kept everything honest (the whole suite runs with &lt;strong&gt;zero&lt;/strong&gt; cloud credentials).&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with the Qwen Cloud stack — field notes
&lt;/h2&gt;

&lt;p&gt;This was my first project going all-in on the Qwen ecosystem. Honest notes from the journey:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DashScope (Qwen API).&lt;/strong&gt; One key from the Qwen Cloud console drives both chat and embeddings. text-embedding-v4 returns clean 1024-dim vectors; embedding 1,558 invoices took under two minutes in batches of 10.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  How to fix the 401 invalid_api_key error
  &lt;p&gt;The one gotcha for international accounts: use the intl endpoints, or you'll stare at 401 invalid_api_key wondering what you did wrong:&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="c1"&gt;# native SDK
&lt;/span&gt;&lt;span class="n"&gt;dashscope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_http_api_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dashscope-intl.aliyuncs.com/api/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# OpenAI-compatible mode (what AgentScope uses under the hood)
&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://dashscope-intl.aliyuncs.com/compatible-mode/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AgentScope 2.x.&lt;/strong&gt; Alibaba's multi-agent framework had a major rewrite, so tutorials from 1.x will mislead you — read the installed source. The API I landed on:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  AgentScope 2.x agent setup
  &lt;br&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;agentscope.agent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;  &lt;span class="c1"&gt;# Agent IS the ReAct agent
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentscope.model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DashScopeChatModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentscope.credential&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DashScopeCredential&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agentscope.tool&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Toolkit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FunctionTool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ToolResponse&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DashScopeChatModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;DashScopeCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;INTL_COMPAT_URL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qwen-max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RiskTriageAgent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="n"&gt;toolkit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Toolkit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;FunctionTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screen_vendor_sanctions&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Three things that cost me debugging time: Msg.content must be a &lt;strong&gt;list of content blocks&lt;/strong&gt; (not a string), tool functions must return a &lt;strong&gt;ToolResponse&lt;/strong&gt; (not a dict), and the credential's base_url decides which region you hit. Once wired, an agent calling a real OFAC-screening tool worked on the first live run — and AgentScope's built-in external tool-confirmation flow maps beautifully onto human-in-the-loop designs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DashVector.&lt;/strong&gt; The pleasant surprise of the project. Free trial cluster, created a 1024-dim cosine collection in the console, and the SDK is tiny:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  DashVector upsert and query
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;coll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dashvector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ENDPOINT&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;transactions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;dashvector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;inv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;invoice_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{...})])&lt;/span&gt;
&lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vendor_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Being built by the same team as Qwen, it pairs naturally with Qwen embeddings — no dimension gymnastics, no separate index management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alibaba Cloud ECS.&lt;/strong&gt; The whole system deploys as one Docker Compose stack (app + PostgreSQL) on a $0.02/hour ECS instance in Singapore, behind Caddy for automatic Let's Encrypt HTTPS. Total cloud bill for the entire hackathon: &lt;strong&gt;under $10&lt;/strong&gt;. A fun proof-of-deployment trick: Alibaba's internal metadata service (&lt;a href="http://100.100.100.200" rel="noopener noreferrer"&gt;http://100.100.100.200&lt;/a&gt;) is only reachable from inside Alibaba Cloud — one curl attests your instance identity.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I'd tell you if you're building on Qwen Cloud
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pin your AgentScope version and introspect the installed API&lt;/strong&gt; — the 2.x rewrite is good, but docs lag. inspect.signature() is your friend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design so the LLM is a planner/narrator, not the source of truth.&lt;/strong&gt; Deterministic logic decides; Qwen explains. Your demo will survive any quota hiccup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep one region.&lt;/strong&gt; DashScope intl + DashVector + ECS + OSS all in Singapore = no cross-region surprises and free internal traffic to OSS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make your test suite credential-free.&lt;/strong&gt; An in-memory repository behind the same interface as Postgres + DashVector meant CI never needed a single key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human gates are a feature, not friction.&lt;/strong&gt; The two-gate design is the reason a finance team could actually deploy this.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;A production-posture autopilot for finance audits: live on Alibaba Cloud, HTTPS domain, 124 green tests, graceful fallbacks, idempotent writes — and a human in command of every dollar-touching decision.&lt;/p&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/proga100" rel="noopener noreferrer"&gt;
        proga100
      &lt;/a&gt; / &lt;a href="https://github.com/proga100/aiauditfrauds" rel="noopener noreferrer"&gt;
        aiauditfrauds
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Multi-agent finance fraud auditor on Qwen + AgentScope + DashVector, deployed on Alibaba Cloud (Qwen Cloud Hackathon, Agent Society)
    &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;AIAuditFrauds&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A multi-agent AI auditor that automates the corporate finance-audit workflow end-to-end — hunting duplicate payments, ghost vendors, policy breaches, off-hours transactions and OFAC sanctions risk — with human-in-the-loop checkpoints at every critical decision.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Built for the &lt;strong&gt;Global AI Hackathon Series with Qwen Cloud&lt;/strong&gt; · Track: &lt;strong&gt;Autopilot Agent&lt;/strong&gt; · Runs 100% on the Qwen / Alibaba Cloud stack.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;Live demo:&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://aiauditfrauds.flance.info" rel="nofollow noopener noreferrer"&gt;https://aiauditfrauds.flance.info&lt;/a&gt;&lt;/strong&gt; &lt;em&gt;(deployed on Alibaba Cloud ECS, Singapore)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🎬 &lt;strong&gt;Demo video (2:18):&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=RVi0Vh_mm_w" rel="nofollow noopener noreferrer"&gt;https://www.youtube.com/watch?v=RVi0Vh_mm_w&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🧩 &lt;strong&gt;Stack:&lt;/strong&gt; Qwen (DashScope) · AgentScope · DashVector · PostgreSQL · Alibaba Cloud OSS&lt;/li&gt;
&lt;li&gt;🔗 &lt;strong&gt;Proof of Alibaba Cloud usage:&lt;/strong&gt; &lt;a href="https://github.com/proga100/aiauditfrauds/aiauditfrauds/integrations/alibaba_cloud.py" rel="noopener noreferrer"&gt;&lt;code&gt;aiauditfrauds/integrations/alibaba_cloud.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The idea — and why it matters&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Corporate finance teams drown in invoices, and fraud hides in the noise: the same invoice paid twice, a
payment to a vendor that doesn't really exist, an amount that quietly breaks policy, a wire pushed through
at 3 a.m., a payee on a sanctions list. A human can't eyeball…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/proga100/aiauditfrauds" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;Try it live:&lt;/strong&gt; &lt;a href="https://aiauditfrauds.flance.info" rel="noopener noreferrer"&gt;https://aiauditfrauds.flance.info&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎬 &lt;strong&gt;3-min demo:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=RVi0Vh_mm_w" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=RVi0Vh_mm_w&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⭐ &lt;strong&gt;Code (GPL-3.0):&lt;/strong&gt; &lt;a href="https://github.com/proga100/aiauditfrauds" rel="noopener noreferrer"&gt;https://github.com/proga100/aiauditfrauds&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built for the Global AI Hackathon Series with Qwen Cloud — Track 4: Autopilot Agent. The project concept existed before the hackathon; during the submission period it was rebuilt end-to-end on the Qwen stack (DashScope, AgentScope, DashVector, ECS). Development was AI-assisted with Claude Code.&lt;/p&gt;

</description>
      <category>qwen</category>
      <category>ai</category>
      <category>agents</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>How to Check if an Image Has Alt Text: 4 Easy Methods</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 30 Mar 2026 17:01:58 +0000</pubDate>
      <link>https://dev.to/proga100/how-to-check-if-an-image-has-alt-text-4-easy-methods-4555</link>
      <guid>https://dev.to/proga100/how-to-check-if-an-image-has-alt-text-4-easy-methods-4555</guid>
      <description>&lt;h2&gt;
  
  
  Why Alt Text Matters
&lt;/h2&gt;

&lt;p&gt;Alt text (alternative text) is a short written description added to an image via the &lt;code&gt;alt&lt;/code&gt; attribute in HTML. It serves two critical purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It allows screen readers to describe images to visually impaired users&lt;/li&gt;
&lt;li&gt;It gives search engines context to understand what an image depicts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;According to the WebAIM Million 2025 report, &lt;strong&gt;95.9% of home pages have detectable WCAG failures&lt;/strong&gt;, and missing alt text remains the single most common accessibility error found on the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Inspect the Page Source (View Source)
&lt;/h2&gt;

&lt;p&gt;The simplest way to check alt text is to view the raw HTML source:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the page in your browser&lt;/li&gt;
&lt;li&gt;Right-click anywhere and select &lt;strong&gt;View Page Source&lt;/strong&gt; (or press &lt;code&gt;Ctrl+U&lt;/code&gt; / &lt;code&gt;Cmd+U&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Ctrl+F&lt;/code&gt; / &lt;code&gt;Cmd+F&lt;/code&gt; to search for &lt;code&gt;&amp;lt;img&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For each image tag, look for the &lt;code&gt;alt&lt;/code&gt; attribute&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example of properly formatted alt text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A woman reading a book in a library"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;alt&lt;/code&gt; attribute is missing entirely, or if it's present but empty (&lt;code&gt;alt=""&lt;/code&gt;), the image may need attention. Note that &lt;code&gt;alt=""&lt;/code&gt; is intentionally used for decorative images—this is valid per WCAG standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: Use Browser Developer Tools (Inspect Element)
&lt;/h2&gt;

&lt;p&gt;For a faster, more visual approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click directly on the image you want to check&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Inspect&lt;/strong&gt; or &lt;strong&gt;Inspect Element&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The DevTools panel will open with the image's HTML highlighted&lt;/li&gt;
&lt;li&gt;Look for the &lt;code&gt;alt&lt;/code&gt; attribute in the highlighted &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This method is especially useful when you want to check a specific image quickly without searching through the full page source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 3: Use the WAVE Accessibility Tool
&lt;/h2&gt;

&lt;p&gt;The WAVE browser extension from WebAIM is one of the most widely used free accessibility testing tools available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the WAVE browser extension (Chrome or Firefox)&lt;/li&gt;
&lt;li&gt;Navigate to the page you want to check&lt;/li&gt;
&lt;li&gt;Click the WAVE extension icon&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red icon&lt;/strong&gt; = missing alt text (critical error)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Green icon&lt;/strong&gt; = alt text is present&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yellow icon&lt;/strong&gt; = potential concern (suspiciously long, duplicated, or filename-based)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;WAVE also displays a summary count of errors, making it easy to see how many images on a page are missing alt text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 4: Use Alt Audit for Sitewide Checks
&lt;/h2&gt;

&lt;p&gt;For larger websites with hundreds or thousands of images, automated tools like Alt Audit save hours of manual work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scan thousands of images across your entire domain in minutes&lt;/li&gt;
&lt;li&gt;Identify exactly which pages and images are missing alt text&lt;/li&gt;
&lt;li&gt;Get AI-powered suggestions to generate descriptive alt text automatically&lt;/li&gt;
&lt;li&gt;Track your progress over time as you fix issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Makes Good Alt Text?
&lt;/h2&gt;

&lt;p&gt;Follow these guidelines when writing alt descriptions:&lt;/p&gt;

&lt;p&gt;✓ &lt;strong&gt;Be descriptive and specific:&lt;/strong&gt; "Golden retriever puppy playing in autumn leaves" beats "dog"&lt;br&gt;
✓ &lt;strong&gt;Keep it concise:&lt;/strong&gt; Aim for under 125 characters (screen readers may cut off longer text)&lt;br&gt;
✓ &lt;strong&gt;Don't start with "Image of" or "Photo of":&lt;/strong&gt; Screen readers already announce it's an image&lt;br&gt;
✓ &lt;strong&gt;Reflect context:&lt;/strong&gt; The same image might need different alt text depending on where it appears&lt;br&gt;
✓ &lt;strong&gt;Use empty alt for decorative images:&lt;/strong&gt; &lt;code&gt;alt=""&lt;/code&gt; tells screen readers to skip purely decorative images&lt;/p&gt;

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

&lt;p&gt;Watch out for these frequent errors:&lt;/p&gt;

&lt;p&gt;✗ Missing &lt;code&gt;alt&lt;/code&gt; attribute entirely&lt;br&gt;
✗ Using filenames as alt text ("IMG_4823.jpg")&lt;br&gt;
✗ Keyword stuffing ("best cheap shoes buy shoes online")&lt;br&gt;
✗ Identical alt text on different images&lt;br&gt;
✗ Alt text that's too long or too short to be meaningful&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Comparison: All 4 Methods
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Skill Level&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;View Source&lt;/td&gt;
&lt;td&gt;Quick spot-checks&lt;/td&gt;
&lt;td&gt;Single page&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Beginner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DevTools&lt;/td&gt;
&lt;td&gt;Inspecting specific images&lt;/td&gt;
&lt;td&gt;Single element&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Intermediate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAVE Extension&lt;/td&gt;
&lt;td&gt;Visual accessibility overview&lt;/td&gt;
&lt;td&gt;Single page&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Beginner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alt Audit&lt;/td&gt;
&lt;td&gt;Full site audits at scale&lt;/td&gt;
&lt;td&gt;Entire domain&lt;/td&gt;
&lt;td&gt;Free tier available&lt;/td&gt;
&lt;td&gt;Beginner&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Whether you're a developer, content manager, or SEO specialist, knowing how to check if an image has alt text is fundamental for building accessible, high-performing websites. For fast, thorough, and scalable solutions, automated tools like Alt Audit help you stay compliant with WCAG standards while improving your site's accessibility and search rankings.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Canonical URL:&lt;/strong&gt; &lt;a href="https://altaudit.com/blog/how-to-check-if-image-has-alt-text" rel="noopener noreferrer"&gt;https://altaudit.com/blog/how-to-check-if-image-has-alt-text&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wcag</category>
    </item>
    <item>
      <title>How to Check if an Image Has Alt Text — 4 Methods I Actually Use</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Sat, 21 Mar 2026 11:54:52 +0000</pubDate>
      <link>https://dev.to/proga100/how-to-check-if-an-image-has-alt-text-4-methods-i-actually-use-27h4</link>
      <guid>https://dev.to/proga100/how-to-check-if-an-image-has-alt-text-4-methods-i-actually-use-27h4</guid>
      <description>&lt;p&gt;If you've ever wondered whether the images on your site actually have alt text — you're not alone. It's one of those things that's easy to forget and surprisingly tedious to check manually.&lt;/p&gt;

&lt;p&gt;I've been working on accessibility tooling for a while now, and these are the four methods I rely on daily — from quick one-off checks to full site audits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bother checking?
&lt;/h2&gt;

&lt;p&gt;Alt text does two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Screen readers use it to describe images to visually impaired users.&lt;/li&gt;
&lt;li&gt;Search engines use it to understand what an image shows.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Missing alt text is the most common WCAG violation on the web (&lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html" rel="noopener noreferrer"&gt;WCAG 1.1.1&lt;/a&gt;). And fixing it is usually straightforward — you just have to know where the gaps are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: View Page Source
&lt;/h2&gt;

&lt;p&gt;The old-school way. Still works perfectly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click anywhere on the page → View Page Source (or Ctrl+U / Cmd+U)&lt;/li&gt;
&lt;li&gt;Ctrl+F → search for &lt;code&gt;&amp;lt;img&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check each image tag for the &lt;code&gt;alt&lt;/code&gt; attribute
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- ✅ Good --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A woman reading a book in a library"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- ❌ Missing --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- ⚠️ Empty (valid only for decorative images) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"divider.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quick note: &lt;code&gt;alt=""&lt;/code&gt; is actually correct for purely decorative images. WCAG says screen readers should skip these.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: DevTools (Inspect Element)
&lt;/h2&gt;

&lt;p&gt;This is my go-to for checking a specific image:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click the image → Inspect&lt;/li&gt;
&lt;li&gt;DevTools opens with the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag highlighted&lt;/li&gt;
&lt;li&gt;Look for the &lt;code&gt;alt&lt;/code&gt; attribute right there&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It takes about 3 seconds. You can also hover over elements in the panel to see which image you're looking at — super useful on image-heavy pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 3: WAVE Browser Extension
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://wave.webaim.org/extension/" rel="noopener noreferrer"&gt;WAVE&lt;/a&gt; is a free accessibility checker from WebAIM. It overlays visual indicators directly on the page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔴 Red icon = missing alt text (error)&lt;/li&gt;
&lt;li&gt;🟢 Green icon = alt text present&lt;/li&gt;
&lt;li&gt;Summary panel shows total error count&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install the Chrome or Firefox extension, navigate to any page, click the icon. Done. You get an instant visual map of every accessibility issue — not just alt text.&lt;/p&gt;

&lt;p&gt;I use WAVE when I want a broader accessibility check beyond just images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 4: Scan your entire site at once
&lt;/h2&gt;

&lt;p&gt;The methods above work great for individual pages. But if you're managing a site with hundreds or thousands of images, checking one page at a time isn't realistic.&lt;/p&gt;

&lt;p&gt;This is why I built &lt;a href="https://altaudit.com/blog/how-to-check-if-image-has-alt-text" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt;. It crawls your entire domain and flags every image that's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing an alt attribute entirely&lt;/li&gt;
&lt;li&gt;Has an empty alt where it shouldn't be&lt;/li&gt;
&lt;li&gt;Has alt text that's suspiciously short, long, or auto-generated (like &lt;code&gt;IMG_4823.jpg&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get a prioritized report so you can fix the worst issues first, and it can generate AI-powered alt text suggestions for the ones that need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing good alt text (once you find the gaps)
&lt;/h2&gt;

&lt;p&gt;Finding missing alt text is step one. Writing good replacements is step two. A few rules I follow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be specific, not generic.&lt;/strong&gt; "Golden retriever puppy playing in autumn leaves" beats "dog photo."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep it under 125 characters.&lt;/strong&gt; Screen readers may truncate longer text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skip "Image of" / "Photo of."&lt;/strong&gt; Screen readers already announce that it's an image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Match the context.&lt;/strong&gt; The same chart might need different alt text on a marketing page vs. a data report.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistakes I see constantly
&lt;/h2&gt;

&lt;p&gt;After auditing thousands of sites, these come up again and again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filenames as alt text — &lt;code&gt;banner-v2-final.png&lt;/code&gt; is not alt text&lt;/li&gt;
&lt;li&gt;Keyword stuffing — "best cheap shoes buy shoes online" helps no one and can hurt your SEO&lt;/li&gt;
&lt;li&gt;Same alt text on every image — screen reader users can't tell them apart&lt;/li&gt;
&lt;li&gt;No alt attribute at all — some CMS themes and plugins just don't add one&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Checking alt text is one of those small things that has an outsized impact — on accessibility, on SEO, and on the overall quality of your site. Start with DevTools for quick checks, use WAVE for page-level audits, and use a crawler like &lt;a href="https://altaudit.com/blog/how-to-check-if-image-has-alt-text" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt; when you need the full picture.&lt;/p&gt;

&lt;p&gt;If you want the complete walkthrough with screenshots and more detail, I wrote a longer version here: &lt;a href="https://altaudit.com/blog/how-to-check-if-image-has-alt-text" rel="noopener noreferrer"&gt;How to Check if an Image Has Alt Text (4 Easy Methods)&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What's your go-to method for checking alt text? I'd love to hear in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>a11y</category>
      <category>seo</category>
      <category>html</category>
    </item>
    <item>
      <title>Is Your Alt Text Actually Good? A Developer's Guide to Writing (and Checking) Descriptions That Work</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 16 Mar 2026 12:44:11 +0000</pubDate>
      <link>https://dev.to/proga100/is-your-alt-text-actually-good-a-developers-guide-to-writing-and-checking-descriptions-that-work-1oif</link>
      <guid>https://dev.to/proga100/is-your-alt-text-actually-good-a-developers-guide-to-writing-and-checking-descriptions-that-work-1oif</guid>
      <description>&lt;p&gt;You've added alt text. But is it any good?&lt;/p&gt;

&lt;p&gt;Most developers I talk to treat alt text as a binary thing: either the &lt;code&gt;alt&lt;/code&gt; attribute is there or it isn't. But the spec is more nuanced than that, and bad alt text — alt text that's technically present but useless — can be just as harmful as no alt text at all.&lt;/p&gt;

&lt;p&gt;This guide covers how to write effective alt text, how to evaluate what you've already got, and how to use a free checker to get instant quality scores.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Any Alt Text" Isn't Good Enough
&lt;/h2&gt;

&lt;p&gt;Here's a quick breakdown of common failure modes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Failure 1: Missing entirely --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"product-shot.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Failure 2: Filename as alt text (useless) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"IMG_2847.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"IMG_2847.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Failure 3: Generic descriptor (nearly useless) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"team.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Failure 4: "Image of" redundancy (screen readers already say "image") --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"ceo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Image of CEO"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Failure 5: Keyword stuffing (bad for everyone) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"shoe.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Nike shoe shoes footwear buy Nike cheap Nike shoes"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- What actually works --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"product-shot.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Black Nike Air Max 90 running shoes on white background, side view"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of those failures has a real impact. Screen reader users get confusing or no information. Search engines can't index the image content. Accessibility audits fail. Lawsuits cite them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alt Text Quality Scoring Framework
&lt;/h2&gt;

&lt;p&gt;Here's how I think about alt text quality — a framework you can apply yourself or automate:&lt;/p&gt;

&lt;h3&gt;
  
  
  Score: 0 — Missing or empty (for meaningful images)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"chart.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 0/100 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"chart.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 0/100 for meaningful image --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Empty alt text (&lt;code&gt;alt=""&lt;/code&gt;) is &lt;strong&gt;correct&lt;/strong&gt; for purely decorative images. It tells screen readers to skip the image. But for any image that conveys information, this is a critical failure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Score: 20-30 — Filename or generic label
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"DSC_0023.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"DSC_0023.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 20/100 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"team.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"photo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 25/100 --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better than nothing, barely. The field is filled but the value is meaningless to users and search engines alike.&lt;/p&gt;

&lt;h3&gt;
  
  
  Score: 40-50 — Generic but relevant
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"annual-report.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"report cover"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 45/100 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"team.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"team photo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 45/100 --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At least it's contextually relevant, but it doesn't describe what's actually in the image. Who's on the team? What does the report cover look like?&lt;/p&gt;

&lt;h3&gt;
  
  
  Score: 70-80 — Specific and descriptive
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"team.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Five engineers gathered around a whiteboard in a modern office"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 75/100 --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is passing. It describes who and what is visible. A screen reader user gets useful context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Score: 90-100 — Specific, contextual, appropriately concise
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"q4-results.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Bar chart showing 45% revenue increase in Q4 2024 compared to Q3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- 95/100 --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Describes subject, context, and relevant detail. Under 125 characters. No redundant phrases. This is the target.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Do's and Don'ts at a Glance
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ Be specific — describe what's actually visible&lt;/li&gt;
&lt;li&gt;✅ Keep it under 125 characters (screen readers may truncate longer text)&lt;/li&gt;
&lt;li&gt;✅ Include relevant context (who, what, where for people; data for charts)&lt;/li&gt;
&lt;li&gt;✅ Use natural language with relevant keywords where they fit organically&lt;/li&gt;
&lt;li&gt;✅ Use &lt;code&gt;alt=""&lt;/code&gt; for purely decorative images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Start with "Image of", "Photo of", "Picture of"&lt;/li&gt;
&lt;li&gt;❌ Use the filename as alt text&lt;/li&gt;
&lt;li&gt;❌ Repeat the surrounding text verbatim&lt;/li&gt;
&lt;li&gt;❌ Keyword stuff&lt;/li&gt;
&lt;li&gt;❌ Leave it blank for meaningful images&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alt Text by Image Type
&lt;/h2&gt;

&lt;p&gt;Different images need different approaches:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Image type&lt;/th&gt;
&lt;th&gt;What to describe&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Product photo&lt;/td&gt;
&lt;td&gt;Color, type, key features, angle/background&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Person / headshot&lt;/td&gt;
&lt;td&gt;Name (if known), role/context, setting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data chart / graph&lt;/td&gt;
&lt;td&gt;Chart type, key finding or trend, time period&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Screenshot&lt;/td&gt;
&lt;td&gt;What UI is shown, what action is being demonstrated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logo&lt;/td&gt;
&lt;td&gt;Brand name + "logo"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decorative&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;alt=""&lt;/code&gt; — no description needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infographic&lt;/td&gt;
&lt;td&gt;Summarize the key information conveyed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Button/icon image&lt;/td&gt;
&lt;td&gt;The action the button performs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to Check Your Existing Alt Text
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1 — Browser DevTools (manual)
&lt;/h3&gt;

&lt;p&gt;Right-click any image → Inspect → look for the &lt;code&gt;alt&lt;/code&gt; attribute in the HTML:&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="c1"&gt;// Check all images on a page with console one-liner&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;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="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hasAlt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt; &lt;span class="o"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gets tedious fast for large pages. And it only checks the current page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2 — Free Alt Text Checker (instant quality score)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://altaudit.com/free-alt-text-checker" rel="noopener noreferrer"&gt;Alt Audit's free alt text checker&lt;/a&gt; lets you paste any existing alt text and get an instant quality score with specific feedback:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Length check (is it too short, too long, or just right?)&lt;/li&gt;
&lt;li&gt;Redundancy detection (does it start with "image of"?)&lt;/li&gt;
&lt;li&gt;Filename detection (is it just a filename?)&lt;/li&gt;
&lt;li&gt;Descriptiveness scoring (does it have enough words to be meaningful?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also gives a &lt;strong&gt;suggested improvement&lt;/strong&gt; when the score is below 70, so you're not just told what's wrong — you get direction on how to fix it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3 — AI Generation for New or Missing Alt Text
&lt;/h3&gt;

&lt;p&gt;If you have images with no alt text at all, manually checking won't help — you need to generate from scratch. The same tool offers AI-powered generation: upload an image and get an auto-generated, quality alt text description based on what's actually in the image.&lt;/p&gt;

&lt;p&gt;Free tier includes 25 AI-generated alt texts per month, no credit card required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Alt Text Into Your Dev Workflow
&lt;/h2&gt;

&lt;p&gt;The real fix isn't one-time cleanup — it's making good alt text the default:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;alt&lt;/code&gt; attribute as a required field in your CMS or component system&lt;/li&gt;
&lt;li&gt;Lint HTML in your CI/CD for missing &lt;code&gt;alt&lt;/code&gt; attributes:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Using axe-core CLI&lt;/span&gt;
npx axe https://yoursite.com &lt;span class="nt"&gt;--rules&lt;/span&gt; image-alt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For content teams:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an alt text style guide with examples by image type&lt;/li&gt;
&lt;li&gt;Make alt text a required field in your media upload workflow&lt;/li&gt;
&lt;li&gt;Review AI-generated alt text before publish for brand or data-sensitive images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For agencies:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include an alt text audit in every site deliverable&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://altaudit.com/free-alt-text-checker" rel="noopener noreferrer"&gt;Alt Audit's site scanner&lt;/a&gt; to generate a compliance report for clients&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Alt text quality exists on a spectrum. Empty is not the same as bad, and bad is not the same as good. The goal is &lt;strong&gt;specific, concise, and contextual&lt;/strong&gt; — describing what's actually in the image in a way that serves both screen reader users and search engines.&lt;/p&gt;

&lt;p&gt;If you're unsure where your current alt text stands, start with the &lt;a href="https://altaudit.com/free-alt-text-checker" rel="noopener noreferrer"&gt;free alt text checker&lt;/a&gt;. Paste in a description, get a quality score, and see exactly what to improve. It takes 30 seconds and you might be surprised by what you find.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post was originally published on &lt;a href="https://altaudit.com/free-alt-text-checker" rel="noopener noreferrer"&gt;Alt Audit — Free Alt Text Checker&lt;/a&gt;. Get 25 free AI-generated alt texts per month with a free account.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>seo</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Automated Alt Text for 10,000 WordPress Images — Here's What I Learned</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 16 Mar 2026 12:36:23 +0000</pubDate>
      <link>https://dev.to/proga100/i-automated-alt-text-for-10000-wordpress-images-heres-what-i-learned-1389</link>
      <guid>https://dev.to/proga100/i-automated-alt-text-for-10000-wordpress-images-heres-what-i-learned-1389</guid>
      <description>&lt;p&gt;WordPress powers 43% of the internet. And roughly 43% of those sites have the same problem: a media library full of images with no alt text, empty alt attributes, or filenames like &lt;code&gt;IMG_2847.jpg&lt;/code&gt; passed off as descriptions.&lt;/p&gt;

&lt;p&gt;I've been there. Working across agency client sites, I've stared down libraries of 5,000, 10,000, even 30,000 images — all needing alt text. Here's what I've learned about doing it efficiently without sacrificing quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Alt Text Is a Real Problem (Not Just a Compliance Checkbox)
&lt;/h2&gt;

&lt;p&gt;Let's be honest about what's actually at stake:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessibility&lt;/strong&gt;: Screen readers read the &lt;code&gt;alt&lt;/code&gt; attribute aloud. An empty or missing alt attribute means a user relying on a screen reader gets absolutely nothing. On an image-heavy site — eCommerce, photography, news — that's a broken experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SEO&lt;/strong&gt;: Google can't see images. It reads alt text. Descriptive alt text is how your images get indexed and ranked in image search. A site with 5,000 images and no alt text has 5,000 missed SEO opportunities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Legal risk&lt;/strong&gt;: ADA lawsuits targeting inaccessible websites are rising year over year. Missing alt text on meaningful images is consistently cited in demand letters and complaints.&lt;/p&gt;

&lt;h2&gt;
  
  
  The WordPress Alt Text Problem Is Structural
&lt;/h2&gt;

&lt;p&gt;WordPress stores four text fields per image in the media library: title, caption, description, and &lt;strong&gt;alt text&lt;/strong&gt;. The alt text field is the only one that maps to the HTML &lt;code&gt;alt&lt;/code&gt; attribute that assistive technologies and search engines actually use.&lt;/p&gt;

&lt;p&gt;But here's the structural problem: &lt;strong&gt;WordPress never auto-fills alt text.&lt;/strong&gt; When you upload an image, the alt text field is blank. If you don't fill it in manually, it stays blank.&lt;/p&gt;

&lt;p&gt;For a site uploading 50 images a week, that's 2,600 images per year added with no alt text. After five years? You're not fighting a backlog — you're fighting an archive.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Approached Automation
&lt;/h2&gt;

&lt;p&gt;After trying several approaches, the workflow that actually scales looks like this:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Audit First
&lt;/h3&gt;

&lt;p&gt;Before generating anything, you need to know what you're dealing with. How many images are missing alt text? What percentage have empty strings vs. filenames vs. real descriptions that just need improvement?&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;# Quick approach: search your DB for empty alt text&lt;/span&gt;
SELECT pm.post_id, pm.meta_value 
FROM wp_postmeta pm
WHERE pm.meta_key &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'_wp_attachment_image_alt'&lt;/span&gt;
AND &lt;span class="o"&gt;(&lt;/span&gt;pm.meta_value &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; OR pm.meta_value IS NULL&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But running raw DB queries is clunky for non-developers, and doesn't give you a visual overview. I ended up using &lt;a href="https://altaudit.com/wordpress-alt-text-plugin" rel="noopener noreferrer"&gt;Alt Audit's WordPress plugin&lt;/a&gt; for this — it scans the full media library and gives you a dashboard of missing, empty, and inadequate alt text across all images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Bulk Generation
&lt;/h3&gt;

&lt;p&gt;Once you know the scope, you need to generate alt text at scale. The important distinction here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation on upload&lt;/strong&gt; — Good for keeping up with new content. New images get auto-generated alt text when they're uploaded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bulk retroactive generation&lt;/strong&gt; — Critical for the existing backlog. Select all images missing alt text, run AI generation in batch, review and apply.&lt;/p&gt;

&lt;p&gt;The AI engine in &lt;a href="https://altaudit.com/wordpress-alt-text-plugin" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt; uses Google Gemini Vision to analyze each image and generate contextually accurate descriptions. For a batch of 500 images, the process takes minutes rather than hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Review Before Applying
&lt;/h3&gt;

&lt;p&gt;Not everything should go live unreviewed. AI vision models are excellent at general images (products, people, illustrations) but can struggle with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technical diagrams or charts with specific data labels&lt;/li&gt;
&lt;li&gt;Images with embedded text (infographics, screenshots)&lt;/li&gt;
&lt;li&gt;Brand-specific or context-dependent images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My rule: bulk-apply for the long tail (products, stock photos, banners), review manually for editorial and data-heavy images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 — Set Up Ongoing Automation
&lt;/h3&gt;

&lt;p&gt;Once the backlog is cleared, set up automatic alt text generation on upload. Every new image gets a description from day one. The backlog never grows back.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alt Audit WordPress Plugin — Setup in 5 Minutes
&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;# Install via WP CLI&lt;/span&gt;
wp plugin &lt;span class="nb"&gt;install &lt;/span&gt;alt-audit &lt;span class="nt"&gt;--activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or search "Alt Audit" in the WordPress plugin directory and activate with one click.&lt;/p&gt;

&lt;p&gt;After activation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a free account at altaudit.com (25 AI credits/month, no card needed)&lt;/li&gt;
&lt;li&gt;Copy your API key and paste it in the plugin settings&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Media → Alt Audit Scanner&lt;/strong&gt; to run your first scan&lt;/li&gt;
&lt;li&gt;Select images with missing alt text and click &lt;strong&gt;Generate Alt Text&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Review the suggestions and click &lt;strong&gt;Apply&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. The plugin handles the rest — including rule-based fallback generation for images where AI isn't needed (logos, icons, structural images).&lt;/p&gt;

&lt;h2&gt;
  
  
  Alt Text Quality: What "Good" Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;The goal isn't just filling the field — it's writing descriptions that actually help users and search engines.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Image type&lt;/th&gt;
&lt;th&gt;Bad alt text&lt;/th&gt;
&lt;th&gt;Good alt text&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Product photo&lt;/td&gt;
&lt;td&gt;&lt;code&gt;blue-headphones.jpg&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Blue wireless over-ear headphones with cushioned ear pads on white background&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team photo&lt;/td&gt;
&lt;td&gt;&lt;code&gt;team&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Four engineers standing in front of a server rack at Alt Audit's London office&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chart&lt;/td&gt;
&lt;td&gt;&lt;code&gt;chart-2024.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Bar chart showing 45% increase in organic search traffic from January to December 2024&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decorative banner&lt;/td&gt;
&lt;td&gt;&lt;code&gt;banner&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(should be &lt;code&gt;alt=""&lt;/code&gt;)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The magic number: &lt;strong&gt;aim for 10–150 characters&lt;/strong&gt;, describe the subject and context, skip "image of" or "photo of" (screen readers already say that).&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing WordPress Alt Text Approaches
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Quality&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Manual writing&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;4+ hrs/100 images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Yoast SEO&lt;/td&gt;
&lt;td&gt;Reminder only&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Still manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Engine plugin&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;~30 min/100 images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alt Audit&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;~5 min/100 images&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Alt text at scale is a solved problem in 2026. AI vision models are accurate enough for the vast majority of WordPress images, and the tooling to automate bulk generation has matured significantly.&lt;/p&gt;

&lt;p&gt;The bottleneck isn't technical anymore — it's awareness. Most sites don't have a systematic approach to alt text, and it shows in their accessibility scores and image search rankings.&lt;/p&gt;

&lt;p&gt;If you're managing a WordPress site and haven't audited your media library lately, start there. You'll probably find thousands of images that need attention. The &lt;a href="https://altaudit.com/wordpress-alt-text-plugin" rel="noopener noreferrer"&gt;Alt Audit plugin&lt;/a&gt; (free tier available) is a solid starting point for the audit and the fix.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post was originally published on &lt;a href="https://altaudit.com/wordpress-alt-text-plugin" rel="noopener noreferrer"&gt;Alt Audit — WordPress Alt Text Plugin&lt;/a&gt;. Free plan includes 25 AI credits/month. No credit card required.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>a11y</category>
      <category>seo</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Get Your Website WCAG 2.2 Compliant (Without Losing Your Mind)</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 16 Mar 2026 12:29:28 +0000</pubDate>
      <link>https://dev.to/proga100/how-to-get-your-website-wcag-22-compliant-without-losing-your-mind-565j</link>
      <guid>https://dev.to/proga100/how-to-get-your-website-wcag-22-compliant-without-losing-your-mind-565j</guid>
      <description>&lt;p&gt;Here's a stat that should make every developer pause: &lt;strong&gt;96% of websites have detectable WCAG failures.&lt;/strong&gt; Not some websites — nearly all of them.&lt;/p&gt;

&lt;p&gt;And the #1 culprit? Missing alt text on images.&lt;/p&gt;

&lt;p&gt;If your site is in that 96%, you're not just failing an accessibility audit — you're potentially exposed to ADA lawsuits, locking out 1 billion+ users with disabilities, and leaving SEO value on the table. The good news: WCAG compliance is way more achievable than it sounds, especially with the right tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Is WCAG 2.2?
&lt;/h2&gt;

&lt;p&gt;WCAG (Web Content Accessibility Guidelines) is the international standard for web accessibility, published by the W3C. Version 2.2, released in 2023, added 9 new success criteria to an already comprehensive spec.&lt;/p&gt;

&lt;p&gt;There are three conformance levels:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;th&gt;Required by?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bare minimum — alt text, keyboard nav, no seizure content&lt;/td&gt;
&lt;td&gt;Everyone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Legal standard in most countries&lt;/td&gt;
&lt;td&gt;ADA, EAA, EN 301 549&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AAA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Best practice for government/public sector&lt;/td&gt;
&lt;td&gt;Recommended only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If your site serves users in the US, EU, or UK, &lt;strong&gt;WCAG 2.1/2.2 AA is what you need to target.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The 4 Pillars Every Dev Needs to Know (POUR)
&lt;/h2&gt;

&lt;p&gt;Every WCAG criterion maps to one of four principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Perceivable&lt;/strong&gt; — Can users receive the content? (alt text, captions, color contrast)&lt;/li&gt;
&lt;li&gt;⌨️ &lt;strong&gt;Operable&lt;/strong&gt; — Can users interact with it? (keyboard navigation, focus indicators, no time traps)&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Understandable&lt;/strong&gt; — Is it clear? (plain language, predictable UI, helpful error messages)&lt;/li&gt;
&lt;li&gt;🛠️ &lt;strong&gt;Robust&lt;/strong&gt; — Does it work with assistive tech? (valid HTML, proper ARIA, screen reader support)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Most Common WCAG Failures (Fix These First)
&lt;/h2&gt;

&lt;p&gt;You don't need to boil the ocean. Start with the issues that affect the most users:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 🖼️ Missing Alt Text (WCAG 1.1.1)
&lt;/h3&gt;

&lt;p&gt;The single most common failure. Every meaningful image needs a descriptive &lt;code&gt;alt&lt;/code&gt; attribute. Empty &lt;code&gt;alt=""&lt;/code&gt; is correct only for decorative images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Bad --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"team-photo.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Also bad --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"team-photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Good --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"team-photo.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Five engineers collaborating around a whiteboard at Alt Audit HQ"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. 🎨 Insufficient Color Contrast (WCAG 1.4.3)
&lt;/h3&gt;

&lt;p&gt;Normal text must have a contrast ratio of at least &lt;strong&gt;4.5:1&lt;/strong&gt; against its background. Large text (18pt+) needs &lt;strong&gt;3:1&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 🖱️ Keyboard Inaccessibility (WCAG 2.1.1)
&lt;/h3&gt;

&lt;p&gt;Every interactive element — buttons, links, dropdowns, modals — must be reachable and operable via keyboard alone. Tab through your site right now. Can you reach everything?&lt;/p&gt;

&lt;h3&gt;
  
  
  4. 🏷️ Missing Form Labels (WCAG 1.3.1)
&lt;/h3&gt;

&lt;p&gt;Every &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; needs a programmatically associated &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt;. Placeholder text alone does not count.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 🔗 Non-Descriptive Links (WCAG 2.4.4)
&lt;/h3&gt;

&lt;p&gt;Links that say "click here" or "read more" are useless to screen reader users who navigate by tab. Use descriptive text: "Read the WCAG 2.2 compliance guide."&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Run a WCAG Compliance Check
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Automated scanning (catches ~30–40% of issues)
&lt;/h3&gt;

&lt;p&gt;Use these tools to get a baseline fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://altaudit.com/wcag-compliance" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt;&lt;/strong&gt; — Scans your entire site for WCAG failures, with special focus on alt text (the #1 failure). Generates AI-powered fixes in bulk. Free plan available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;axe DevTools&lt;/strong&gt; — Browser extension that highlights violations in DevTools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lighthouse&lt;/strong&gt; (Chrome) — Built-in audit with accessibility scoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WAVE&lt;/strong&gt; — Visual overlay tool for accessibility errors&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Manual testing (catches the other 60–70%)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tab through the entire page — can you reach everything?&lt;/li&gt;
&lt;li&gt;Use VoiceOver (Mac/iOS) or NVDA (Windows) for a real screen reader experience&lt;/li&gt;
&lt;li&gt;Test at 200% zoom — does content reflow without horizontal scrolling?&lt;/li&gt;
&lt;li&gt;Check every form for labels and error messages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Practical WCAG 2.2 Compliance Checklist
&lt;/h2&gt;

&lt;p&gt;Here's a quick checklist for WCAG 2.2 AA:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Images &amp;amp; Media&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] All meaningful images have descriptive alt text&lt;/li&gt;
&lt;li&gt;[ ] Decorative images have &lt;code&gt;alt=""&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Videos have captions and audio descriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keyboard &amp;amp; Navigation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] All interactive elements are keyboard accessible&lt;/li&gt;
&lt;li&gt;[ ] Visible focus indicator on all focusable elements&lt;/li&gt;
&lt;li&gt;[ ] Skip navigation link at the top of the page&lt;/li&gt;
&lt;li&gt;[ ] No keyboard traps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Forms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] All inputs have associated labels&lt;/li&gt;
&lt;li&gt;[ ] Error messages are clear and descriptive&lt;/li&gt;
&lt;li&gt;[ ] Required fields are indicated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Visual&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Text contrast ratio ≥ 4.5:1 (normal text)&lt;/li&gt;
&lt;li&gt;[ ] Text contrast ratio ≥ 3:1 (large text)&lt;/li&gt;
&lt;li&gt;[ ] Text can be resized to 200% without loss of functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;New in WCAG 2.2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Dragging actions have pointer alternatives&lt;/li&gt;
&lt;li&gt;[ ] Target size ≥ 24×24 CSS pixels for interactive elements&lt;/li&gt;
&lt;li&gt;[ ] Focus not obscured by sticky headers/footers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Alt Text Problem at Scale
&lt;/h2&gt;

&lt;p&gt;Fixing one image is easy. Fixing 5,000? That's where most sites get stuck.&lt;/p&gt;

&lt;p&gt;If you're running a WordPress site, a large content platform, or managing multiple client sites, you need &lt;strong&gt;automated alt text generation at scale&lt;/strong&gt;. Tools like &lt;a href="https://altaudit.com/wcag-compliance" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt; can scan your entire site, identify every image with missing or inadequate alt text, and generate WCAG-compliant descriptions using AI — all in one workflow.&lt;/p&gt;

&lt;p&gt;The output? A full compliance report you can download and share with clients or stakeholders.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR — Start Here
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run an automated scan&lt;/strong&gt; — Find out where you stand in minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix alt text first&lt;/strong&gt; — It's the #1 failure and the easiest win&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix keyboard navigation&lt;/strong&gt; — Tab through your site and document every gap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix color contrast&lt;/strong&gt; — Run your palette through a contrast checker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual test with a screen reader&lt;/strong&gt; — Nothing replaces real assistive tech testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document and retest&lt;/strong&gt; — Accessibility is ongoing, not a checkbox&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal isn't perfection on day one. It's making meaningful progress, building accessible habits into your dev workflow, and not being the team that gets a lawsuit because nobody checked if the contact form had labels.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://altaudit.com/wcag-compliance" rel="noopener noreferrer"&gt;Alt Audit — WCAG Compliance Tool&lt;/a&gt;. Alt Audit helps developers and agencies run automated WCAG compliance checks and fix alt text at scale.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wcag</category>
      <category>a11y</category>
      <category>webdev</category>
      <category>seo</category>
    </item>
    <item>
      <title>Best WordPress Alt Text Generator Plugins in 2026 (Compared)</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 16 Mar 2026 12:03:51 +0000</pubDate>
      <link>https://dev.to/proga100/best-wordpress-alt-text-generator-plugins-in-2026-compared-4m52</link>
      <guid>https://dev.to/proga100/best-wordpress-alt-text-generator-plugins-in-2026-compared-4m52</guid>
      <description>&lt;p&gt;WordPress powers over 43% of all websites on the internet — and the vast majority of them have an alt text problem. Manually writing alt text for every image is time-consuming, tedious, and easy to forget. The result? Thousands of images with no alt text, empty attributes, or unhelpful defaults like the filename.&lt;/p&gt;

&lt;p&gt;This hurts both &lt;strong&gt;SEO&lt;/strong&gt; (search engines can't index images properly) and &lt;strong&gt;accessibility&lt;/strong&gt; (screen reader users get no useful context).&lt;/p&gt;

&lt;p&gt;The good news: AI-powered WordPress alt text generator plugins now make it possible to automatically generate accurate, descriptive alt text for your entire image library — in minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Look for in a WordPress Alt Text Plugin
&lt;/h2&gt;

&lt;p&gt;Not all alt text plugins are created equal. Key criteria to evaluate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI quality&lt;/strong&gt; — Does it use a capable vision AI that produces accurate, context-aware descriptions?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulk processing&lt;/strong&gt; — Can it handle your existing image library, not just new uploads?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overwrite control&lt;/strong&gt; — Can you choose whether to overwrite existing alt text or only fill in missing ones?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual support&lt;/strong&gt; — Can it generate alt text in multiple languages for international sites?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt; — Can you set tone, style, or keyword focus?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WooCommerce compatibility&lt;/strong&gt; — Does it handle product images correctly?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WCAG compliance focus&lt;/strong&gt; — Does it help meet accessibility standards, not just fill in text?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Top WordPress Alt Text Generator Options in 2026
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Alt Audit (API Integration)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://altaudit.com" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt; is a dedicated accessibility and alt text platform that integrates with WordPress via its API. Unlike a traditional plugin, Alt Audit gives you a full dashboard to scan your site, review every image, and generate AI-powered alt text — with full control over what gets published.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Full-site scanning across all WordPress pages and posts&lt;/li&gt;
&lt;li&gt;AI-generated alt text using advanced vision models&lt;/li&gt;
&lt;li&gt;Bulk fix capabilities — update hundreds of images at once&lt;/li&gt;
&lt;li&gt;Detailed reporting showing missing, empty, or inadequate alt text&lt;/li&gt;
&lt;li&gt;Multilingual alt text generation for international sites&lt;/li&gt;
&lt;li&gt;WCAG compliance-focused — built specifically for accessibility, not just SEO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideal for agencies, developers, and site owners who want a professional-grade solution with full auditability.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Yoast SEO (Basic Alt Text Reminders)
&lt;/h3&gt;

&lt;p&gt;Yoast SEO is one of the most popular WordPress plugins overall. It includes basic alt text prompts in its content analysis — flagging images that are missing alt text and reminding you to add them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;However&lt;/strong&gt;, Yoast does not automatically generate alt text. For large sites or media libraries, you're still writing alt text manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Imagify / ShortPixel (Optimization-First)
&lt;/h3&gt;

&lt;p&gt;Image optimization plugins like Imagify and ShortPixel focus primarily on compressing and converting images for performance. Some have begun adding basic alt text features, but their core competency is not AI-generated descriptions.&lt;/p&gt;

&lt;p&gt;Worth using alongside a dedicated alt text tool, but not as a primary solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. AI Engine (ChatGPT-Powered)
&lt;/h3&gt;

&lt;p&gt;AI Engine is a popular WordPress plugin leveraging OpenAI's API for content generation tasks, including alt text. It can generate alt text on upload and offers some bulk processing.&lt;/p&gt;

&lt;p&gt;Output quality depends on the model and prompt configuration — some technical setup required. A flexible option for developers comfortable with API configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Automatically Generate Alt Text for Existing WordPress Images
&lt;/h2&gt;

&lt;p&gt;Most WordPress sites have hundreds or thousands of images already uploaded with no alt text. Here's the general workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit your existing library&lt;/strong&gt; — Identify how many images are currently missing alt text (tools like Alt Audit can give you a complete count instantly)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose your generation tool&lt;/strong&gt; — Select a plugin or platform that supports bulk alt text generation for existing media&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure preferences&lt;/strong&gt; — Set your preferred language, tone, and any keywords to incorporate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review before publishing&lt;/strong&gt; — For brand-sensitive images, review AI-generated text before applying&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply in bulk&lt;/strong&gt; — Run the bulk update to populate missing alt text across your library&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor going forward&lt;/strong&gt; — Set up automatic generation for future uploads&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Alt Text vs. Image Title in WordPress: What's the Difference?
&lt;/h2&gt;

&lt;p&gt;WordPress stores several text fields for each image:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alt text&lt;/strong&gt; — Exposed to screen readers via the &lt;code&gt;alt&lt;/code&gt; attribute in HTML ✅&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Title&lt;/strong&gt; — NOT read by screen readers by default ❌&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caption&lt;/strong&gt; — Displayed below images, not the same as alt text ❌&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt; — Used internally in the media library ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure your alt text plugin is updating the &lt;strong&gt;correct field&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does Auto-Generated Alt Text Meet WCAG Standards?
&lt;/h2&gt;

&lt;p&gt;Modern vision AI models can produce accurate, contextually appropriate descriptions for most image types. Edge cases where human review is recommended:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly specialized technical diagrams&lt;/li&gt;
&lt;li&gt;Images with embedded text&lt;/li&gt;
&lt;li&gt;Complex infographics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For everyday images (product photos, team headshots, blog illustrations, banners), AI-generated alt text from a quality tool will meet &lt;strong&gt;WCAG 1.1.1 Level A&lt;/strong&gt; requirements. The key is using a tool that generates real, meaningful descriptions rather than short, generic labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started with Alt Text Automation
&lt;/h2&gt;

&lt;p&gt;If your WordPress site has images without alt text, every day you wait is a day those images are invisible to screen readers and search engines. Automated alt text generation has never been more accessible or accurate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://altaudit.com/wordpress-alt-text-plugin" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt; helps WordPress site owners and agencies identify every image with missing or inadequate alt text and fix them at scale with AI — achieving WCAG compliance faster and improving image SEO at the same time.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://altaudit.com/blog/best-wordpress-alt-text-generator-plugins-in-2026-compared" rel="noopener noreferrer"&gt;altaudit.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>a11y</category>
      <category>seo</category>
      <category>webdev</category>
    </item>
    <item>
      <title>WCAG Audit: A Complete Guide to Testing and Fixing Web Accessibility</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 16 Mar 2026 11:59:24 +0000</pubDate>
      <link>https://dev.to/proga100/wcag-audit-a-complete-guide-to-testing-and-fixing-web-accessibility-2mc1</link>
      <guid>https://dev.to/proga100/wcag-audit-a-complete-guide-to-testing-and-fixing-web-accessibility-2mc1</guid>
      <description>&lt;p&gt;A WCAG audit is a systematic evaluation of your website to determine how well it conforms to the Web Content Accessibility Guidelines (WCAG) — the globally recognized standards published by the W3C for making digital content accessible to people with disabilities.&lt;/p&gt;

&lt;p&gt;Whether you're a developer, designer, or business owner, conducting a WCAG audit is one of the most important steps toward building an inclusive digital experience and staying compliant with laws like the ADA, Section 508, and the European Accessibility Act (EAA).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why WCAG Audits Matter
&lt;/h2&gt;

&lt;p&gt;Over 1 billion people worldwide live with some form of disability. When websites aren't accessible, these users are excluded from information and services. Beyond ethics, there are strong legal and business reasons to audit regularly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Legal compliance&lt;/strong&gt;: Failing to meet accessibility standards can result in lawsuits and fines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wider reach&lt;/strong&gt;: Accessible sites serve more users, including older adults and those with temporary disabilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better SEO&lt;/strong&gt;: Alt text, proper headings, and descriptive links also improve search rankings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved UX&lt;/strong&gt;: Accessibility improvements benefit all users&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding WCAG Levels: A, AA, and AAA
&lt;/h2&gt;

&lt;p&gt;WCAG is organized into three conformance levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Level A&lt;/strong&gt;: Minimum baseline — absolute essentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level AA&lt;/strong&gt;: Required by most laws (ADA, EAA) — the standard target for most organizations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level AAA&lt;/strong&gt;: Highest level — not typically required by law but recommended for specialized use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most audits target &lt;strong&gt;WCAG 2.1 AA&lt;/strong&gt; or &lt;strong&gt;WCAG 2.2 AA&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Principles of WCAG (POUR)
&lt;/h2&gt;

&lt;p&gt;Every WCAG success criterion falls under one of four core principles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Perceivable&lt;/strong&gt; — Content must be presented in ways users can perceive (e.g., alt text for images, captions for video)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operable&lt;/strong&gt; — UI must be operable (e.g., keyboard accessibility, no seizure-inducing content)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understandable&lt;/strong&gt; — Content must be understandable (e.g., clear language, predictable navigation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust&lt;/strong&gt; — Content must work with assistive technologies (e.g., valid HTML, ARIA attributes)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Conduct a WCAG Audit: Step-by-Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Scope
&lt;/h3&gt;

&lt;p&gt;Decide which pages to audit. Prioritize high-traffic pages, checkout flows, contact forms, and critical user journeys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Use Automated Scanning Tools
&lt;/h3&gt;

&lt;p&gt;Automated tools can catch around 30–40% of WCAG issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alt Audit&lt;/strong&gt; — Detects missing or inadequate alt text across your entire site&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;axe DevTools&lt;/strong&gt; — Browser extension catching a wide range of WCAG issues in your dev workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WAVE&lt;/strong&gt; — Free visual tool that overlays accessibility errors on your live site&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lighthouse&lt;/strong&gt; — Built into Chrome DevTools, provides an accessibility score with recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Perform Manual Testing
&lt;/h3&gt;

&lt;p&gt;Manual testing uncovers what automation misses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard navigation&lt;/strong&gt; — Can every element be reached and used with only a keyboard?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screen reader testing&lt;/strong&gt; — Use NVDA, JAWS, or VoiceOver to verify content is read correctly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Color contrast&lt;/strong&gt; — Ensure text meets minimum ratios (4.5:1 for normal text, 3:1 for large text)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Form accessibility&lt;/strong&gt; — All inputs should have proper labels, error messages, and instructions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus indicators&lt;/strong&gt; — Visible focus states must be present for all interactive elements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Document Your Findings
&lt;/h3&gt;

&lt;p&gt;Create a detailed audit report covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each issue found&lt;/li&gt;
&lt;li&gt;The WCAG criterion it violates&lt;/li&gt;
&lt;li&gt;The severity level (critical, major, minor)&lt;/li&gt;
&lt;li&gt;Recommended remediation steps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Remediate and Retest
&lt;/h3&gt;

&lt;p&gt;Work through findings systematically, starting with the most critical issues. Retest after each fix to confirm resolution and check for regressions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common WCAG Failures to Watch For
&lt;/h2&gt;

&lt;p&gt;These are the most frequently encountered accessibility failures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing or empty alt text on images&lt;/li&gt;
&lt;li&gt;Insufficient color contrast&lt;/li&gt;
&lt;li&gt;Form inputs without associated labels&lt;/li&gt;
&lt;li&gt;Non-descriptive link text ("click here", "read more")&lt;/li&gt;
&lt;li&gt;Videos without captions or transcripts&lt;/li&gt;
&lt;li&gt;Pages that can't be navigated by keyboard&lt;/li&gt;
&lt;li&gt;Missing skip navigation links&lt;/li&gt;
&lt;li&gt;Inaccessible PDF documents&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Often Should You Audit?
&lt;/h2&gt;

&lt;p&gt;Accessibility is an ongoing commitment, not a one-time fix. Best practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conduct a full audit &lt;strong&gt;at least once a year&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Audit after significant changes (redesigns, new templates, major feature launches)&lt;/li&gt;
&lt;li&gt;Integrate automated scanning into your CI/CD pipeline to catch regressions early&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Start Your WCAG Audit Today
&lt;/h2&gt;

&lt;p&gt;A WCAG audit is the foundation of any serious accessibility program. By identifying and fixing barriers on your website, you protect your organization from legal risk and create a better experience for every visitor.&lt;/p&gt;

&lt;p&gt;One of the most common and impactful WCAG failures is missing or inadequate alt text. Tools like &lt;a href="https://altaudit.com" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt; make it easy to scan your entire site, identify images with missing alt text, and fix them at scale with AI.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://altaudit.com/blog/wcag-audit-a-complete-guide-to-testing-and-fixing-web-accessibility" rel="noopener noreferrer"&gt;altaudit.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>wcag</category>
      <category>webdev</category>
      <category>seo</category>
    </item>
    <item>
      <title>Stop Writing Alt Text Manually: How AI Is Changing Image SEO Forever</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Tue, 03 Mar 2026 18:05:19 +0000</pubDate>
      <link>https://dev.to/proga100/stop-writing-alt-text-manually-how-ai-is-changing-image-seo-forever-4gh4</link>
      <guid>https://dev.to/proga100/stop-writing-alt-text-manually-how-ai-is-changing-image-seo-forever-4gh4</guid>
      <description>&lt;p&gt;If you've ever stared at a WordPress media library with thousands of images — all missing alt text — you know the feeling. It's somewhere between &lt;em&gt;"I should fix this"&lt;/em&gt; and &lt;em&gt;"this is going to take forever."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You're not wrong on either count.&lt;/p&gt;

&lt;p&gt;Alt text isn't optional. It's the bridge between your images and the people (and bots) who can't see them. Get it right, and you boost your SEO, pass accessibility audits, and make your site usable for everyone. Get it wrong — or skip it entirely — and you're leaving real value on the table.&lt;/p&gt;

&lt;p&gt;The good news? You no longer have to do it manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Alt Text Actually Matters
&lt;/h2&gt;

&lt;p&gt;When a screen reader encounters an image on your page, it reads the alt text aloud. If that field is empty, the user gets nothing — or worse, a garbled filename like &lt;code&gt;IMG_20231104_152301.jpg&lt;/code&gt;. That's not just unhelpful; it's a barrier.&lt;/p&gt;

&lt;p&gt;For search engines, it's a similar story. Google can't "see" your images the way a human can. Alt text is how you tell it: &lt;em&gt;here's what this image shows, and here's why it matters on this page.&lt;/em&gt; Without it, your images are essentially invisible to Google Image Search.&lt;/p&gt;

&lt;p&gt;There's also a legal angle that's getting harder to ignore. &lt;strong&gt;WCAG 2.1 Level A&lt;/strong&gt; (Success Criterion 1.1.1) requires non-text content to have a text alternative. The EU's European Accessibility Act came into effect in June 2025. Similar legislation is expanding in the US and UK. The question isn't &lt;em&gt;if&lt;/em&gt; you'll need to fix your alt text — it's &lt;em&gt;when&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Manual Approach Doesn't Scale
&lt;/h2&gt;

&lt;p&gt;For a site with 50 images, manual alt text is manageable. For 5,000? It becomes a project. For 50,000? A crisis.&lt;/p&gt;

&lt;p&gt;Here's what it actually looks like in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crawl your site to identify missing or weak alt text&lt;/li&gt;
&lt;li&gt;Open each image one by one in the media library&lt;/li&gt;
&lt;li&gt;Write a description, weave in a keyword, save&lt;/li&gt;
&lt;li&gt;Repeat hundreds (or thousands) of times&lt;/li&gt;
&lt;li&gt;New images get uploaded next week — cycle restarts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not that it can't be done. It's that it &lt;em&gt;shouldn't&lt;/em&gt; have to be done this way.&lt;/p&gt;




&lt;h2&gt;
  
  
  What AI-Powered Alt Text Generation Actually Does
&lt;/h2&gt;

&lt;p&gt;Modern AI doesn't just slap a generic label on your image. Good tools use computer vision to analyze the actual content — objects, scenes, context — and generate natural language descriptions that read like something a human wrote.&lt;/p&gt;

&lt;p&gt;The rough process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Image recognition&lt;/strong&gt; — identifies what's in the image: a product, person, landscape, diagram&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context awareness&lt;/strong&gt; — factors in surrounding data like page title, product name, or focus keyword&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural language generation&lt;/strong&gt; — turns those observations into a coherent, useful description&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result isn't perfect 100% of the time, but it gets you 80-90% of the way there. That's the difference between a months-long project and an afternoon.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Alt Audit Handles This (And Why the Free Tier Is Genuinely Free)
&lt;/h2&gt;

&lt;p&gt;Most alt text tools make you choose: pay for AI, or do it yourself. &lt;a href="https://altaudit.com" rel="noopener noreferrer"&gt;Alt Audit&lt;/a&gt; takes a different approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule-Based Generation: Free, Unlimited, Offline
&lt;/h3&gt;

&lt;p&gt;The core engine is &lt;strong&gt;rule-based generation&lt;/strong&gt; — completely free, works entirely on your server, no API key, no external service, no monthly subscription.&lt;/p&gt;

&lt;p&gt;You set up templates using dynamic variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{site_name} | {page_title} | {product_title} | {image_filename}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alt Audit fills them in automatically based on context. For a WooCommerce product page, it pulls the product title. For a blog post, the post title. It adapts to your content type automatically.&lt;/p&gt;

&lt;p&gt;For most sites — especially large libraries with predictable image patterns — this alone handles the overwhelming majority of missing alt text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Five Quality Levels (Not Just "Has It" or "Doesn't")
&lt;/h3&gt;

&lt;p&gt;Alt Audit scores every image across five statuses:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Missing&lt;/td&gt;
&lt;td&gt;Critical — fails WCAG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decorative&lt;/td&gt;
&lt;td&gt;Correctly marked as decorative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weak&lt;/td&gt;
&lt;td&gt;Present but unhelpful&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Acceptable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Optimal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This matters because &lt;code&gt;alt="image"&lt;/code&gt; technically &lt;em&gt;exists&lt;/em&gt; but does nothing for SEO or accessibility. Alt Audit shows you the full picture — not just a count of empty fields.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Generation for Complex Images
&lt;/h3&gt;

&lt;p&gt;When templates aren't enough — infographics, lifestyle photography, complex product shots — you can opt into AI-powered generation. Computer vision analyzes the actual image and writes a description no template could produce.&lt;/p&gt;

&lt;p&gt;The AI tier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports &lt;strong&gt;130+ languages&lt;/strong&gt; (great for multilingual sites and EAA compliance)&lt;/li&gt;
&lt;li&gt;Pulls focus keywords from &lt;strong&gt;Yoast SEO and Rank Math&lt;/strong&gt; automatically&lt;/li&gt;
&lt;li&gt;Pay-as-you-go, no subscription — new users get &lt;strong&gt;25 free credits&lt;/strong&gt; to test it&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lives Where You Already Work
&lt;/h3&gt;

&lt;p&gt;No separate dashboard to log into, no CSV exports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gutenberg&lt;/strong&gt; — real-time quality indicators on image blocks as you write&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classic Editor&lt;/strong&gt; — meta box for per-post auditing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media Library&lt;/strong&gt; — inline editing, quality badges, and bulk actions in the standard grid&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Practical Workflow for Bulk Alt Text Cleanup
&lt;/h2&gt;

&lt;p&gt;Here's how to approach a large-scale cleanup using Alt Audit:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Audit.&lt;/strong&gt; Open the dashboard, scan your media library. You'll immediately see Missing, Weak, Good, and Excellent breakdowns. Start with Missing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — Set up free templates.&lt;/strong&gt; Configure rule-based templates for your main content types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WooCommerce:  {product_title} - {site_name}
Blog:         {image_filename} from {page_title}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This handles your library in bulk, instantly, for free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Use AI for exceptions.&lt;/strong&gt; Run AI generation on image categories where templates fall short — product lifestyle shots, team photos, custom graphics. Use your free credits to sample quality first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — Review before publishing.&lt;/strong&gt; Non-negotiable. AI is fast but not infallible. Spot-check a sample, fix anything generic, make sure keywords read naturally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Maintain going forward.&lt;/strong&gt; New uploads get flagged automatically in the media library. You won't let the problem rebuild itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Accessibility Compliance Timeline
&lt;/h2&gt;

&lt;p&gt;If you serve EU customers, the European Accessibility Act requires WCAG 2.1 Level A compliance — including image alt text — as of June 2025. US Section 508 and UK accessibility regulations are also expanding in scope.&lt;/p&gt;

&lt;p&gt;Alt text is one of the most straightforward accessibility wins available. It doesn't require a redesign or a developer. It's metadata. The hard part is doing it at scale — which is exactly what Alt Audit solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;If your site has more than a few hundred images, manual alt text isn't a strategy — it's a backlog. Alt Audit handles the bulk of the work automatically with free rule-based generation, surfaces the images that need human attention through quality scoring, and integrates directly into the WordPress workflow you already use.&lt;/p&gt;

&lt;p&gt;The free tier is worth installing today. The AI is there when you need it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://wordpress.org/plugins/alt-audit/" rel="noopener noreferrer"&gt;Try Alt Audit free on WordPress.org&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://altaudit.com/blog/stop-writing-alt-text-manually-how-ai-is-changing-image-seo-forever" rel="noopener noreferrer"&gt;altaudit.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>seo</category>
      <category>accessibility</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Mastering Alt Text Generation: A Comprehensive Guide for SEO and Accessibility</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Thu, 26 Feb 2026 19:39:46 +0000</pubDate>
      <link>https://dev.to/proga100/mastering-alt-text-generation-a-comprehensive-guide-for-seo-and-accessibility-3leo</link>
      <guid>https://dev.to/proga100/mastering-alt-text-generation-a-comprehensive-guide-for-seo-and-accessibility-3leo</guid>
      <description>&lt;p&gt;Okay, let's cut to the chase. I was digging into performance metrics on a client's site, specifically around their blog content, and noticed image loading was a significant bottleneck. Not just slow, but &lt;em&gt;really&lt;/em&gt; slow. This wasn't just a UX annoyance; it was impacting engagement and, you guessed it, SEO. We're talking about how a seemingly small piece of HTML can become a major roadblock.&lt;/p&gt;

&lt;p&gt;Here's the breakdown of what we found, what we did, and what the impact was.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Bloated Images &amp;amp; Missed SEO Opportunities
&lt;/h2&gt;

&lt;p&gt;The client had a ton of blog posts with numerous images. The issue wasn't just the sheer number, but the &lt;em&gt;quality&lt;/em&gt; and &lt;em&gt;optimization&lt;/em&gt; of these images. Many were high-resolution JPEGs, often uncompressed, leading to massive file sizes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The symptoms were clear:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Slow page load times:&lt;/strong&gt; Users were bouncing before content even loaded.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Poor Core Web Vitals scores:&lt;/strong&gt; Specifically LCP (Largest Contentful Paint) was suffering.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Low Lighthouse scores:&lt;/strong&gt; Accessibility and SEO scores were taking a hit.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Underperforming image search traffic:&lt;/strong&gt; Images weren't being discovered or ranked effectively.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond the raw performance, I saw a consistent pattern of poor &lt;code&gt;alt&lt;/code&gt; text implementation. It was either missing entirely, generic (&lt;code&gt;image.jpg&lt;/code&gt;), or stuffed with keywords. This was a double whammy: hurting accessibility for screen reader users and confusing search engines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Investigation: An Audit of Image Assets and Alt Text
&lt;/h2&gt;

&lt;p&gt;My approach was to audit the existing image assets and their &lt;code&gt;alt&lt;/code&gt; text implementation across a representative sample of blog posts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key areas of focus:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Image File Sizes &amp;amp; Formats:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  What formats were being used (JPEG, PNG, GIF)?&lt;/li&gt;
&lt;li&gt;  What were the average file sizes per image?&lt;/li&gt;
&lt;li&gt;  Were modern formats like WebP being considered?&lt;/li&gt;
&lt;li&gt;  Were images being served at appropriate resolutions for their display context?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;alt&lt;/code&gt; Text Quality:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Was &lt;code&gt;alt&lt;/code&gt; text present for all meaningful images?&lt;/li&gt;
&lt;li&gt;  Was it descriptive and accurate?&lt;/li&gt;
&lt;li&gt;  Was it free of keyword stuffing?&lt;/li&gt;
&lt;li&gt;  Did it convey the &lt;em&gt;purpose&lt;/em&gt; of the image within the content?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Technical Implementation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  How were images being embedded? Standard &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags?&lt;/li&gt;
&lt;li&gt;  Were there any lazy loading mechanisms in place?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Findings: A Perfect Storm of Neglect
&lt;/h3&gt;

&lt;p&gt;The audit revealed a predictable, yet frustrating, set of issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Average JPEG file size:&lt;/strong&gt; 850KB. Many exceeded 1.5MB.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Image format prevalence:&lt;/strong&gt; 90% JPEGs, 8% PNGs (for graphics that could have been SVGs), 2% GIFs (often used as static images).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;alt&lt;/code&gt; text presence:&lt;/strong&gt; Only about 40% of images had &lt;code&gt;alt&lt;/code&gt; text.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;alt&lt;/code&gt; text quality:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Of the &lt;code&gt;alt&lt;/code&gt; text present, 60% was generic (e.g., "Blog post image").&lt;/li&gt;
&lt;li&gt;  20% was keyword-stuffed (e.g., "Best developer tools for coding productivity software").&lt;/li&gt;
&lt;li&gt;  Only 20% was reasonably descriptive.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This confirmed that both image optimization and &lt;code&gt;alt&lt;/code&gt; text strategy were severely lacking.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Fix: A Two-Pronged Optimization Strategy
&lt;/h2&gt;

&lt;p&gt;We implemented a multi-step solution targeting both image optimization and &lt;code&gt;alt&lt;/code&gt; text best practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Image Optimization Pipeline
&lt;/h3&gt;

&lt;p&gt;We introduced a process to optimize images &lt;em&gt;before&lt;/em&gt; they were uploaded, and in some cases, implemented server-side resizing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Format Conversion:&lt;/strong&gt; Prioritizing WebP for its superior compression and quality. Fallback to JPEG for older browsers.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Compression:&lt;/strong&gt; Using tools like &lt;code&gt;imagemin&lt;/code&gt; (via Gulp or Webpack) to aggressively compress images without significant visual degradation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Responsive Images:&lt;/strong&gt; Implementing &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; elements or &lt;code&gt;srcset&lt;/code&gt; attributes to serve appropriately sized images based on the user's viewport.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Lazy Loading:&lt;/strong&gt; Using native browser lazy loading (&lt;code&gt;loading="lazy"&lt;/code&gt;) for all images below the fold.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bad vs. Good: Image Embedding (Responsive)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"large-image.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A descriptive alt text."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good (using &lt;code&gt;srcset&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"medium-image.jpg"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"small-image.webp 480w,
          medium-image.webp 800w,
          large-image.webp 1200w"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 600px) 480px,
         (max-width: 1024px) 800px,
         1200px"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A descriptive alt text."&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Note: For simplicity, I've omitted WebP fallbacks here, but they would typically be handled with the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element for broader compatibility.)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Strategic &lt;code&gt;alt&lt;/code&gt; Text Generation
&lt;/h3&gt;

&lt;p&gt;This was less about automation and more about a disciplined approach.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Focus on Context and Purpose:&lt;/strong&gt; The &lt;code&gt;alt&lt;/code&gt; text should describe what the image &lt;em&gt;adds&lt;/em&gt; to the content, not just what it &lt;em&gt;is&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Be Concise and Specific:&lt;/strong&gt; Aim for clarity and avoid jargon or overly long descriptions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Avoid Keyword Stuffing:&lt;/strong&gt; Treat &lt;code&gt;alt&lt;/code&gt; text as a natural language description, not an SEO hack.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Decorative Images:&lt;/strong&gt; For purely decorative images, an empty &lt;code&gt;alt=""&lt;/code&gt; attribute is appropriate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bad vs. Good: &lt;code&gt;alt&lt;/code&gt; Text Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; A blog post about effective code review practices, featuring a screenshot of a pull request with clear comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"pr-screenshot.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"code review pull request comments best practices development"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"pr-screenshot.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Screenshot of a pull request showing specific feedback on a code change."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Measurable Result: Tangible Performance Gains
&lt;/h2&gt;

&lt;p&gt;The impact of these changes was significant and measurable across several key metrics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Average Image Payload Reduction:&lt;/strong&gt; Reduced by &lt;strong&gt;65%&lt;/strong&gt; (from ~850KB to ~300KB per page).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;LCP Improvement:&lt;/strong&gt; Increased by an average of &lt;strong&gt;2.5 seconds&lt;/strong&gt; across audited pages.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Lighthouse Scores:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Performance: Improved from an average of 60 to &lt;strong&gt;85&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  Accessibility: Improved from an average of 75 to &lt;strong&gt;98&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  SEO: Improved from an average of 70 to &lt;strong&gt;90&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Image Search Traffic:&lt;/strong&gt; Saw a &lt;strong&gt;20% increase&lt;/strong&gt; in traffic originating from Google Image Search within 3 months.&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Bounce Rate Reduction:&lt;/strong&gt; Decreased by &lt;strong&gt;12%&lt;/strong&gt; on pages with optimized images.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons Learned: The Devil (and the Gains) are in the Details
&lt;/h2&gt;

&lt;p&gt;This project reinforced some critical engineering truths:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Don't Treat Images as Afterthoughts:&lt;/strong&gt; They are first-class citizens of your web content. Ignoring them is leaving performance and SEO gains on the table.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;&lt;code&gt;alt&lt;/code&gt; Text is More Than Just SEO:&lt;/strong&gt; It's a fundamental accessibility requirement. Get it right for everyone.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Automation is Key for Scale:&lt;/strong&gt; For ongoing content creation, a well-defined image optimization pipeline (built into your CMS or build process) is crucial. Manual optimization is unsustainable.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Balance is Crucial:&lt;/strong&gt; Aggressive compression can degrade quality. Find the sweet spot. Similarly, &lt;code&gt;alt&lt;/code&gt; text needs to be descriptive without being a novel.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Measure Everything:&lt;/strong&gt; You can't improve what you don't measure. The data from this audit and the subsequent improvements was the driving force for buy-in.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This wasn't a revolutionary new technology, but a disciplined application of existing best practices. The results speak for themselves.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Note: This article was drafted with the assistance of AI and reviewed for technical accuracy by our team.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>alttext</category>
    </item>
    <item>
      <title>How I Used Claude CLI to Fix My Laravel SaaS Site’s SEO (Zero Traffic Fully Optimized)</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 23 Feb 2026 21:27:44 +0000</pubDate>
      <link>https://dev.to/proga100/how-i-used-claude-cli-to-fix-my-laravel-saas-sites-seo-zero-traffic-fully-optimized-4f21</link>
      <guid>https://dev.to/proga100/how-i-used-claude-cli-to-fix-my-laravel-saas-sites-seo-zero-traffic-fully-optimized-4f21</guid>
      <description>&lt;h1&gt;
  
  
  How I Used Claude CLI to Fix My Laravel SaaS Site’s SEO (Zero Traffic → Fully Optimized)
&lt;/h1&gt;

&lt;p&gt;After spending months building my Laravel SaaS, I expected slow growth — but not &lt;em&gt;zero&lt;/em&gt; organic traffic.&lt;/p&gt;

&lt;p&gt;The product worked. The UI was clean. Everything deployed smoothly.&lt;/p&gt;

&lt;p&gt;Google? Completely unimpressed.&lt;/p&gt;

&lt;p&gt;So I did what any developer would do:&lt;/p&gt;

&lt;p&gt;I asked an AI to debug my SEO.&lt;/p&gt;




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

&lt;p&gt;My project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Laravel 12&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Livewire 3&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mcamara/laravel-localization&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;AI-powered accessibility tool (&lt;a href="https://altaudit.com" rel="noopener noreferrer"&gt;altaudit.com&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five languages. Marketing pages. Blog. Clean architecture.&lt;/p&gt;

&lt;p&gt;Traffic: basically none.&lt;/p&gt;




&lt;h2&gt;
  
  
  The SEO Audit
&lt;/h2&gt;

&lt;p&gt;Using Claude CLI, I ran a structured audit of the live site.&lt;/p&gt;

&lt;p&gt;The result was brutal — and incredibly useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Critical Issues Found
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No &lt;code&gt;Sitemap:&lt;/code&gt; in &lt;code&gt;robots.txt&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Google may not auto-discover pages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zero canonical tags&lt;/td&gt;
&lt;td&gt;Duplicate content risk (especially multilingual sites)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No Open Graph tags&lt;/td&gt;
&lt;td&gt;Broken social previews&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No structured data (JSON-LD)&lt;/td&gt;
&lt;td&gt;No eligibility for rich results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hreflang only on homepage&lt;/td&gt;
&lt;td&gt;Localized pages invisible to search engines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No noindex on auth pages&lt;/td&gt;
&lt;td&gt;Crawl budget wasted on &lt;code&gt;/login&lt;/code&gt;, &lt;code&gt;/dashboard&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nothing catastrophic individually.&lt;/p&gt;

&lt;p&gt;Together? SEO invisibility cloak.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 1 — Crawl &amp;amp; Indexing Fixes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  robots.txt
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User-agent: *
Disallow: /dashboard
Disallow: /login
Disallow: /register
Disallow: /livewire/
Sitemap: https://altaudit.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Canonical Tags
&lt;/h3&gt;

&lt;p&gt;Added to layouts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="canonical" href="{{ url()-&amp;gt;current() }}"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  noindex for Private Pages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta name="robots" content="noindex, nofollow"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Phase 2 — Open Graph &amp;amp; hreflang
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Open Graph
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta property="og:title" content="{{ __('meta.title') }}"&amp;gt;
&amp;lt;meta property="og:description" content="{{ __('meta.description') }}"&amp;gt;
&amp;lt;meta property="og:url" content="{{ url()-&amp;gt;current() }}"&amp;gt;
&amp;lt;meta property="og:image" content="{{ asset('images/preview.png') }}"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  hreflang (Multilingual SEO Essential)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@foreach(LaravelLocalization::getSupportedLocales() as $localeCode =&amp;gt; $properties)
&amp;lt;link rel="alternate" hreflang="{{ $localeCode }}"
      href="{{ LaravelLocalization::getLocalizedURL($localeCode) }}"&amp;gt;
@endforeach

&amp;lt;link rel="alternate" hreflang="x-default"
      href="{{ LaravelLocalization::getLocalizedURL('en') }}"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this, Google treats translations like unrelated pages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 3 — Structured Data (JSON-LD)
&lt;/h2&gt;

&lt;p&gt;This is where Laravel developers hit a classic trap.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Blade &lt;code&gt;@context&lt;/code&gt; Bug
&lt;/h3&gt;

&lt;p&gt;Blade interprets &lt;code&gt;@context&lt;/code&gt;, &lt;code&gt;@type&lt;/code&gt;, etc. as directives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; ParseError.&lt;/p&gt;

&lt;h3&gt;
  
  
  Correct Fix
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="application/ld+json"&amp;gt;
@verbatim
{
  "@context": "https://schema.org",
  "@type": "SoftwareApplication",
  "name": "Alt Audit"
}
@endverbatim
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternative for dynamic JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"@@context": "https://schema.org"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, this feels weird. Yes, it works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unexpected Laravel Gotchas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ route:cache + Localization = Disaster
&lt;/h3&gt;

&lt;p&gt;If you're using &lt;code&gt;mcamara/laravel-localization&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan route:cache  &lt;span class="c"&gt;# ❌ DON'T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Localized routes are dynamic.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan route:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2️⃣ view:clear Isn’t Always Enough
&lt;/h3&gt;

&lt;p&gt;Sometimes compiled Blade views linger:&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;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; storage/framework/views/&lt;span class="k"&gt;*&lt;/span&gt;.php
php artisan view:cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instant mystery bug resolution.&lt;/p&gt;




&lt;h3&gt;
  
  
  3️⃣ Quotes Inside &lt;code&gt;{{ }}&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{-- WRONG --}}
gtag('config', '{{ config('services.ga.id') }}')

{{-- CORRECT --}}
gtag('config', '{{ config("services.ga.id") }}')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tiny detail → fatal error.&lt;/p&gt;




&lt;h2&gt;
  
  
  New Pages That Actually Matter
&lt;/h2&gt;

&lt;p&gt;SEO isn’t just tags.&lt;/p&gt;

&lt;p&gt;It’s &lt;em&gt;intent targeting&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/about&lt;/code&gt; → E-E-A-T signals&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/wcag-compliance&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/alt-text-seo&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each translated into 5 languages.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Claude CLI Was Actually Good At
&lt;/h2&gt;

&lt;p&gt;Not magic.&lt;/p&gt;

&lt;p&gt;Not "AI hype."&lt;/p&gt;

&lt;p&gt;Just extremely efficient at:&lt;/p&gt;

&lt;p&gt;✔ Reading real Blade files&lt;br&gt;&lt;br&gt;
✔ Finding real structural problems&lt;br&gt;&lt;br&gt;
✔ Applying consistent fixes&lt;br&gt;&lt;br&gt;
✔ Avoiding generic SEO advice  &lt;/p&gt;

&lt;p&gt;Most value came from &lt;strong&gt;systematic analysis&lt;/strong&gt;, not individual snippets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final State
&lt;/h2&gt;

&lt;p&gt;Every public page now has:&lt;/p&gt;

&lt;p&gt;✅ Canonical&lt;br&gt;&lt;br&gt;
✅ Open Graph&lt;br&gt;&lt;br&gt;
✅ hreflang&lt;br&gt;&lt;br&gt;
✅ JSON-LD&lt;br&gt;&lt;br&gt;
✅ Proper robots directives  &lt;/p&gt;

&lt;p&gt;From invisible → properly indexed candidate.&lt;/p&gt;




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

&lt;p&gt;Most Laravel SaaS SEO problems are not complex.&lt;/p&gt;

&lt;p&gt;They are &lt;strong&gt;death by small omissions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Canonical missing. hreflang incomplete. robots.txt half-configured.&lt;/p&gt;

&lt;p&gt;Individually harmless.&lt;/p&gt;

&lt;p&gt;Collectively fatal.&lt;/p&gt;




&lt;p&gt;If you’re building a Laravel product and planning to “fix SEO later”…&lt;/p&gt;

&lt;p&gt;Later is why Google ignores you.&lt;/p&gt;




&lt;p&gt;Curious what your site is silently missing? Run an audit. You might be surprised.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>seo</category>
      <category>laravel</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Harnessing Gemini AI for Automatic Alt Text Generation: A PHP Developer's Guide</title>
      <dc:creator>Rustamjon Akhmedov</dc:creator>
      <pubDate>Mon, 16 Feb 2026 19:30:40 +0000</pubDate>
      <link>https://dev.to/proga100/harnessing-gemini-ai-for-automatic-alt-text-generation-a-php-developers-guide-1cg9</link>
      <guid>https://dev.to/proga100/harnessing-gemini-ai-for-automatic-alt-text-generation-a-php-developers-guide-1cg9</guid>
      <description>&lt;h1&gt;
  
  
  Automating Alt Text Generation with Gemini and PHP: Enhancing Accessibility and SEO
&lt;/h1&gt;

&lt;p&gt;In the ever-evolving landscape of web development, &lt;strong&gt;accessibility&lt;/strong&gt; and &lt;strong&gt;Search Engine Optimization (SEO)&lt;/strong&gt; are no longer afterthoughts but fundamental pillars of a successful online presence. For visually impaired users, &lt;strong&gt;alt text (alternative text)&lt;/strong&gt; serves as a vital bridge, providing descriptive information about an image when it cannot be viewed. Screen readers rely on alt text to convey the image's content and function, ensuring an inclusive user experience.&lt;/p&gt;

&lt;p&gt;Beyond accessibility, search engines also leverage alt text to understand image content, contributing significantly to image search rankings and overall website discoverability. However, manually generating descriptive and accurate alt text for every image can be a tedious and time-consuming process, especially for websites with large image libraries. This is where the power of &lt;strong&gt;Artificial Intelligence&lt;/strong&gt;, particularly &lt;strong&gt;Google's Gemini&lt;/strong&gt;, comes into play.&lt;/p&gt;

&lt;p&gt;This comprehensive guide will explore how developers, particularly those working with PHP, can integrate Gemini's advanced image understanding capabilities to automate alt text generation, enhancing both accessibility and SEO efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Gemini: A New Era of AI Multimodality
&lt;/h2&gt;

&lt;p&gt;Gemini, Google's latest and most capable AI model, represents a significant leap forward in artificial intelligence. Unlike previous models that were often specialized for specific tasks (e.g., text generation or image recognition), Gemini is &lt;strong&gt;natively multimodal&lt;/strong&gt;. This means it can understand, operate across, and combine different types of information, including text, images, audio, video, and code, seamlessly.&lt;/p&gt;

&lt;p&gt;For developers, this multimodal capability is a game-changer. It allows for more sophisticated and context-aware interactions with AI, opening up new possibilities for application development. When it comes to image analysis, Gemini's ability to process visual information and generate relevant textual descriptions is particularly potent. It can go beyond simple object recognition to understand the context, relationships between objects, and even infer actions or emotions within an image, leading to richer and more informative alt text.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Foundation: Gemini API and PHP Integration
&lt;/h2&gt;

&lt;p&gt;To leverage Gemini's power for alt text generation, developers will need to interact with the Gemini API. Google provides robust APIs that allow programmatic access to its AI models. For PHP developers, this typically involves making HTTP requests to the Gemini API endpoints. The core process involves sending an image (or a URL to an image) along with a prompt to the Gemini API. The API then processes this input and returns a generated text description.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Your Gemini API Key
&lt;/h3&gt;

&lt;p&gt;Before you can start making API calls, you'll need to obtain an API key from Google AI Studio or the Google Cloud Platform. This key acts as your authentication credential. It's crucial to keep your API key secure and avoid exposing it directly in your client-side code. For PHP applications, it's best practice to store API keys in environment variables or secure configuration files that are not publicly accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making API Requests with PHP
&lt;/h3&gt;

&lt;p&gt;PHP offers several ways to make HTTP requests. The most common and recommended methods include using:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Guzzle HTTP Client:&lt;/strong&gt; A popular and powerful HTTP client library for PHP. It simplifies making requests, handling responses, and managing errors.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;cURL:&lt;/strong&gt; PHP's built-in cURL extension provides low-level access to various network protocols, including HTTP. While more verbose than Guzzle, it's a reliable option.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's outline a conceptual example using Guzzle to send an image and a prompt to the Gemini API for alt text generation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Assuming you're using Composer for Guzzle&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;GuzzleHttp\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;GuzzleHttp\Exception\RequestException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Generates alt text for an image using the Gemini API.
 *
 * @param string $imagePath The local path to the image file.
 * @param string $apiKey Your Gemini API key.
 * @param string $geminiApiEndpoint The Gemini API endpoint URL.
 * @return string|null The generated alt text, or null if an error occurred.
 */&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;generateAltText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$geminiApiEndpoint&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;?string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Ensure the image file exists and is readable&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;file_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_readable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Error generating alt text: Image file not found or not readable at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&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="c1"&gt;// Prepare the image data for upload&lt;/span&gt;
        &lt;span class="nv"&gt;$imageData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imageData&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Could not read image file.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nv"&gt;$base64Image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;base64_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imageData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$mimeType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mime_content_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Construct the request body&lt;/span&gt;
        &lt;span class="nv"&gt;$requestBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'contents'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="s1"&gt;'parts'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Describe this image in detail for alt text. Focus on key visual elements and context.'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt;
                            &lt;span class="s1"&gt;'inline_data'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                                &lt;span class="s1"&gt;'mime_type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$mimeType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="s1"&gt;'data'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$base64Image&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="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="c1"&gt;// Make the POST request to the Gemini API&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$geminiApiEndpoint&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'?key='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'json'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$requestBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'timeout'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Set a reasonable timeout&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStatusCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$statusCode&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"API request failed with status code &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$statusCode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBody&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContents&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Extract and return the generated alt text&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'candidates'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'parts'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'candidates'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'parts'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Log API response for debugging if alt text is not found&lt;/span&gt;
            &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Gemini API response did not contain expected alt text structure: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RequestException&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle Guzzle-specific exceptions&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getResponse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStatusCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nv"&gt;$errorBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getBody&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContents&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Gemini API Request Error (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$statusCode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$errorBody&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Gemini API Request Error: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="nc"&gt;Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Log other exceptions&lt;/span&gt;
        &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'General Error generating alt text: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// --- Example Usage ---&lt;/span&gt;

&lt;span class="c1"&gt;// Load API key from environment variable for security&lt;/span&gt;
&lt;span class="nv"&gt;$apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GEMINI_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Replace with the actual Gemini API endpoint for the model you are using (e.g., Gemini Pro Vision)&lt;/span&gt;
&lt;span class="nv"&gt;$geminiApiEndpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$imagePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/path/to/your/image.jpg'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Use __DIR__ for relative paths within the script&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$apiKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Gemini API Key not configured. Please set the GEMINI_API_KEY environment variable.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;file_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Image file not found at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Generating alt text for: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$altText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateAltText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$imagePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$apiKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$geminiApiEndpoint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$altText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Generated Alt Text: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;htmlspecialchars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$altText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to generate alt text. Please check error logs.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;  Replace &lt;code&gt;https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent&lt;/code&gt; with the actual Gemini API endpoint for the model you intend to use.&lt;/li&gt;
&lt;li&gt;  Ensure you have Guzzle installed via Composer: &lt;code&gt;composer require guzzlehttp/guzzle&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Store your &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; in your server's environment variables for security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Crafting Effective Prompts for Alt Text Generation
&lt;/h2&gt;

&lt;p&gt;The quality of the generated alt text is heavily influenced by the prompt provided to the Gemini model. A well-crafted prompt guides the AI to produce descriptions that are not only accurate but also contextually relevant and SEO-friendly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Elements of an Effective Prompt:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Clarity and Specificity:&lt;/strong&gt; Clearly state the objective. For example, instead of just "Describe this image," use "Describe this image for use as alt text on a website, focusing on its key elements and purpose."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Contextual Information (Optional but Recommended):&lt;/strong&gt; If the image is part of a specific article or product page, providing that context can lead to more tailored alt text. For instance, "This image is for a blog post about sustainable gardening. Describe the image, highlighting any plants or gardening tools."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Length and Detail:&lt;/strong&gt; Specify the desired level of detail. "Provide a concise description" versus "Provide a detailed description."&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;SEO Considerations:&lt;/strong&gt; You can even hint at SEO goals. "Describe this image, ensuring the description is useful for users and potentially includes relevant keywords if natural to do so."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Prompts:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  "Generate alt text for this image. Focus on the main subject and any actions taking place."&lt;/li&gt;
&lt;li&gt;  "Describe this product image for an e-commerce website. Include details about the product's appearance and any notable features."&lt;/li&gt;
&lt;li&gt;  "This image depicts a historical event. Provide an accurate and informative description suitable for an educational website."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Experimentation with different prompts is key to finding what works best for your specific use case and the nuances of the Gemini model you are utilizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Implementing Automated Alt Text Generation
&lt;/h2&gt;

&lt;p&gt;While Gemini offers a powerful solution for automating alt text generation, a purely automated approach might not always yield perfect results. A hybrid strategy often proves most effective, combining AI's efficiency with human oversight.&lt;/p&gt;

&lt;h3&gt;
  
  
  Human Review and Refinement
&lt;/h3&gt;

&lt;p&gt;It's highly recommended to implement a review process where generated alt text is checked by a human before being finalized. This ensures accuracy, catches any potential misinterpretations by the AI, and allows for fine-tuning descriptions to perfectly match the image's intent and context within the webpage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Different Image Types
&lt;/h3&gt;

&lt;p&gt;Consider how you'll handle various image types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Decorative Images:&lt;/strong&gt; Images that purely serve aesthetic purposes and don't convey critical information might not need detailed alt text. In such cases, an empty &lt;code&gt;alt&lt;/code&gt; attribute (&lt;code&gt;alt=""&lt;/code&gt;) is often appropriate, signaling to screen readers to skip the image. You might need logic to identify these or a manual tagging system.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Functional Images (e.g., Buttons, Icons):&lt;/strong&gt; Alt text for these should describe the action the image performs (e.g., &lt;code&gt;alt="Search"&lt;/code&gt;, &lt;code&gt;alt="Add to Cart"&lt;/code&gt;). Gemini can be prompted to identify these functions if context is provided.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Informative Images (Charts, Graphs, Infographics):&lt;/strong&gt; These often require more detailed descriptions, potentially summarizing the data presented. Gemini can provide a starting point, but significant human input might be necessary for complex data visualizations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance and Cost Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;API Rate Limits:&lt;/strong&gt; Be mindful of the API rate limits imposed by Google. Implement appropriate error handling and potentially caching mechanisms to avoid hitting these limits.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cost:&lt;/strong&gt; API usage typically incurs costs. Monitor your usage and consider optimizing requests. For instance, batching requests where possible or only generating alt text for new uploads rather than re-processing existing images.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Asynchronous Processing:&lt;/strong&gt; For large-scale operations, consider implementing asynchronous processing (e.g., using job queues) to avoid blocking your web application and provide a better user experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enhancing SEO with Gemini-Generated Alt Text
&lt;/h2&gt;

&lt;p&gt;Accurate and descriptive alt text is a cornerstone of effective SEO. By leveraging Gemini, you can significantly improve your website's SEO performance in several ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  Improved Image Search Rankings
&lt;/h3&gt;

&lt;p&gt;Search engines like Google use alt text to index images. When users search for images, well-optimized alt text increases the likelihood of your images appearing in the search results. Gemini's ability to generate descriptive text helps search engines better understand the image's content, leading to higher relevance and better rankings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Understanding of Page Content
&lt;/h3&gt;

&lt;p&gt;Search engine crawlers analyze all the content on a webpage, including alt text. Descriptive alt text provides additional context about the page's topic, reinforcing its relevance for specific keywords and improving the page's overall SEO score.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enhanced User Experience and Reduced Bounce Rates
&lt;/h3&gt;

&lt;p&gt;While not a direct ranking factor, user experience is paramount. Images that are relevant to the content and accurately described via alt text contribute to a more engaging and informative user journey. This can lead to lower bounce rates and increased time spent on site, both positive signals for SEO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility as an SEO Signal
&lt;/h3&gt;

&lt;p&gt;Google increasingly emphasizes accessibility. By ensuring your website is accessible through proper alt text implementation, you align with search engine best practices and potentially gain favor in search rankings. Implementing Gemini for alt text generation is a proactive step towards building a more inclusive and SEO-friendly website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: The Future of Image Content Optimization
&lt;/h2&gt;

&lt;p&gt;The integration of AI models like Gemini into web development workflows presents a transformative opportunity. Automating alt text generation using Gemini's advanced multimodal capabilities significantly streamlines the process, making it more efficient and scalable. For PHP developers, harnessing the Gemini API allows for the creation of more accessible, SEO-rich, and user-friendly websites.&lt;/p&gt;

&lt;p&gt;While human oversight remains crucial for ensuring the highest quality, AI-powered tools like Gemini provide a powerful foundation for optimizing image content. By embracing these advancements, developers can stay ahead of the curve, build more inclusive digital experiences, and unlock new levels of performance for their web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Call to Action
&lt;/h2&gt;

&lt;p&gt;Ready to supercharge your website's accessibility and SEO?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Get your Gemini API key&lt;/strong&gt; and start experimenting with the Gemini API.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Integrate the provided PHP code&lt;/strong&gt; into your project and adapt it to your specific needs.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Develop a robust prompt strategy&lt;/strong&gt; to ensure the highest quality alt text generation.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Implement a human review process&lt;/strong&gt; for critical images to guarantee accuracy and context.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Share your experiences and findings&lt;/strong&gt; in the comments below! Let's build a more accessible web together.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>gemini</category>
      <category>php</category>
      <category>alttext</category>
    </item>
  </channel>
</rss>
