Repository navigation
feat(website): club teaser in lesson one of an open course - #1630
Conversation
The gate names the club only when a course is locked, and most readers never climb that far: the bot's thirty-day funnel counted 1 club card against 56 new people, so a reader inside their first open course met no mention of the club at all. Lesson one now carries the teaser below the pager -- its words are the ladder spec's new SAY_CLUB_* consts (Russian in i18n), its button is the same start link the gate uses, and a reader already holding a paid key sees nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary by t27-beesChecked by the t27 compilert27c parse, parse-complete and typecheck on each changed .t27 file at
Read by the modelThis PR adds a club teaser on lesson 1 of open courses so readers encounter the subscription offer inside their first course, not only on locked-course gates. New spec constants Worth a look
Read: 4 files, +47 -3, the whole diff. Head |
feat(website): club teaser in lesson one of an open course (#1630) The gate names the club only when a course is locked, and most readers never climb that far: the bot's thirty-day funnel counted 1 club card against 56 new people, so a reader inside their first open course met no mention of the club at all. Lesson one now carries the teaser below the pager -- its words are the ladder spec's new SAY_CLUB_* consts (Russian in i18n), its button is the same start link the gate uses, and a reader already holding a paid key sees nothing. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
What
The club is the one subscription, and the site's own ladder page named it only when a course was locked. A reader inside their first open course -- the majority, per the bot's thirty-day funnel (1 club card seen against 56 new people) -- met no mention of it at all. Lesson one of an open course now carries the teaser.
How
SAY_CLUB_TITLE/SAY_CLUB_LINEinspecs/ladder/course-ladder.t27, with a test pinning the teaser's words apart from the gate's (SAY_CLUB_* != SAY_PAID_*): the gate answers "why is this locked", the teaser answers "what is next".i18n/course-ladder.ru.json(every key,{0}/digit parity held by the generator);courseLadder.generated.tsregenerated.Course.tsx:ClubTeaserbelow the lesson pager, reusing the gate'scourse-hero course-ladderclasses and the samestartLink(STEP.paid, route)button; rendered only on lesson 1, hidden while a key is still being checked and for readers already holding a valid paid key (useLaddernow returnsinClub).SAY_PAID_LATER).{ "version": 1, "head_sha": "7fc86ad6f5ba2ec3e550736e433e1abae9c4660c", "summary": "The ladder page named the club only on a locked course, so a reader inside their first open course never met it; lesson one now carries a teaser whose words live in the ladder spec and whose button is the same start link the gate uses.", "changes": [ "specs/ladder/course-ladder.t27: SAY_CLUB_TITLE and SAY_CLUB_LINE consts plus test the_teaser_speaks_for_itself_not_for_the_gate", "i18n/course-ladder.ru.json: Russian for both new keys", "src/lib/courseLadder.generated.ts: regenerated (18 words x 2 languages)", "src/pages/Course.tsx: useLadder returns inClub (valid.paid); new ClubTeaser below the lesson-one pager, hidden while checking and for paid-key holders" ], "tests": [ { "command": "npm run check:course-ladder", "status": "passed", "result": "generated file up to date with the spec", "evidence": "local run of this head in /tmp/tri-club-teaser/apps/website, 2026-10-13" }, { "command": "npm run test:course-ladder", "status": "passed", "result": "5 of 5 node tests pass, including EN/RU key parity and the mutation suite", "evidence": "local run of this head in /tmp/tri-club-teaser/apps/website, 2026-10-13" }, { "command": "npm run test:course", "status": "passed", "result": "42 of 42 course/lesson/cast tests pass", "evidence": "local run of this head in /tmp/tri-club-teaser/apps/website, 2026-10-13" }, { "command": "npm run check:course-pages", "status": "passed", "result": "course pages check and its node tests pass", "evidence": "local run of this head in /tmp/tri-club-teaser/apps/website, 2026-10-13" }, { "command": "npm run typecheck:ratchet", "status": "passed", "result": "179 errors across 26 files, baseline 179 across 26, no file gained type errors", "evidence": "local run of this head in /tmp/tri-club-teaser/apps/website, 2026-10-13; base comparison run on stashed pristine HEAD produced the identical 179-error set" } ], "limitations": [ "The teaser shows on lesson 1 of every open course including a paid rung the reader already holds the key for, suppressed only by the inClub check on that course's own key", "No phone screenshot taken: the teaser reuses the gate's existing course-hero course-ladder classes, so its layout is the layout the gate already ships" ], "tags": ["website", "courseLadder", "club"], "blog": { "title": "The one subscription, named where the reader actually is", "summary": "The site said the club's name only on courses a reader could not open, so everyone inside their first open course met silence where the money question lives. Lesson one now carries a teaser, and its words live in the ladder spec beside the gate's.", "outline": [ "The symptom in numbers: thirty days of the bot's funnel counted 56 new people, 1 of whom ever saw the club card, because on the site the club appeared only on the locked rung of the ladder.", "The asymmetry: the gate answers a question the locked reader asks, why is this closed, while the open-course reader asks what comes next, and no page answered that, so the teaser had to be new words, not a moved block.", "The mechanics: two consts in the ladder spec with a test pinning them apart from the gate's, a regenerated words file, and one small component under the lesson-one pager that reuses the gate's classes and its start link, hidden for anyone already holding a paid key." ] } }Companion to gHashTag/999-multibots-telegraf#3998 (the club row on the bot's main menu, merged).
🤖 Generated with Claude Code