Skip to content

Weekly leagues, friends and push notifications - #28

Merged
nannndev merged 1 commit into
mainfrom
claude/exciting-bell-qakqv7
Sep 30, 2026
Merged

nannndev merged 1 commit into
mainfrom
claude/exciting-bell-qakqv7

Conversation

@nannndev

Copy link
Copy Markdown
Owner

Summary

League (/league)

  • XP. Every stored run earns XP:
    • about 1 per 10 correct characters, scaled down when accuracy drops, and ×1.5 for verified Ranked runs;
    • capped at 60 per run and 800 per day;
    • counted once per run, keyed by run id in league_xp.
  • Groups. The first XP of the week puts a player in a group of up to 30 at their division.
  • Weekly settlement. Top 5 move up and bottom 5 move down (groups of 10 or more), across Bronze → Silver → Gold → Diamond. A player's week is settled the first time they are seen in the new week, so no cron is needed.
  • UI.
    • The group table shows promotion and demotion zones and highlights your row.
    • The page shows a countdown and a banner with last week's result.
    • Kap wears a division medal, a new medal look drawn in both 2D and 3D.
  • Results screen. A chip shows "+N XP · Silver league".

Friends

  • One-way follows. Follow from a profile page (which now shows follower and following counts) or by searching a GitHub username or name.
  • A friends board ranks you and everyone you follow by weekly XP, with each player's best WPM this week.
  • A feed of recent runs by people you follow.

Push

  • Settings → Notifications turns on Web Push for the device, with separate toggles for streak and league.
  • A daily Vercel Cron runs at 12:00 UTC (19:00 WIB). It reminds players whose streak would break tonight, using their own time zone.
  • Being overtaken in your league sends a nudge.
  • The service worker imports public/push-sw.js, which handles push events and notification clicks.
  • The tab-only reminder stays quiet when push already covers the streak.

Plumbing

  • api/social.ts and api/push.ts bring the total to 10 of 12 functions. The shared route() helper handles CORS, method checks, auth and errors.
  • JWTs are now cached for 10 minutes, because Appwrite rate-limits createJWT.
  • scripts/setup-appwrite-social.mjs (npm run setup:social) creates the collections and adds a profile name index for search.
  • npm run setup:push-keys prints the VAPID keys and CRON_SECRET.
  • appwrite/schema.md documents the new collections.

Setup needed after merge

  1. npm run setup:social
  2. npm run setup:push-keys, then add VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT and CRON_SECRET in Vercel and redeploy.

Test plan

  • vitest: 207 tests pass. New ones cover league rules, joining and settling, the daily cap, overtakes, group filling, follows, search, the friends board and feed, push subscriptions and the streak cron, all run against an in-memory Appwrite fake.
  • tsc -b, the API typecheck and the build pass.
  • Browser check with the API and Appwrite mocked:
    • League page on desktop and mobile;
    • Friends search and Follow;
    • the feed;
    • the Settings Notifications card.

🤖 Generated with Claude Code

https://claude.ai/code/session_018xNjY7412Rp5bFuw5h69yu


Generated by Claude Code

League: every stored run earns XP (about one per ten correct characters,
less when sloppy, 1.5x when Ranked verifies it; capped per run and per day,
and counted once per run). The first XP of a week puts you in a group of up
to 30 at your division; when the week ends the top 5 move up and the bottom
5 move down (Bronze, Silver, Gold, Diamond), settled the next time you are
seen. /league shows your group with promotion and demotion zones, a
countdown, last week's result and Kap wearing your division medal; the
results screen shows the XP a run earned.

Friends: follow anyone from their profile or by searching GitHub usernames;
a friends board ranks you and the people you follow by weekly XP and best
speed, and a feed shows their recent runs.

Push: Settings turns on Web Push per device. A daily Vercel Cron (12:00 UTC,
19:00 WIB) reminds players whose streak breaks tonight, in their time zone,
and being overtaken in your league sends a nudge. The tab-only reminder
steps aside when push covers it.

New serverless functions: api/social.ts and api/push.ts (10 of 12). Needs
npm run setup:social and the VAPID/CRON env vars (npm run setup:push-keys).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018xNjY7412Rp5bFuw5h69yu
@vercel

vercel Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
codetype Ready Ready Preview Sep 30, 2026 4:14am UTC

@nannndev
nannndev merged commit 2c32fd8 into main Sep 30, 2026
2 checks passed

This branch was successfully deployed

1 active deployment
Preview — 895d2d8b Deployed Sep 30, 2026 by vercel[bot]
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.

2 participants