SDK

Validation

15 rules. 100 points. One score per page.

validateMetadata(metadata, options?)

Validate a metadata object against all 15 SEO rules. Returns a structured result with score, grade, and detailed findings.

Basic usagetypescript
import { validateMetadata } from 'indxel'

const result = validateMetadata({
  title: 'Pricing — Simple plans for developers',
  description: 'Start free. Upgrade when you need more.',
  openGraph: {
    title: 'Pricing',
    description: 'Start free.',
    images: [{ url: '/og-pricing.png' }],
  },
  twitter: { card: 'summary_large_image' },
  alternates: { canonical: 'https://mysaas.com/pricing' },
})

console.log(result.score)    // 85
console.log(result.grade)    // 'B'
console.log(result.errors)   // [{ id: 'description-length', message: '...', weight: 10 }]
console.log(result.warnings) // [{ id: 'alternates-hreflang', message: '...', weight: 5 }]
console.log(result.passed)   // [{ id: 'title-present', ... }, ...]

Strict mode

In strict mode, warnings are promoted to errors. Useful for CI/CD where you want zero tolerance.

typescript
const result = validateMetadata(metadata, { strict: true })
// Warnings now count as errors (weight = 0 instead of half)

Return type

ValidationResulttypescript
type ValidationResult = {
  score: number       // 0-100
  grade: string       // 'A' | 'B' | 'C' | 'D' | 'F'
  errors: RuleFinding[]
  warnings: RuleFinding[]
  passed: RuleFinding[]
}

type RuleFinding = {
  id: string          // Rule identifier (e.g. 'title-length')
  message: string     // Human-readable explanation
  weight: number      // Points this rule is worth
}

Scoring Algorithm

Each rule has a weight. The total possible is 100 points.

  • Pass — full weight awarded
  • Warning — half weight awarded
  • Error — 0 points
GradeScore
A>= 90
B>= 80
C>= 70
D>= 60
F< 60

All 15 Rules

RuleWeightCheck
title-present5Page has a title tag
title-length10Title is 50-60 characters
description-present5Meta description exists
description-length10Description is 120-160 characters
og-image10OpenGraph image is set
og-title5OpenGraph title is set
og-description5OpenGraph description is set
canonical-url10Canonical URL present and absolute
structured-data-present10At least one JSON-LD block
structured-data-valid5JSON-LD has @context and @type
robots-not-blocking5Page not accidentally noindexed
twitter-card5Twitter card type configured
alternates-hreflang5Hreflang alternates declared
viewport-meta5Viewport meta tag present
favicon5Favicon referenced

Total: 100 points

All weights sum to 100. A perfect score means every rule passes.

Using in CI/CD

The CLI's check --ci command uses validateMetadata() internally. For programmatic use in custom scripts:

Custom validation scripttypescript
import { validateMetadata } from 'indxel'

const result = validateMetadata(pageMetadata, { strict: true })

if (result.errors.length > 0) {
  console.error(`SEO check failed: ${result.score}/100 (${result.grade})`)
  result.errors.forEach(e => console.error(`  ✗ ${e.id}: ${e.message}`))
  process.exit(1)
}

console.log(`SEO check passed: ${result.score}/100 (${result.grade})`)