Repository navigation
XP kudos: a live 馃憦 count on each plain-English XP entry - #262
Merged
Merged
Conversation
- /api/kudos (netlify/functions/kudos.mjs) keeps the counts as one JSON document in the "kudos" Netlify Blobs store, separate from site data. Known entries only, once per visitor per entry per day (an HMAC of IP, entry and day written with onlyIfNew; no IP stored), same-origin only, and ETag-checked writes so simultaneous kudos all count - The XP data moves to data/xp.mjs so the function and the card share it; xpId gives each entry a stable id from the fields that name it - composables/useKudos.js refreshes every 15s while the plain-English XP list is showing; buttons hide where the function isn't running - The service worker leaves /api/kudos alone (never a stale count) - Security tests with an in-memory store, hostile bodies in payloads.mjs, and an accessibility test of the buttons - The yoga teacher training line says "Graduate" (same as #261) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nginuw5wmUjUSkmQB1J3pS
# Conflicts: # components/AboutCard.vue
This was referenced Oct 25, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
In the About card's plain-English XP view, every entry now has a 馃憦 kudos button with a live count that all visitors share. A Netlify function counts the kudos and keeps them in a separate JSON document in Netlify Blobs, apart from the site's data.
Related Issue
None. Requested directly.
Changes Made
netlify/functions/kudos.mjs(/api/kudos):GETreturns{ counts }.POST { id }adds one kudos and returns{ id, count, counted }.counts) in the site-wide Netlify Blobs storekudos.onlyIfNew.POSTwhoseSec-Fetch-Sitesays another site is refused.onlyIfMatch) and retried, so kudos sent at the same moment are all counted.data/xp.mjs:xpIdgives each entry a stable id from the fields that name it, so rewording a line keeps its kudos.composables/useKudos.js:localStoragewhich entries this browser has already given kudos to.components/AboutCard.vue:public/sw.js: the service worker leaves/api/kudosalone, so a count is never an old cached copy.tests/security/kudos.test.mjsruns against an in-memory store. It covers: once a day per visitor, simultaneous kudos, hostile bodies (KUDOS_BODIESinpayloads.mjs) and unknown ids, cross-site requests, methods, and cleaning of stored data.tests/e2e/a11y.spec.mjscovers the buttons before and after a tap.@netlify/blobs.How to Test
npm test: 278 tests, including the new kudos tests.npm run generate.PLAYWRIGHT_CHROMIUM_PATH=/opt/pw-browsers/chromium npx playwright test tests/e2e/a11y.spec.mjs -g "About card|XP kudos" --project="Pixel 7" --project="Galaxy Tab S9 landscape". The browser path is only needed here; CI installs its own browser./#xpand hold the card for plain English.Additional Notes
data/xp.mjsmatches main's data exactly.readable/highlighttext fromcomponents/AboutCard.vue.data/xp.mjs.<TermText>) sits right next to the new button, so that merge may need a small hand fix too.馃 Generated with Claude Code
https://claude.ai/code/session_01Nginuw5wmUjUSkmQB1J3pS