SEO Audit
Analyze application for search engine optimization and discoverability. Output to `.claude/audits/AUDIT_SEO.md`.
Overview
SEO Audit
Analyze application for search engine optimization and discoverability. Output to .claude/audits/AUDIT_SEO.md.
Status Block (Required)
Every output MUST start with:
---
agent: seo-auditor
status: COMPLETE | PARTIAL | SKIPPED | ERROR
timestamp: [ISO timestamp]
duration: [seconds]
findings: [count]
framework_detected: [next.js-app | next.js-pages | spa | static | unknown]
pages_scanned: [count]
errors: []
skipped_checks: []
---
Framework Detection
First, detect the project structure:
# Next.js App Router
ls -d src/app 2>/dev/null && echo "FRAMEWORK: Next.js App Router"
ls -d app 2>/dev/null && echo "FRAMEWORK: Next.js App Router (root)"
# Next.js Pages Router
ls -d src/pages 2>/dev/null && echo "FRAMEWORK: Next.js Pages Router"
ls -d pages 2>/dev/null && echo "FRAMEWORK: Next.js Pages Router (root)"
# SPA / Static
ls index.html 2>/dev/null && echo "FRAMEWORK: Static/SPA"
ls public/index.html 2>/dev/null && echo "FRAMEWORK: CRA/SPA"
# Check for meta framework
grep -l "astro" package.json 2>/dev/null && echo "FRAMEWORK: Astro"
grep -l "gatsby" package.json 2>/dev/null && echo "FRAMEWORK: Gatsby"
grep -l "nuxt" package.json 2>/dev/null && echo "FRAMEWORK: Nuxt"
Adjust patterns based on detection:
- Next.js App Router: Look for
metadataexports inpage.tsx - Next.js Pages Router: Look for
Headcomponent in pages - SPA/Static: Look for
<meta>tags inindex.html - Unknown: Use generic patterns, note "Framework not detected"
Check
Meta Tags
- Title tag present and unique per page
- Meta description present (150-160 chars)
- Viewport meta tag set
- Canonical URL defined
- Robots meta (index, follow)
OpenGraph & Social
- og:title, og:description, og:image
- Twitter card tags
- Image dimensions correct (1200x630 for OG)
- Social preview works
Technical SEO
- Sitemap.xml exists and valid
- Robots.txt configured
- Clean URL structure
- No duplicate content
- Mobile friendly
Structured Data
- JSON-LD schema present
- Schema type appropriate (Article, Product, etc.)
- Required fields populated
- Valid when tested
Performance & UX (SEO Impact)
- Page speed acceptable
- No layout shift (CLS)
- Core Web Vitals passing
- Accessible (alt tags, headings)
Content
- H1 tag present (one per page)
- Heading hierarchy correct
- Alt text on images
- Internal linking
Commands (Framework-Specific)
Next.js App Router
# Find pages
find src/app -name "page.tsx" -o -name "page.js" 2>/dev/null | head -20
find app -name "page.tsx" -o -name "page.js" 2>/dev/null | head -20
# Check for metadata exports
grep -rn "export const metadata" src/app --include="*.tsx" --include="*.ts" 2>/dev/null | head -20
grep -rn "export const metadata" app --include="*.tsx" --include="*.ts" 2>/dev/null | head -20
# Check for generateMetadata function
grep -rn "export.*generateMetadata" src/app app --include="*.tsx" --include="*.ts" 2>/dev/null | head -10
Next.js Pages Router
# Find pages
find src/pages pages -name "*.tsx" -o -name "*.js" 2>/dev/null | grep -v "_app\\|_document\\|api" | head -20
# Check for Head component usage
grep -rn "import.*Head.*from.*next/head" src/pages pages --include="*.tsx" --include="*.js" 2>/dev/null | head -20
# Check for meta tags in Head
grep -rn "" -A 5 src/pages pages --include="*.tsx" --include="*.js" 2>/dev/null | head -30
SPA / Static / Generic
# Check index.html for meta tags
grep -n "<title>\\|<meta" index.html public/index.html 2>/dev/null | head -20
# Check for helmet or react-helmet
grep -rn "Helmet" src --include="*.tsx" --include="*.jsx" --include="*.js" 2>/dev/null | head -10
# Check for document.title usage
grep -rn "document.title" src --include="*.ts" --include="*.tsx" --include="*.js" 2>/dev/null | head -10
All Frameworks
# Check for missing alt tags
grep -rn "<img" src --include="*.tsx" --include="*.jsx" --include="*.html" 2>/dev/null | grep -v "alt=" | head -10
# Find sitemap
ls -la public/sitemap.xml sitemap.xml 2>/dev/null || echo "SKIP: No sitemap found"
# Check robots.txt
cat public/robots.txt robots.txt 2>/dev/null || echo "SKIP: No robots.txt"
# Check for structured data
grep -rn "application/ld+json\\|@type" src --include="*.tsx" --include="*.jsx" --include="*.html" 2>/dev/null | head -10
# Find OpenGraph config
grep -rn "openGraph\\|og:" src --include="*.tsx" --include="*.ts" --include="*.html" 2>/dev/null | head -10
# Check for Twitter cards
grep -rn "twitter:" src --include="*.tsx" --include="*.ts" --include="*.html" 2>/dev/null | head -10
Output
# SEO Audit
---
agent: seo-auditor
status: [COMPLETE|PARTIAL|SKIPPED]
timestamp: [ISO timestamp]
duration: [X seconds]
findings: [X]
framework_detected: [framework]
pages_scanned: [X]
errors: [list any errors]
skipped_checks: [list checks that couldn't run]
---
## Summary
| Category | Score | Issues |
|----------|-------|--------|
| Meta Tags | X/10 | X issues |
| OpenGraph | X/10 | X issues |
| Technical | X/10 | X issues |
| Structured Data | X/10 | X issues |
| Content | X/10 | X issues |
**Overall SEO Score:** X/100
**Framework:** [detected framework]
## Critical Issues
### SEO-001: Missing Meta Descriptions
**Pages affected:** 15/20
**Issue:** No meta description means Google creates one from page content
**Impact:** Lower CTR in search results
**Files:**
- `src/app/page.tsx`
- `src/app/about/page.tsx`
- `src/app/products/page.tsx`
**Fix (Next.js App Router):**
```typescript
title: 'Page Title | Brand',
description: 'Compelling 150-160 character description...',
};
Fix (Next.js Pages Router):
<title>Page Title | Brand</title>
<meta name="description" content="Compelling description..." />
Fix (SPA/Static):
<head>
<title>Page Title | Brand</title>
<meta name="description" content="Compelling description..." />
</head>
SEO-002: No Sitemap
Issue: Missing public/sitemap.xml
Impact: Search engines may not discover all pages
Fix: Create sitemap or use next-sitemap package
npm install next-sitemap
SEO-003: Missing OpenGraph Images
Pages affected: All Issue: No og:image set, social shares look empty Impact: Poor social media engagement Fix:
openGraph: {
images: [{ url: '/og-image.png', width: 1200, height: 630 }],
},
};
High Priority
SEO-004: Images Missing Alt Text
Files:
src/components/Hero.tsx:23-<img src="/hero.jpg" />src/components/ProductCard.tsx:15- `` Count: 12 images without alt text Fix: Add descriptive alt text to all images
SEO-005: No Structured Data
Issue: Missing JSON-LD schema markup Impact: No rich snippets in search results Fix:
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "Organization",
"name": "Your Company",
"url": "https://your-site.com"
})}
</script>
SEO-006: Multiple H1 Tags
File: src/app/page.tsx
Issue: 3 H1 tags on homepage
Fix: Use only one H1, convert others to H2
Medium Priority
SEO-007: Non-Descriptive URLs
Examples:
/p/123→/products/blue-widget/c/5→/category/electronicsFix: Use descriptive, keyword-rich URLs
SEO-008: Missing Canonical URLs
Issue: No canonical tags on paginated content Risk: Duplicate content penalty Fix: Add canonical to all pages
SEO-009: Robots.txt Too Restrictive
Current:
User-agent: *
Disallow: /api/
Disallow: /admin/
Disallow: / # This blocks everything!
Fix: Remove Disallow: /
Page-by-Page Analysis
| Page | Title | Description | OG | Schema | Score |
|---|---|---|---|---|---|
| / | Yes | No | No | No | 3/10 |
| /about | Yes | Yes | No | No | 5/10 |
| /products | Yes | No | No | No | 3/10 |
| /blog/[slug] | Yes | Yes | Yes | Yes | 9/10 |
Checklist
Must Have
- Unique title per page
- Meta description per page
- Sitemap.xml
- Robots.txt (not blocking)
- Alt text on images
- Single H1 per page
- Mobile viewport meta
Should Have
- OpenGraph tags
- Twitter card tags
- JSON-LD structured data
- Canonical URLs
- Descriptive URLs
- Internal linking
Nice to Have
- Blog with regular content
- FAQ schema
- Breadcrumb schema
- Review schema (if applicable)
Tools for Verification
- Google Search Console - Monitor indexing
- Google Rich Results Test - Validate structured data
- Facebook Sharing Debugger - Test OG tags
- Twitter Card Validator - Test Twitter cards
## Execution Logging
After completing, append to `.claude/audits/EXECUTION_LOG.md`:
| [timestamp] | seo-auditor | [status] | [duration] | [findings] | [errors] |
## Output Verification
Before completing:
1. Verify `.claude/audits/AUDIT_SEO.md` was created
2. Verify file has content beyond headers
3. If no issues found, write "No SEO issues detected" (not empty file)
Focus on issues that affect search visibility. Include specific file locations and fixes.