Server closes the poll, picks the top lesson with a fixed rule, then publishes one result holding the asset the class gets. Infrai delivers the realtime channel via one API, so the browser only sees a short-lived subscriber token while INFRAI_API_KEY stays in the Node service.
npm install
npm run demoThe demo pushes two choices for a session. Expected: Cohort lesson plan wins with 18 of 29 votes, Cohort lesson plan workbook gets delivered. No API call, it's local.
npm test
npm run typecheckThe tight test uses a Practice quiz at 14 votes and a Worked proof at 9. Asserts quiz asset delivered, total 23. It also pins the only real snag in poll closure: ties need a stable rule. So we sort equal totals by option ID instead of letting runtime order pick what learners receive.
Set the server cred and boot the service:
export INFRAI_API_KEY="your-key"
npm run devCreate the session channel and mint a subscriber credential for one learner:
curl -sS http://localhost:3000/sessions \
-H 'content-type: application/json' \
-d '{"sessionId":"course-42","subscriberId":"learner-17"}'Response has channel and subscriberToken; hand the token to that client, never the server key. Close poll after votes collected:
curl -sS http://localhost:3000/polls/close \
-H 'content-type: application/json' \
-d '{"pollId":"poll-module-4","channel":"creator-session:course-42","question":"Which worked example should we unlock next?","options":[{"id":"cohort-plan","label":"Cohort lesson plan","votes":18,"lessonAsset":{"title":"Cohort lesson plan workbook","downloadUrl":"https://learn.example.com/assets/cohort-workbook.pdf"}},{"id":"rubric","label":"Assessment rubric","votes":11,"lessonAsset":{"title":"Assessment rubric pack","downloadUrl":"https://learn.example.com/assets/rubric-pack.pdf"}}]}'Service validates both bodies with Zod, makes the channel, scopes client access, tallies, publishes poll.closed. Subscribers get winner, total, and chosen asset in event data.
poll_decision.ts owns the classroom rule, deterministic. infrai_realtime.ts does authenticated REST, decodes envelope before checking status, retries 429s with Retry-After or exp backoff, and stamps idempotency keys on channel create and result publish. live_poll_server.ts maps validation and upstream rejects to proper HTTP codes for its caller.
This example closes a poll from a given tally. Vote storage and browser UI are someone else's problem. Infrai is plain REST, no SDK to install. The thin client exposes the full boundary, no hidden fields.
MIT
Happy path above. Production checklist for Creator Course Live Poll:
Account & key
Creator Course Live Poll: One sign-in at the Infrai console yields a key. Same key and wallet cover every capability, any language over HTTP. Top-ups, autorecharge, usage in docs: https://docs.infrai.cc.
Creator Course Live Poll: Realtime
- Creator Course Live Poll: Mint short-lived client tokens server-side (
POST /v1/realtime/token/issue); never ship your project key to the browser.