Skip to content

[feat] 76 FW1 + FW2: first visit, first-win quest, anonymous first-visit counts - #479

Open
AlexZ005 wants to merge 2 commits into
feat/76from
feat/76-onboard
Open

AlexZ005 wants to merge 2 commits into
feat/76from
feat/76-onboard

Conversation

@AlexZ005

Copy link
Copy Markdown
Collaborator

Roadmap 76 lane 76-onboard: FW1 (first visit) and FW2 (anonymous first-visit counts behind the cloud seam). One commit per item.

FW1 — one question, a first-win quest

  • The Welcome asks one question: Play a game · Remix a game · Start from a template · Describe it (plus a small "Empty scene" link).
  • A three-step first-win quest follows: change something → press Play → invite someone. Each step completes when the user does it.
    • Steps ride the tour engine. The engine gains hideWhilePlaying, quiet and onAdvanced.
    • The Play answer starts the remix quest when the game ends. Play exits as true → false → null, so quests.playEdge waits for the null.
  • On a first visit, advanced toolbar buttons wait behind » / More until the first Play. Settings ▸ Interface ▸ Show everything now shows them at once.
  • The editor tour is optional: logo menu ▸ Tour the interface.
  • New modules: src/lib/onboarding/{quests,onboardState,firstWin}.js.
  • whats-new suite: its boot waits passed {timeout} as the 2nd argument, which Playwright reads as the function argument, so they gave up at 30 s. They now pass it as the 3rd argument, at 90 s.

FW2 — anonymous first-visit counts

  • src/lib/onboarding/funnel.js sends each first-visit step at most once per browser, plus day-1 / day-7 / weekly returns.
  • Each event carries a closed set of fields {e, c, b, d, x}. There is no id or user agent, and the bucketed time is the only timing.
  • Nothing is sent or stored under DNT or GPC, or when Settings ▸ Privacy ▸ Count my visits anonymously is off.
  • Under debugStores, nothing counts unless the suite sets funnelUnderTest.
  • New cloudHooks seam: onFunnelEvent / notifyFunnelEvent / funnelListening, with a capped boot queue. cloudApi adds onFunnelEvent and funnelEvent('ob_waitlist'). Both are documented in OPEN-CORE.md.
  • With no plugin there is no listener and the Privacy row reads "This build counts nothing".

Proof

  • Unit: onboardingQuests 15/15 and onboardingFunnel 14/14.
  • Guard checks (each confirmed red with its guard removed): the DNT guard (unit), and the play-exit edge (2 red with the old logic).
  • e2e on a local slot:
    • onboarding 69/0, new and in battery.json (parts A–F: guard, every answer, quest steps, Play answer, phones, funnel order / DNT / GPC / returns / Privacy row).
    • tours 81/0.
    • whats-new 28/0.
  • Full unit run 2794/2795. The one red is sim/behaviours "loop guard", a 250 ms timing check under load average 24, which passes alone.
  • svelte-check 287/39 = baseline; check:tokens clean; build ok.
  • Screenshots, dark and light, desktop and N6 folded/unfolded: lane evidence after-76/76-onboard/shots/.

The cloud half (Worker /community/ob, Staff ▸ Funnel, the G1 opt-in count) is in a separate cloud PR.

🤖 Generated with Claude Code

AlexZ005 and others added 2 commits October 26, 2026 10:43
…ls after the first Play

- Welcome asks one question — Play / Remix / Template / Describe it (empty scene stays as a quiet
  link) — and each answer leads straight into its own path (the Play path loads a game and
  starts it; Remix / Template list the bundled starters; Describe it runs the assistant or says
  how to set one up)
- the first-win quest rides the tours engine: change something → Play → invite someone, each
  step completed by doing it (an undo-worthy edit, Play starting, the invite link copied or a
  peer joining); a quiet ring, no dimming, hidden while the game runs; a template / remix starts
  it once the scene has loaded, Play starts it after the first game ends
- tour engine: `hideWhilePlaying` + `quiet` on a TourDef, `onAdvanced` listeners (an action
  completing a step, heard before the step moves on); TourCard notes Skip / Don't show
- index entries may carry a `quest` line; core keeps a default per bundled game and template
- progressive disclosure: on a first visit the advanced toolbar buttons (flow, animation, pivot,
  mode) wait in the » overflow and Modules / toolboxes / Layouts behind More until the first
  Play; Settings ▸ Interface ▸ "Show everything now" and "Start the first-win quest"
- the editor tour no longer starts after the Welcome — it is offered at the end of the quest
  and from the logo menu ("Tour the interface")
- unit: tests/unit/onboardingQuests.test.js; e2e: tests/e2e/onboarding.test.cjs (battery),
  tours.test.cjs follows the new start

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- onboarding/funnel.js: ob_view / ob_choice / ob_first_edit / ob_first_play (+ a time bucket) /
  ob_first_share / ob_quest_done / ob_tour_skip (+ the step), once per browser and only for a
  browser that met the Welcome; return_d1 / return_d7 / one return_w per later week for any
  browser (the G1 weekly-returning line); ob_waitlist for the plugin's feature-update opt-in
- closed vocabularies only — {e, c (the Welcome answer), b (release), d desktop|touch|vr, x};
  no id of any kind; the first-seen day stays in this browser
- Do Not Track / Global Privacy Control send nothing and store nothing; Settings ▸ Privacy ▸
  "Count my visits anonymously" (default on, local) appears once a plugin listens; under test
  nothing counts without `funnelUnderTest`
- cloudHooks `onFunnelEvent(fn)` + a 20-event boot queue; cloudApi `onFunnelEvent` /
  `funnelEvent('ob_waitlist')` (additive, typeof-probed); the open-source build sends nothing
- unit: tests/unit/onboardingFunnel.test.js (rules on a synthetic clock, guards with their
  counterfactuals, the seam); e2e: onboarding.test.cjs part F

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

1 participant