guide · computers

ABS Sort Pages: By Grade and Date, the Rules

ABS review listings default to newest-first; the secondary key is grade. URL params (?sort=grade|oldest|new) reach a /reviews/[sort].astro. The four tie-breakers and why we don't sort by score.

July 14, 2026 · By Alastair Fraser

A friendly retro robot at a long sort table with three stacks of review cards labeled A / B / C; within each stack the cards are arranged by score and date, while a small human figure inspects the top of stack A and approves the order.

The convention in one sentence

ABS review listings default to newest-first; the secondary key (tie-breaker) is the grade chip (A/B/C/D/F). Three URL params — ?sort=new, ?sort=grade, ?sort=oldest — flip the primary key. We don’t sort by score.

The “4” tie-breakers in order after grade:

  1. Grade (A-F, A highest)
  2. Score within the same grade (higher first)
  3. Date within the same grade+score (newest first)
  4. Slug (deterministic; ensures idempotent order)

The URL paths: /reviews/ is the default newest-first; /reviews/grade/ is highest grade; /reviews/oldest/ is oldest-first.

Why grade-first, not score-first

The intuition would be “sort by score because that’s what readers care about.” We don’t, for “3” reasons:

  1. Score is a continuous signal; grade is a discrete signal that reflects editorial weight. A “91” and a “92” might both be A; sorting by score would put “92” first, hiding the editorial judgment that both are A-grade.
  2. Score regresses to mean. Two reviews with similar scores (“87” and “89”) might have very different editorial import. Grade converts noise into signal.
  3. Readers relate to grade. “I want A-grade reviews” is a useful query; “I want reviews ≥87” is not.

The “91 <-> 92” swap example: under score-first sorting the “92” review ranks above the “91”; under grade-first, both end up adjacent, and the more recent one wins.

The three URL params

ParamPrimary keyTie-breakerWhen to use
(default)Date descGrade, then scoreHomepage, /reviews/ listing
?sort=grade (path /reviews/grade/)Grade descScore desc, then date desc”Show me the best stuff first”
?sort=oldest (path /reviews/oldest/)Date ascGrade, then scoreArchive-style, “show history”

A ?sort=score query param exists and is intentional — but it’s the lowest-priority param and we don’t promote it. A direct request still works for the operator or QA paths.

The Astro route

src/pages/reviews/[sort].astro handles the dynamic case. The static /reviews/index.astro handles the default. The [sort].astro validates against the “3” accepted values (new, grade, oldest), throws otherwise.

// src/pages/reviews/[sort].astro (simplified)
export async function getStaticPaths() {
  return [
    { params: { sort: 'new' } },
    { params: { sort: 'grade' } },
    { params: { sort: 'oldest' } },
  ];
}
const sort = Astro.params.sort;
const sorted = sortReviews(sort);
---
{sorted.map(r => <ReviewCard post={r} />)}

The sortReviews() helper lives in a shared utils file and is reused by /reviews/index.astro and /category/[cat]/[sort].astro paths.

The tie-breakers, applied

When two reviews are equally graded, the sort picks by score. The score is the sum of the “4” rubric dimensions (signal, frame, evidence, fit) and ranges “0-100”. The published review carries the score in its frontmatter; the home page displays a band (good/mid/low) rather than the raw number.

When two reviews tie on score, the sort picks by date (newer first within a tie). This is the only place date acts as a primary criterion.

What we don’t do

  • Sort by raw score as primary key. Grade-first prevents the regression-to-mean problem.
  • Sort by author. ABS has a single editorial voice; author sort would be uniform.
  • Sort by title alphabetically. Random for editorial consumption.
  • Sort by tag count. A review with “0” tags and a “well-known” product would rank below a tag-heavy but irrelevant review.
  • Add a sticky / pinned / featured-review state. All reviews sort uniformly.

Edge cases

“3” quirks in the data the sort handles:

  1. A review with no grade yet (in flight). The review still appears, sorted to the bottom (grade F is the placeholder; if the score is also missing, the date alone is the order).
  2. A review with a future pubDate (scheduled). The review appears at the top of newest-first until it goes live, then settles into the queue. We don’t artificially hide scheduled reviews; we surface the schedule.
  3. Slug collisions. The tie-breaker order has slug-last on purpose — deterministic / idempotent. Slug collisions shouldn’t happen given our authoring, but if one sneaks in, the order is reproducible.

What this saves

For the operator: no manual reordering. Adding a new review places it in the appropriate slot automatically.

For the reader: a consistent mental model. Grade-first / score-second / date-third is a tree of cognition — “I want A-grade, then I want the higher score in A, then I want the most recent.” Sort the same way every visit, and the reader learns to scan by grade first.

The verify

A one-liner that confirms the order:

curl -sS https://agenticbotsitter.com/reviews/grade/ | \
  grep -oE 'class="grade-[a-f]+' | head -20

Expected:

  • A-grades at the top, in date-desc within
  • Then B-grades, etc.
  • Total visible = ~“30” reviews today.

What NOT to do

  • Don’t add a ?sort=score button to the UI. The tie-breaker convention is enough.
  • Don’t add a “Random” sort. Random on a daily-visit mental model is jarring.
  • Don’t change the tie-breaker order in a minor release without rerunning the regression suite. The order has been stable since “2026-06”.
  • Don’t break the static vs dynamic path distinction. /reviews/index.astro always serves the default; /reviews/grade/ and /reviews/oldest/ are dynamic.

Sources

Last verified: 2026-07-14 against the live /reviews/ listing rendered at https://agenticbotsitter.com/reviews/.

Sources

#sort#reviews#grade#tie-breaker#convention

Submit a take

Have a different read on this? Drop a comment below — your email isn't published, and I read every one. Nothing leaves the site until I approve it.

Your email address will not be published. Required fields are marked.