
Seo Fundamentals
Audit public HTML, JSX, and TSX pages in your repo for titles, meta descriptions, Open Graph tags, heading structure, and image alt text before you ship or iterate on discoverability.
Overview
seo-fundamentals is an agent skill for the Launch phase that runs a local Python audit on public HTML and page components for meta tags, Open Graph, headings, and image alt text.
Install
npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill seo-fundamentalsWhat is this skill?
- Scans HTML plus React JSX/TSX page components while skipping tests, docs, and utility modules
- Verifies title tags, meta descriptions, and Open Graph tags for search and social sharing
- Validates heading hierarchy and image alt attributes for accessibility-aligned SEO
- Includes a bundled Python seo_checker.py you run against a project path for structured audit output
Adoption & trust: 838 installs on skills.sh; 40.1k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are about to ship or refresh pages but have no systematic way to catch missing titles, weak descriptions, broken heading order, or images without alt text across JSX and HTML routes.
Who is it for?
Indie founders and solo devs with React or static sites who want a quick, repo-local on-page SEO pass before publishing.
Skip if: Teams that only need off-page SEO, paid search, or full-site crawl analytics without touching page source in the repository.
When should I use this skill?
Before publishing or updating public HTML, JSX, or TSX routes when you need meta tags, OG tags, headings, and alt attributes verified.
What do I get? / Deliverables
You get a focused SEO issue list scoped to likely public pages so you can fix metadata and structure in the next editing pass.
- Structured SEO audit output from seo_checker.py
- Actionable list of on-page SEO and alt-text issues
Recommended Skills
Journey fit
On-page SEO checks belong on the Launch shelf because they improve how crawlers and social previews interpret pages you are already publishing. The checker targets public-facing page files and classic on-page SEO signals, which maps directly to the seo subphase rather than broader distribution or geo tactics.
How it compares
Use as a repo-local page checker instead of guessing SEO health from ad-hoc Lighthouse runs alone.
Common Questions / FAQ
Who is seo-fundamentals for?
Solo builders and small teams shipping web apps or content sites who want their agent to scan real page files for basic on-page SEO and accessibility-related image tags.
When should I use seo-fundamentals?
Use it in Launch when polishing SEO before go-live, after adding new marketing routes, or when Grow content updates need a quick metadata and heading sanity check on public JSX or HTML pages.
Is seo-fundamentals safe to install?
It is a read-only filesystem scan via a Python script in your project; review the Security Audits panel on this page and inspect the script before running it in CI or on sensitive repos.
SKILL.md
READMESKILL.md - Seo Fundamentals
#!/usr/bin/env python3 """ SEO Checker - Search Engine Optimization Audit Checks HTML/JSX/TSX pages for SEO best practices. PURPOSE: - Verify meta tags, titles, descriptions - Check Open Graph tags for social sharing - Validate heading hierarchy - Check image accessibility (alt attributes) WHAT IT CHECKS: - HTML files (actual web pages) - JSX/TSX files (React page components) - Only files that are likely PUBLIC pages Usage: python seo_checker.py <project_path> """ import sys import json import re from pathlib import Path from datetime import datetime # Fix Windows console encoding try: sys.stdout.reconfigure(encoding='utf-8', errors='replace') except: pass # Directories to skip SKIP_DIRS = { 'node_modules', '.next', 'dist', 'build', '.git', '.github', '__pycache__', '.vscode', '.idea', 'coverage', 'test', 'tests', '__tests__', 'spec', 'docs', 'documentation', 'examples' } # Files to skip (not pages) SKIP_PATTERNS = [ 'config', 'setup', 'util', 'helper', 'hook', 'context', 'store', 'service', 'api', 'lib', 'constant', 'type', 'interface', 'mock', '.test.', '.spec.', '_test.', '_spec.' ] def is_page_file(file_path: Path) -> bool: """Check if this file is likely a public-facing page.""" name = file_path.name.lower() stem = file_path.stem.lower() # Skip utility/config files if any(skip in name for skip in SKIP_PATTERNS): return False # Check path - pages in specific directories are likely pages parts = [p.lower() for p in file_path.parts] page_dirs = ['pages', 'app', 'routes', 'views', 'screens'] if any(d in parts for d in page_dirs): return True # Filename indicators for pages page_names = ['page', 'index', 'home', 'about', 'contact', 'blog', 'post', 'article', 'product', 'landing', 'layout'] if any(p in stem for p in page_names): return True # HTML files are usually pages if file_path.suffix.lower() in ['.html', '.htm']: return True return False def find_pages(project_path: Path) -> list: """Find page files to check.""" patterns = ['**/*.html', '**/*.htm', '**/*.jsx', '**/*.tsx'] files = [] for pattern in patterns: for f in project_path.glob(pattern): # Skip excluded directories if any(skip in f.parts for skip in SKIP_DIRS): continue # Check if it's likely a page if is_page_file(f): files.append(f) return files[:50] # Limit to 50 files def check_page(file_path: Path) -> dict: """Check a single page for SEO issues.""" issues = [] try: content = file_path.read_text(encoding='utf-8', errors='ignore') except Exception as e: return {"file": str(file_path.name), "issues": [f"Error: {e}"]} # Detect if this is a layout/template file (has Head component) is_layout = 'Head>' in content or '<head' in content.lower() # 1. Title tag has_title = '<title' in content.lower() or 'title=' in content or 'Head>' in content if not has_title and is_layout: issues.append("Missing <title> tag") # 2. Meta description has_description = 'name="description"' in content.lower() or 'name=\'description\'' in content.lower() if not has_description and is_layout: issues.append("Missing meta description") # 3. Open Graph tags has_og = 'og:' in content or 'property="og:' in content.lower() if not has_og and is_layout: issues.append("Missing Open Graph tags") # 4. Heading hierarchy - multiple H1s h1_matches = re.findall(r'<h1[^>]*>', content, re.I) if len(h1_matches) > 1: issues.append(f"Multiple H1 tags ({len(h1_matches)})") # 5. Images without alt img_pattern = r'<img[^>]+>' imgs = re.findall(img_pattern, content, re.I) for img in imgs: i