Skip to content

feat(comments): point an empty thread at the badge behind it - #40

Merged
michaeljolley merged 1 commit into
mainfrom
dev/mjolley/expert-succotash
Aug 7, 2026
Merged

feat(comments): point an empty thread at the badge behind it#40
michaeljolley merged 1 commit into
mainfrom
dev/mjolley/expert-succotash

Conversation

@michaeljolley

Copy link
Copy Markdown
Collaborator

What

An empty comment thread used to say "No replies yet. Yours would be the first." True, and it does nothing. Now it names the comment badge the reader is next in line for, with the real number attached.

  • No comment badge yet: "No replies yet. Yours would be the first, and it earns you First Reply I."
  • Already has tier one: "No replies yet. Yours would be the first, and you are 21 threads off First Reply II."
  • Signed out, or the family is finished: the plain line, unchanged.

Why

The thread with nothing in it is the one place where telling somebody what a reply is worth might actually get one written, and the site already knows the answer. badge_progress holds the same counter the grant triggers read, so the number quoted here cannot drift from the one that hands the badge over.

Nobody is told they are one reply off something they already have, which was the whole point of doing this against real progress rather than hardcoding a sentence about the badge.

How

nextStep(shelf, progress, family) is the shelf's own "next step" rule from shapeShelf, narrowed to a single family. Same rule, so the badge named on a thread and the plaque on a profile can never disagree, including the numeral.

Tier two counts distinct threads rather than raw replies, so unitFor maps the counter names to nouns a reader would say and the copy says "threads" where it means threads.

The lookup only runs on an empty thread for a signed in reader, which keeps two extra queries off every thread that already has replies. Every failure path returns null and the line falls back to the plain one: a nudge is a nicety and is never a reason for a thread to fail to load.

Files

  • src/lib/shelf.tsnextStep and unitFor
  • src/lib/badges.ts (new) — the one family read, degrading to null
  • src/pages/api/comments.ts — GET returns nudge, empty threads only
  • src/lib/thread.tsemptyLine, where the copy and the plural live
  • src/components/islands/CommentThread.tsx — renders it

Copy and counter nouns sit in the libs rather than the island because the arithmetic and the plurals are the parts worth testing, and both files already run under plain node.

Testing

15 new cases across tests/shelf.test.mjs and tests/thread.test.mjs. Full suite: 391 passing, 0 failing.

astro check could not run locally because the src/content submodule is empty in this worktree, so the touched TypeScript was type checked directly. CI has the submodule.

"No replies yet. Yours would be the first." is true and does nothing. The
thread with nothing in it is the one place where telling somebody what a
reply is worth might actually get one written, and the site already knows
the answer: badge_progress holds the same counter the grant triggers read.

So the empty line now carries it. Somebody with no comment badge is told a
reply earns First Reply I. Somebody who has it is told how many threads
they are off First Reply II, with the real number rather than a nudge in
general terms. Nobody is offered a badge they already have, and a reader
who is signed out or has finished the family gets the plain line back.

The rule is the shelf's own next step narrowed to one family, so the badge
named here and the plaque on the profile can never disagree. It only runs
on an empty thread for a signed in reader, which keeps two extra queries
off every thread that already has replies in it, and every failure path
returns null: a nudge is a nicety and is never a reason for a thread to
fail to load.

Copy lives in thread.ts and the counter nouns in shelf.ts, both because
the arithmetic and the plurals are the parts worth testing and both files
already run under plain node.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f5e5a689-2285-4421-b2b5-b348df97b055
@michaeljolley
michaeljolley merged commit 402d3c8 into main Aug 7, 2026
11 of 12 checks passed
@michaeljolley
michaeljolley deleted the dev/mjolley/expert-succotash branch August 7, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant