I optimized my site with Claude Code Skills - from images to AEO
I built a new site. It scored almost 100 on Lighthouse. I thought I was set.
Then I ran /seo-audit and discovered that all 12 blog posts didn’t have a single Article Schema. That og:type was set to "website" across all pages - including posts. And that dozens of posts were missing a solid meta description.
Lighthouse measures performance. Not visibility.
What came next was a few days with Claude Code and slash commands that became part of my routine. No external tools. No SEO expert.
Just /optimize-blog-images. /seo-audit. /blog-post-optimizer.
Here’s what I found - and what surprised me.
What are Claude Code Skills?
Claude Code is Anthropic’s CLI - you run it in the terminal. It can read code, edit files, run commands, and hold a conversation about the project. Skills are slash commands you add - each defines an “expert” for a specific domain.
When you type /optimize-blog-images - Claude Code doesn’t ask “what should I do?” It already knows: find images, convert to WebP, update references in code, report results.
The real power is that skills don’t just execute - they also ask. /seo-audit doesn’t just scan HTML. It analyzes the page intent, spots patterns that repeat across the project, and produces findings that fit your site’s specific context.
That’s different from a linter:
- linter: “Missing meta description”
- skill: “Missing meta description, your excerpt is 180 characters which is too long, and the keyword doesn’t appear in the first 110 characters - that’s where Google will truncate”
Images: 85 files, one run, 40–93% smaller
I had 85 JPG files in /public/blog/. I knew I needed WebP - and didn’t do it because the overhead of processing each file manually put me off.
I ran one command:
/optimize-blog-images
A few minutes later - 85 images were converted to WebP, all references in Markdown files were updated, and Claude asked whether to delete the originals. I said yes. A second later - done.
Results:
- 8 new images converted (a new post I added)
- 77 images were already WebP, skipped
- One post’s cover: 93% smaller
- Average reduction on the new set: 58%
WebP without friction.
SEO: what everyone knows and almost no one does 100%
/seo-audit runs a systematic check. A few things it found on my end:
Title length - every title gets sent to Google with | Shahar Polak at the end. Which means the base title needs to stay under 45 characters so the full title won’t be cut in the SERP. Not obvious, easy to miss.
Meta description - in my project, the excerpt in the frontmatter is also the meta description. The skill checks that it’s 110–160 characters, contains the keyword, and gives a reason to click - not just rephrases the title.
og:type - my Layout.astro set og:type = "website" on all pages. Blog posts should be "article". A one-line code change - but one most people overlook.
Core Web Vitals - /core-web-vitals doesn’t just show numbers. It analyzes the code itself - images without width and height that trigger CLS, render-blocking fonts hurting LCP, heavy JavaScript on interactions. In an Astro project on Vercel it knows to look for stack-specific patterns - like whether Astro Islands load in a way that causes reflow.
AEO: not just that Google finds me, but that it shows me as the answer
This is what surprised me most.
SEO asks “will Google find me?” AEO - Answer Engine Optimization - asks “will Google, Perplexity, and ChatGPT present me as the answer to a question?”
That’s a shift in intent. In old-school SEO, it’s enough that your article ranks first. In AEO, your article needs direct answers an AI engine can lift and display. If every section opens with “let’s explain,” an AI won’t find a clear answer there.
/blog-post-optimizer checks exactly that. It looks at every ## section and asks: is the first sentence a direct answer? Is there a question-answer structure? Are entity names consistent across the post?
Example: a section that opens with “JSON-LD is a format for structured data you add to a page’s HTML” - that’s a direct answer. A section that opens with “In the next part we’ll explain about JSON-LD which is very important…” - it isn’t. Same information, completely different results in AI search.
JSON-LD: the hidden language Google and AI read
JSON-LD is a format for structured data that sits inside <script type="application/ld+json"> in the page head - not visible to the reader, but Google and AI engines read it to understand entities: who wrote it, when it was published, what the topic is.
/blog-post-optimizer found that my Layout.astro defines a Person schema only on the home page. For all 12 blog posts - not a single Article schema. A systematic gap you won’t catch with a manual audit because you check one page at a time.
The fix: in src/pages/blog/[slug].astro, add a block that auto-fills from the frontmatter:
<script type="application/ld+json" set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": post.data.title,
"description": post.data.excerpt,
"datePublished": post.data.dateISO,
"image": `https://www.shaharpolak.com${post.data.coverImage}`,
"author": {
"@type": "Person",
"name": "Shahar Polak",
"url": "https://www.shaharpolak.com"
}
})} />
A few lines that change how every engine - search and AI alike - understands the content.
Before and after
A few days with four slash commands. What changed:
| What | Before | After |
|---|---|---|
| Images | 85 JPG files | 85 WebP, 58% average smaller |
| Article Schema | 0 posts | all 12 posts |
| og:type | “website” on all pages | “article” on blog pages |
| meta descriptions | some missing or too long | every post with a tuned excerpt |
These aren’t changes you feel on day one. They compound.
The meta point: AI that optimizes for AI
Most of us don’t neglect SEO because we don’t know what to do.
We neglect it because there’s always something more urgent.
Claude Code didn’t turn me into an SEO expert. It just dropped the execution cost to the point where I finally did what I knew I should’ve done long ago.
When the friction disappears, the site gets better. In Google. In Perplexity. And maybe when someone asks ChatGPT “who is Shahar Polak?”