astro-seo-validator
Validate SEO elements (meta tags, hreflang, canonical, sitemap) for Astro pages
- Category: discovered
- Tags: github, community
- Version: 1.0.0
- Author: walid
- Downloads: 0
- Updated: 2025-11-22
Download the latest version (v1.0.0) from this page.
SKILL.md
---
name: astro-seo-validator
description: Validate SEO elements (meta tags, hreflang, canonical, sitemap) for Astro pages
activation:
keywords:
- seo validation
- meta tags
- hreflang
- canonical url
- sitemap
triggers:
- "check seo"
- "validate seo"
auto_load_project: cv-astro
---
# Astro SEO Validator
## What This Is
Validate SEO elements in Astro pages:
- Meta tags (title, description, OG, Twitter)
- Hreflang tags for multi-language
- Canonical URLs
- Structured data (JSON-LD)
- Sitemap generation and validation
**For**: CV_Astro project (Swiss & Spanish SEO)
---
## When to Activate
Auto-activates when keywords detected:
- "validate seo"
- "check meta tags"
- "verify hreflang"
- "sitemap validation"
Manual: `npm run check:seo`
---
## SEO Validation Checklist
### 1. Meta Tags
**Required on every page**:
```astro
<head>
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="description" content={description} />
<meta name="author" content="Oriol Macías" />
<meta name="robots" content="index, follow" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={Astro.url} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
<meta property="twitter:image" content={image} />
</head>
```
---
### 2. Hreflang Tags
**For multi-language sites**:
```astro
<head>
<!-- English (default) -->
<link rel="alternate" hreflang="en" href="https://oriolmacias.dev/" />
<!-- Spanish -->
<link rel="alternate" hreflang="es" href="https://oriolmacias.dev/es/" />
<!-- French -->
<link rel="alternate" hreflang="fr" href="https://oriolmacias.dev/fr/" />
<!-- Default fallback -->
<link rel="alternate" hreflang="x-default" href="https://oriolmacias.dev/" />
</head>
```
---
### 3. Canonical URL
**Every page must have one**:
```astro
<head>
<link rel="canonical" href={Astro.url.href} />
</head>
```
---
### 4. Sitemap Validation
**Check**:
- [ ] `/sitemap.xml` exists
- [ ] All pages included
- [ ] Hreflang alternates for each URL
- [ ] Valid XML syntax
- [ ] Submitted to Google Search Console
---
## Validation Script
**File**: `scripts/validate-seo.js`
```javascript
import fs from 'fs';
import { glob } from 'glob';
const REQUIRED_META_TAGS = [
'title',
'description',
'og:title',
'og:description',
'og:image',
'twitter:card'
];
async function validateSEO() {
const pages = await glob('src/pages/**/*.astro');
const errors = [];
for (const page of pages) {
const content = fs.readFileSync(page, 'utf-8');
// Check meta tags
REQUIRED_META_TAGS.forEach(tag => {
const hasTag = tag === 'title'
? content.includes('<title>')
: content.includes(`name="${tag}"`) || content.includes(`property="${tag}"`);
if (!hasTag) {
errors.push(`${page}: Missing ${tag}`);
}
});
// Check canonical
if (!content.includes('rel="canonical"')) {
errors.push(`${page}: Missing canonical URL`);
}
// Check hreflang
if (!content.includes('hreflang')) {
errors.push(`${page}: Missing hreflang tags`);
}
}
// Check sitemap
if (!fs.existsSync('public/sitemap.xml')) {
errors.push('Sitemap missing: public/sitemap.xml');
}
// Report
if (errors.length > 0) {
console.error('❌ SEO Validation Errors:\n');
errors.forEach(err => console.error(` ${err}`));
process.exit(1);
} else {
console.log('✅ All SEO elements valid');
}
}
validateSEO();
```
**Add to package.json**:
```json
{
"scripts": {
"check:seo": "node scripts/validate-seo.js"
}
}
```
---
## Quick Reference
| Element | Required | Example |
|---------|----------|---------|
| **Title** | ✅ | `<title>{title}</title>` |
| **Description** | ✅ | `<meta name="description" content={desc} />` |
| **Canonical** | ✅ | `<link rel="canonical" href={url} />` |
| **Hreflang** | ✅ (i18n) | `<link rel="alternate" hreflang="es" />` |
| **OG Tags** | ✅ | `<meta property="og:title" />` |
| **Twitter** | ✅ | `<meta property="twitter:card" />` |
| **Sitemap** | ✅ | `/sitemap.xml` |