For AI agents: a documentation index is available at /llms.txt — markdown versions of all pages are available by appending .md to any URL path.
Skip to content

Scoring API

The scoring module is available as a pure function for programmatic consumers. It takes a ReportResult from runChecks and returns a standalone ScoreResult with the overall score, per-category breakdowns, interaction diagnostics, and fix suggestions.

Compute a score

ts
import { runChecks, computeScore } from 'afdocs';

const report = await runChecks('https://docs.example.com');
const score = computeScore(report);

console.log(score.overall); // 72
console.log(score.grade); // 'C'
console.log(score.categoryScores);
// { 'content-discoverability': { score: 80, grade: 'B' }, ... }
// Categories may have null score/grade when all checks lack sufficient data
console.log(score.diagnostics); // [{ id: 'markdown-undiscoverable', severity: 'warning', ... }]
console.log(score.resolutions); // { 'llms-txt-directive-html': 'Add a visually-hidden element...' }

computeScore is a pure function. It does not modify the report or make any network requests. Composition is the consumer's responsibility: the CLI formatters compose runChecks and computeScore; external consumers call them separately.

Import from the subpath

You can also import from the dedicated scoring subpath:

ts
import { computeScore } from 'afdocs/scoring';

This is the same function; the subpath is provided for consumers who want a narrower import.

ScoreResult

computeScore returns a ScoreResult with these fields:

FieldTypeDescription
overallnumberThe overall score (0-100)
gradeGradeLetter grade (A+, A, B, C, D, F)
categoryScoresRecord<string, CategoryScore>Per-category score and grade. score and grade are null when all checks in the category are notApplicable (insufficient data).
checkScoresRecord<string, CheckScore>Per-check scoring details (weight, coefficient, proportion, earned score, scoreDisplayMode)
diagnosticsDiagnostic[]Interaction diagnostics that fired
capScoreCapScore cap that was applied (present only when a cap reduced the score)
resolutionsRecord<string, string>Fix suggestions keyed by check ID
tagScoresRecord<string, TagScore>Per-tag aggregate scores (present when curated pages have tags)

Each CheckScore includes a scoreDisplayMode field ("numeric" or "notApplicable"). When automatic page discovery finds fewer than 5 pages, page-level checks are marked "notApplicable" and excluded from overall and category score calculations. See Insufficient data for details.

TagScore

When curated pages have tags, each TagScore contains the aggregate score plus a per-check breakdown showing exactly which checks contributed and how each page fared:

FieldTypeDescription
scorenumberAggregate score for this tag (0-100)
gradeGradeLetter grade
pageCountnumberNumber of pages tagged with this tag
checksTagCheckBreakdown[]Per-check breakdown with weight, proportion, and page statuses

Each TagCheckBreakdown contains:

FieldTypeDescription
checkIdstringThe check ID
categorystringThe check's category
weightnumberThe check's effective weight in the scoring system
proportionnumber0-1 proportion earned for this tag's pages
pagesArray<{ url: string; status: string }>Per-page status within this check
ts
const score = computeScore(report);
if (score.tagScores) {
  for (const [tag, tagScore] of Object.entries(score.tagScores)) {
    console.log(`${tag}: ${tagScore.score}/100 (${tagScore.grade})`);
    for (const check of tagScore.checks) {
      if (check.proportion < 1) {
        const failing = check.pages.filter((p) => p.status === 'fail');
        console.log(`  ${check.checkId}: ${failing.length} failing pages`);
      }
    }
  }
}

Grade conversion

If you need to convert a numeric score to a letter grade independently:

ts
import { toGrade } from 'afdocs';

toGrade(92); // 'A'
toGrade(100); // 'A+'
toGrade(55); // 'F'

Types

ts
import type {
  ScoreResult,
  CheckScore,
  CategoryScore,
  TagScore,
  TagCheckBreakdown,
  ScoreCap,
  Diagnostic,
  DiagnosticSeverity, // 'info' | 'warning' | 'critical'
  Grade, // 'A+' | 'A' | 'B' | 'C' | 'D' | 'F'
  ScoreDisplayMode, // 'numeric' | 'notApplicable'
} from 'afdocs';

For how the score is calculated (weights, coefficients, caps, proportional scoring), see Score Calculation.