
Geo Fundamentals
- 1k installs
- 44k repo stars
- Updated July 27, 2026
- sickn33/antigravity-awesome-skills
GEO Fundamentals is a Python audit skill that checks public HTML and React page components for AI-search citation readiness—including structured data, author info, dates, and FAQ sections—for developers who publish index
About
GEO Fundamentals is a Generative Engine Optimization checker from sickn33/antigravity-awesome-skills that runs geo_checker.py against a project path to score public web content for AI citation readiness. The script analyzes HTML files and JSX/TSX React page components—explicitly not markdown developer docs—for structured data, author metadata, publish dates, and FAQ sections that AI engines use when generating answers. Developers run it before publishing landing pages, marketing sites, or product docs that will be indexed by ChatGPT, Perplexity, and similar systems. Usage is `python geo_checker.py <project_path>`, making it a pre-publish gate for content teams shipping indexable React or static HTML surfaces.
- Scans HTML and JSX/TSX files for Generative Engine Optimization signals
- Checks structured data, author info, publish dates, and FAQ sections
- Skips developer-only directories and config files automatically
- Outputs JSON report showing AI citation readiness per page
- Designed specifically for content indexed by ChatGPT, Perplexity, and similar engines
Geo Fundamentals by the numbers
- 1,010 all-time installs (skills.sh)
- +21 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #435 of 1,881 Marketing & SEO skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill geo-fundamentalsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1k |
|---|---|
| repo stars | ★ 44k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | sickn33/antigravity-awesome-skills ↗ |
How do you audit web pages for AI search citation readiness?
Audit public web pages and React components for AI-search visibility before publishing.
Who is it for?
Developers publishing public HTML or React pages who need a pre-ship audit for AI-engine citation readiness before content goes live.
Skip if: Developers auditing internal markdown docs, private repos, or backend-only code with no indexable public web surfaces.
When should I use this skill?
The user wants to check AI-search visibility, run a GEO audit, or validate structured data and FAQ sections on public web pages before publishing.
What you get
GEO audit report covering structured data, author metadata, dates, and FAQ coverage on indexable HTML and JSX/TSX files.
- GEO audit report
- citation-readiness findings
By the numbers
- Audits 2 public web file types: HTML and JSX/TSX
- Checks 4 citation signals: structured data, author info, dates, and FAQ sections
Files
GEO Fundamentals
Optimization for AI-powered search engines.
---
1. What is GEO?
GEO = Generative Engine Optimization
| Goal | Platform |
|---|---|
| Be cited in AI responses | ChatGPT, Claude, Perplexity, Gemini |
SEO vs GEO
| Aspect | SEO | GEO |
|---|---|---|
| Goal | #1 ranking | AI citations |
| Platform | AI engines | |
| Metrics | Rankings, CTR | Citation rate |
| Focus | Keywords | Entities, data |
---
2. AI Engine Landscape
| Engine | Citation Style | Opportunity |
|---|---|---|
| Perplexity | Numbered [1][2] | Highest citation rate |
| ChatGPT | Inline/footnotes | Custom GPTs |
| Claude | Contextual | Long-form content |
| Gemini | Sources section | SEO crossover |
---
3. RAG Retrieval Factors
How AI engines select content to cite:
| Factor | Weight |
|---|---|
| Semantic relevance | ~40% |
| Keyword match | ~20% |
| Authority signals | ~15% |
| Freshness | ~10% |
| Source diversity | ~15% |
---
4. Content That Gets Cited
| Element | Why It Works |
|---|---|
| Original statistics | Unique, citable data |
| Expert quotes | Authority transfer |
| Clear definitions | Easy to extract |
| Step-by-step guides | Actionable value |
| Comparison tables | Structured info |
| FAQ sections | Direct answers |
---
5. GEO Content Checklist
Content Elements
- [ ] Question-based titles
- [ ] Summary/TL;DR at top
- [ ] Original data with sources
- [ ] Expert quotes (name, title)
- [ ] FAQ section (3-5 Q&A)
- [ ] Clear definitions
- [ ] "Last updated" timestamp
- [ ] Author with credentials
Technical Elements
- [ ] Article schema with dates
- [ ] Person schema for author
- [ ] FAQPage schema
- [ ] Fast loading (< 2.5s)
- [ ] Clean HTML structure
---
6. Entity Building
| Action | Purpose |
|---|---|
| Google Knowledge Panel | Entity recognition |
| Wikipedia (if notable) | Authority source |
| Consistent info across web | Entity consolidation |
| Industry mentions | Authority signals |
---
7. AI Crawler Access
Key AI User-Agents
| Crawler | Engine |
|---|---|
| GPTBot | ChatGPT/OpenAI |
| Claude-Web | Claude |
| PerplexityBot | Perplexity |
| Googlebot | Gemini (shared) |
Access Decision
| Strategy | When |
|---|---|
| Allow all | Want AI citations |
| Block GPTBot | Don't want OpenAI training |
| Selective | Allow some, block others |
---
8. Measurement
| Metric | How to Track |
|---|---|
| AI citations | Manual monitoring |
| "According to [Brand]" mentions | Search in AI |
| Competitor citations | Compare share |
| AI-referred traffic | UTM parameters |
---
9. Anti-Patterns
| ❌ Don't | ✅ Do |
|---|---|
| Publish without dates | Add timestamps |
| Vague attributions | Name sources |
| Skip author info | Show credentials |
| Thin content | Comprehensive coverage |
---
Remember: AI cites content that's clear, authoritative, and easy to extract. Be the best answer.
---
Script
| Script | Purpose | Command |
|---|---|---|
scripts/geo_checker.py | GEO audit (AI citation readiness) | python scripts/geo_checker.py <project_path> |
When to Use
This skill is applicable to execute the workflow or actions described in the overview.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
#!/usr/bin/env python3
"""
GEO Checker - Generative Engine Optimization Audit
Checks PUBLIC WEB CONTENT for AI citation readiness.
PURPOSE:
- Analyze pages that will be INDEXED by AI engines (ChatGPT, Perplexity, etc.)
- Check for structured data, author info, dates, FAQ sections
- Help content rank in AI-generated answers
WHAT IT CHECKS:
- HTML files (actual web pages)
- JSX/TSX files (React page components)
- NOT markdown files (those are developer docs, not public content)
Usage:
python geo_checker.py <project_path>
"""
import sys
import re
import json
from pathlib import Path
# Fix Windows console encoding
try:
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
except AttributeError:
pass
# Directories to skip (not public content)
SKIP_DIRS = {
'node_modules', '.next', 'dist', 'build', '.git', '.github',
'__pycache__', '.vscode', '.idea', 'coverage', 'test', 'tests',
'__tests__', 'spec', 'docs', 'documentation'
}
# Files to skip (not public pages)
SKIP_FILES = {
'jest.config', 'webpack.config', 'vite.config', 'tsconfig',
'package.json', 'package-lock', 'yarn.lock', '.eslintrc',
'tailwind.config', 'postcss.config', 'next.config'
}
def is_page_file(file_path: Path) -> bool:
"""Check if this file is likely a public-facing page."""
name = file_path.stem.lower()
# Skip config/utility files
if any(skip in name for skip in SKIP_FILES):
return False
# Skip test files
if name.endswith('.test') or name.endswith('.spec'):
return False
if name.startswith('test_') or name.startswith('spec_'):
return False
# Likely page indicators
page_indicators = ['page', 'index', 'home', 'about', 'contact', 'blog',
'post', 'article', 'product', 'service', 'landing']
# Check if it's in a pages/app directory (Next.js, etc.)
parts = [p.lower() for p in file_path.parts]
if 'pages' in parts or 'app' in parts or 'routes' in parts:
return True
# Check filename indicators
if any(ind in name for ind in page_indicators):
return True
# HTML files are usually pages
if file_path.suffix.lower() == '.html':
return True
return False
def find_web_pages(project_path: Path) -> list:
"""Find public-facing web pages only."""
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[:30] # Limit to 30 pages
def check_page(file_path: Path) -> dict:
"""Check a single web page for GEO elements."""
try:
content = file_path.read_text(encoding='utf-8', errors='ignore')
except Exception as e:
return {'file': str(file_path.name), 'passed': [], 'issues': [f"Error: {e}"], 'score': 0}
issues = []
passed = []
# 1. JSON-LD Structured Data (Critical for AI)
if 'application/ld+json' in content:
passed.append("JSON-LD structured data found")
if '"@type"' in content:
if 'Article' in content:
passed.append("Article schema present")
if 'FAQPage' in content:
passed.append("FAQ schema present")
if 'Organization' in content or 'Person' in content:
passed.append("Entity schema present")
else:
issues.append("No JSON-LD structured data (AI engines prefer structured content)")
# 2. Heading Structure
h1_count = len(re.findall(r'<h1[^>]*>', content, re.I))
h2_count = len(re.findall(r'<h2[^>]*>', content, re.I))
if h1_count == 1:
passed.append("Single H1 heading (clear topic)")
elif h1_count == 0:
issues.append("No H1 heading - page topic unclear")
else:
issues.append(f"Multiple H1 headings ({h1_count}) - confusing for AI")
if h2_count >= 2:
passed.append(f"{h2_count} H2 subheadings (good structure)")
else:
issues.append("Add more H2 subheadings for scannable content")
# 3. Author Attribution (E-E-A-T signal)
author_patterns = ['author', 'byline', 'written-by', 'contributor', 'rel="author"']
has_author = any(p in content.lower() for p in author_patterns)
if has_author:
passed.append("Author attribution found")
else:
issues.append("No author info (AI prefers attributed content)")
# 4. Publication Date (Freshness signal)
date_patterns = ['datePublished', 'dateModified', 'datetime=', 'pubdate', 'article:published']
has_date = any(re.search(p, content, re.I) for p in date_patterns)
if has_date:
passed.append("Publication date found")
else:
issues.append("No publication date (freshness matters for AI)")
# 5. FAQ Section (Highly citable)
faq_patterns = [r'<details', r'faq', r'frequently.?asked', r'"FAQPage"']
has_faq = any(re.search(p, content, re.I) for p in faq_patterns)
if has_faq:
passed.append("FAQ section detected (highly citable)")
# 6. Lists (Structured content)
list_count = len(re.findall(r'<(ul|ol)[^>]*>', content, re.I))
if list_count >= 2:
passed.append(f"{list_count} lists (structured content)")
# 7. Tables (Comparison data)
table_count = len(re.findall(r'<table[^>]*>', content, re.I))
if table_count >= 1:
passed.append(f"{table_count} table(s) (comparison data)")
# 8. Entity Recognition (E-E-A-T signal) - NEW 2025
entity_patterns = [
r'"@type"\s*:\s*"Organization"',
r'"@type"\s*:\s*"LocalBusiness"',
r'"@type"\s*:\s*"Brand"',
r'itemtype.*schema\.org/(Organization|Person|Brand)',
r'rel="author"'
]
has_entity = any(re.search(p, content, re.I) for p in entity_patterns)
if has_entity:
passed.append("Entity/Brand recognition (E-E-A-T)")
# 9. Original Statistics/Data (AI citation magnet) - NEW 2025
stat_patterns = [
r'\d+%', # Percentages
r'\$[\d,]+', # Dollar amounts
r'study\s+(shows|found)', # Research citations
r'according to', # Source attribution
r'data\s+(shows|reveals)', # Data-backed claims
r'\d+x\s+(faster|better|more)', # Comparison stats
r'(million|billion|trillion)', # Large numbers
]
stat_matches = sum(1 for p in stat_patterns if re.search(p, content, re.I))
if stat_matches >= 2:
passed.append("Original statistics/data (citation magnet)")
# 10. Conversational/Direct answers - NEW 2025
direct_answer_patterns = [
r'is defined as',
r'refers to',
r'means that',
r'the answer is',
r'in short,',
r'simply put,',
r'<dfn'
]
has_direct = any(re.search(p, content, re.I) for p in direct_answer_patterns)
if has_direct:
passed.append("Direct answer patterns (LLM-friendly)")
# Calculate score
total = len(passed) + len(issues)
score = (len(passed) / total * 100) if total > 0 else 0
return {
'file': str(file_path.name),
'passed': passed,
'issues': issues,
'score': round(score)
}
def main():
target = sys.argv[1] if len(sys.argv) > 1 else "."
target_path = Path(target).resolve()
print("\n" + "=" * 60)
print(" GEO CHECKER - AI Citation Readiness Audit")
print("=" * 60)
print(f"Project: {target_path}")
print("-" * 60)
# Find web pages only
pages = find_web_pages(target_path)
if not pages:
print("\n[!] No public web pages found.")
print(" Looking for: HTML, JSX, TSX files in pages/app directories")
print(" Skipping: docs, tests, config files, node_modules")
output = {"script": "geo_checker", "pages_found": 0, "passed": True}
print("\n" + json.dumps(output, indent=2))
sys.exit(0)
print(f"Found {len(pages)} public pages to analyze\n")
# Check each page
results = []
for page in pages:
result = check_page(page)
results.append(result)
# Print results
for result in results:
status = "[OK]" if result['score'] >= 60 else "[!]"
print(f"{status} {result['file']}: {result['score']}%")
if result['issues'] and result['score'] < 60:
for issue in result['issues'][:2]: # Show max 2 issues
print(f" - {issue}")
# Average score
avg_score = sum(r['score'] for r in results) / len(results) if results else 0
print("\n" + "=" * 60)
print(f"AVERAGE GEO SCORE: {avg_score:.0f}%")
print("=" * 60)
if avg_score >= 80:
print("[OK] Excellent - Content well-optimized for AI citations")
elif avg_score >= 60:
print("[OK] Good - Some improvements recommended")
elif avg_score >= 40:
print("[!] Needs work - Add structured elements")
else:
print("[X] Poor - Content needs GEO optimization")
# JSON output
output = {
"script": "geo_checker",
"project": str(target_path),
"pages_checked": len(results),
"average_score": round(avg_score),
"passed": avg_score >= 60
}
print("\n" + json.dumps(output, indent=2))
sys.exit(0 if avg_score >= 60 else 1)
if __name__ == "__main__":
main()
Related skills
How it compares
Choose GEO Fundamentals over traditional SEO linters when the goal is AI-engine citation readiness rather than only Google SERP meta tags.
FAQ
Which file types does GEO Fundamentals audit?
GEO Fundamentals audits HTML files and JSX/TSX React page components via geo_checker.py. The checker explicitly excludes markdown files because those are developer docs, not public indexable web content targeted by AI search engines.
How do you run the GEO Fundamentals checker?
GEO Fundamentals runs with `python geo_checker.py <project_path>`. The script analyzes indexable public web content for structured data, author info, dates, and FAQ sections that improve citation readiness in ChatGPT and Perplexity.
Is Geo Fundamentals safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.