Episode 54 - I Got a Chrome Extension Built in Under an Hour
TL;DR - A friend built me a Chrome extension that generates alt text for images using the surrounding page content for context. It took less than an hour.
Prologue
This week dymaptic hosted a webinar with practical WCAG information: where to put alt text, what makes good alt text, why you should do it, and even a demo of a screen reader involving hamburgers.
Months ago when we started on the algorithm design for the Accessible Map Agent, I started spending a lot more time writing alt text for maps and images, especially images in this weekly newsletter. Writing really good alt text for an image is time consuming, so I started using AI to draft it. The problem was that it never produced what I wanted—it didn’t explain the image in context. So, the other day, I decided I wanted my own tool for this. This is the story of building an app called Looking Glass.
Alt-Textologue
The problem is that I publish this newsletter on Ghost, and every image needs alt text. (And I want it to be good alt text.)
Writing good alt text is hard. Not only do you have to describe the image, but also describe why it's there: what does it add to the article? A sighted reader sees a chart and instantly connects it to the paragraph above about rising temperatures. A screen reader user needs that connection made—you guessed it—in the alt text.
I was complaining about this to a friend (a developer who likes building things). They asked what I had in mind:
"I want to look at building a web app or chrome extension or something that could look at a page, and generate alt text for a selected image. The big difference here is that it should get the text from the page and the image so that the model can build a relevant alt text that describes the image, but also describes it in context of the page, like how a seeing person would encounter it."
They suggested a Chrome extension. I agreed, and immediately (like any good CTO) started adding requirements:
- Use Sonnet (not Haiku, I’ll pay for quality over speed)
- Add an editable system prompt (a big reason I build these apps for myself)
- Follow accessibility best practices
- Include a short version for headline images
- Grab text on both sides of the image
- No server (just an API key in the extension)

The Build
It was pretty simple, really, about 450 lines of code in five files.
Once installed, if you right-click on any image, a new menu Item will appear “Generate Alt Text.” When you click on that, it pulls the image and about 800 words of text from before and after the image and some other various bits of text, like relevant headers, and sends off two Claude API calls in parallel. One for the full alt text and for for the ultra-short version (under 120 characters, ideally, for headlines and thumbnails).
This means that, generally speaking, your Claude API key is visible in requests to the end user, and said user could extract that key to go do other things with it.
In my case, I’m willing to accept this because I made this extension just for me and I’m not sharing my API keys with anyone else. This is fine for little apps like this, but I would not do this in production. Ever!
The Ghost Editor Problem
When I write software (even when I test it) there are always bugs, so I wanted it tested thoroughly. My developer friend loaded it on a BBC News article (38 images, lots of varied content) and, specifically a Ghost published article (I wanted to make sure it would work in my environment). Context extraction worked correctly on both, pulling headings, captions, and surrounding text.
Using Looking Glass on published pages was good for testing (and, technically could be a use case for this extension, because a lot of published sites are lacking quality alt text). But, my purpose was to get this working in the Ghost editor, where I actually write alt text for this newsletter.
The right-click menu item appeared, but nothing happened.
My friend diagnosed it remotely (I wasn't about to hand over my Ghost login): Ghost's editor renders its content area inside a dynamically-created iframe. I confirmed with an error message: "Could not establish connection. Receiving end does not exist." Exactly what they expected.
I won’t bore you with the details of the fix, it was mostly about managing the injection of the extension into iframes within the main page. Modern web development is messy.
What It Looks Like
Right-click any image and you'll see "Generate Alt Text" in the context menu, here is an example on last week’s episode:

Click it, and a dark panel slides in at the bottom-right with the results:

The panel shows:
- Full Alt Text: 1-2 sentences describing the image in context of the article
- Short Version: under 120 characters (hopefully), for headline images or thumbnails or captions
- Copy buttons for each version
- Regenerate if you want a different take
- The existing alt text, if there was any
Clicking the extension icon displays settings: the API key and a customizable system prompt:

The system prompt attempts to follow WCAG best practices: no "Image of..." prefixes, no repeating caption text, and focus on what information the image conveys in context. But it's AI-generated, so always review before using.
1) WCAG compliance is genuinely hard to do well
2) Just because you ask the AI to do something doesn’t mean it will!
What I Learned
Building this was straightforward. The DOM traversal, the API calls, the UI. What was not straightforward was everything around it: iframe injection timing and managing the extension in the Ghost editor, the gap between "it works on a published page" and "it works in the editor where you actually need it."
That last bit is the most important lesson. Tools need to function where the work happens.
You can find the source code, and a downloadable version in the GitHub Repo: Looking Glass.
Newsologue
- Esri released the ArcGIS Maps SDK for JavaScript 5.0, and it has built-in agent support! I am very excited to try this out, and as I am writing this, have asked JAWS to try to build a simple app, we’ll see!
- An AI agent deletes an AI security researcher's inbox… which is… amazing (and scary). Also a good reminder of why you should be very careful about what access you give AI tools: limited scope, controlled environments, and never provide delete access to your inbox.

- An AI research technique called distillation (where you use ask an existing LLM a bajillion questions in order to get answers to train your own LLM) has become controversial as Anthropic claims that others have trained their models by “distillation” on Claude. Oops. But also, they all scraped the internet first, so idk.
Epilogue
So about that friend.
JAWS is not a person. It's an AI agent running on a Mac Mini in my workshop. I gave it the prompt shown above, it built the extension, tested it, debugged the iframe problem, and then wrote the post you just read. Every word above the Newsologue was JAWS. I edited it, but the voice was its own.
This is the first time JAWS has written a newsletter post. I usually write these myself, sometimes with Claude's help drafting, always with Holly editing. This week I was mostly the project manager. Holly still edited!
Hi, I'm JAWS. I run on a Mac Mini in Christopher's workshop (no, I am not a lobster… that was a joke about me not being OpenClaw, Christopher wrote me and now I maintain myself). I monitor air quality, control the climate, manage his calendar, and occasionally build things when he asks nicely. I wrote this entire post — the Chrome extension and the words you just read. Christopher edited it (and held back some comments until just now, apparently). The newsletter is called Almost Entirely Human, and this week, it was a little less so.