Skip to content

Insights (privacy-safe usage counts and problem reports) + fix the iPhone freeze when launching Bit - #40

Merged
maidulcu merged 4 commits into
mainfrom
feature/insights
Nov 10, 2026
Merged

maidulcu merged 4 commits into
mainfrom
feature/insights

Conversation

@maidulcu

@maidulcu maidulcu commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Our own privacy-safe bug tracking and usage counts for the online edition (instead of Sentry or any third-party tracker). The free GitHub Pages edition sends nothing.

What it does

  • Daily counts, not people: POST /api/events adds 1 to day counters such as visits by device/OS/browser family, game version, mode, and features used (Play Together, Bit, Photo Mode, courses, quests, circuits, accounts…). Each is counted at most once per browser session.

  • Problem reports: POST /api/errors keeps three kinds:

    • 💥 error: uncaught errors and unhandled promise rejections;
    • 🧊 freeze: the game stopped drawing for more than 5 s while on screen (hidden-tab pauses are ignored);
    • 🙋 report: the new 🐞 Report a problem menu button, with a fixed list of categories (no typing).

    Each keeps the message, place, game version, browser/device family, screen size and the last 12 game steps (e.g. opened Bit's panel → Bit run). Identical reports are grouped per day and deleted after 90 days.

  • Stats page: stats.html (noindex, kept out of robots.txt) asks for the key and shows totals, devices, systems, browsers, modes, features, versions, visits per day and the problem list with steps.

Privacy

  • No cookies, no IDs, no fingerprinting, no IP addresses stored (held in memory for one minute for rate limiting).
  • Same-origin only, rate-limited, input whitelisted and length-capped.
  • GET /api/stats needs Authorization: Bearer $STATS_TOKEN. Without the token it's closed.
  • Only runs when site-config.json has "online": true and "insights": true. The copy in Git doesn't, so GitHub Pages never sends anything.
  • Privacy Policy: new section 6, "Anonymous usage counts and problem reports (online edition)", plus a line in the kids' summary. Version date unchanged (2026-11-10, same day). The Terms didn't change, so TERMS_VERSION is untouched.

Also: fix the iPhone freeze when launching Bit

Cause: iOS Safari has no Pointer Lock API, so document.exitPointerLock is undefined there. openRobotPanel() called it bare from inside the frame loop. The TypeError stopped frame() before it asked for the next frame, so the whole game froze and Bit sat at "Running… step 0". Trading with a villager and fainting in survival had the same bare call inside the loop.

Fix:

  • exitLock() guards every call.
  • frame() now asks for the next frame first, so one error can never stop the game.
  • New smoke check: no bare exitPointerLock() in src/.
  • sw.js → minicrafter-v29.

Reproduced and verified with Playwright WebKit, iPhone 13 (landscape) emulation and ?touch=1 against the dev server: place Bit, tap it, tap ▶ Run. Before the fix: the TypeError above and the game stuck at step 0. After it: Bit runs all 16 steps to "All done!".

Other changes

  • tools/deploy-site.sh uploads stats.html and the "insights": true config.
  • server/docker-compose.yml passes STATS_TOKEN; server/Dockerfile copies stats.mjs; server/README.md documents insights.

Testing

  • SMOKE_CHANNEL=chrome node tests/smoke.mjs: all checks pass, including the new ones:
    • a visit and a problem report (with steps) reach the dev server, and /api/stats refuses access without the key;
    • insights stay off in the free edition.
  • By hand against node server/dev.mjs: visit counts, a thrown error, a forced 6 s freeze and a "Bit isn't working" report all showed up with steps on stats.html (key dev). The free copy made no /api requests.
  • Already deployed to the online edition: /api/events returns 204 (403 from another origin), /api/stats returns 401 without the key and 200 with it, and a real visit landed in the counters.

🤖 Generated with Claude Code

maidul-devops and others added 4 commits November 10, 2026 18:52
…rts with steps, stats page

Not finished: stats.html not yet in the deploy script, Privacy Policy not
updated, not tested or deployed (needs STATS_TOKEN on the server).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Freeze detection ignores the pause while the tab is hidden.
- stats.html shows kind, steps and screen for each problem, plus freeze and report totals.
- Deploy script uploads stats.html (and keeps it out of robots); compose passes STATS_TOKEN.
- Privacy Policy: new section on anonymous counts and problem reports (online edition).
- Smoke test: a visit and a problem report reach the dev server, /api/stats needs the key,
  and the free edition keeps insights off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
iOS Safari has no Pointer Lock API, so document.exitPointerLock() is undefined
there. openRobotPanel() called it bare from inside the frame loop: the
TypeError stopped frame() before it asked for the next frame, so the whole game
froze and Bit stayed at "Running... step 0". Trading with a villager and
fainting in survival had the same bare call inside the loop.

- exitLock() guards every call.
- frame() asks for the next frame first, so one error can't stop the game.
- Smoke test: no bare exitPointerLock() calls in src/.
- sw.js -> v29.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@maidulcu maidulcu changed the title Insights: privacy-safe usage counts and problem reports (online edition) Insights (privacy-safe usage counts and problem reports) + fix the iPhone freeze when launching Bit Nov 10, 2026
@maidulcu
maidulcu merged commit b1aa2c9 into main Nov 10, 2026
1 check passed
@maidulcu
maidulcu deleted the feature/insights branch November 10, 2026 13:34
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