Skip to content

feat: implement onboard walkthrough for new user - #2712

Merged
hvn2k1 merged 11 commits into
mainfrom
onboard-walkthrough
Jul 30, 2026
Merged

feat: implement onboard walkthrough for new user#2712
hvn2k1 merged 11 commits into
mainfrom
onboard-walkthrough

Conversation

@hvn2k1

@hvn2k1 hvn2k1 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Resolves #2514

What this PR does

Adds an animated, in-console onboarding walkthrough that guides new users through the core journey — create a feature flag → create an API key → connect an SDK — using spotlight overlays on the real UI (powered by driver.js, ~5 kB, MIT).

Entry points

  • A Get Started button pinned at the bottom of the sidebar (new rocket icon) starts the walkthrough at any time.
  • First-time users: the walkthrough starts automatically on first login, detected via account.lastSeen == 0 from GetMe.

Walkthrough flow

  1. Spotlight on the Feature Flags menu, then on the + Create Flag button.
  2. Guides through the create-flag form (general info, variations), step by step.
  3. Steps are action-driven where possible: they advance when the user actually clicks the real button (advanceOnClick), not a "Next" button — users learn by doing in their own console.
  4. After the flag is created, a celebration dialog leads to the API Keys page and guides key creation the same way.
  5. Once the key exists (and the key-secret dialog is closed), a Connect an SDK modal shows install + initialize/evaluate starter code for all 8 supported SDKs (JavaScript, React, React Native, Android, iOS, Flutter, Go, Node.js), with the API endpoint, flag ID, and feature tag pre-filled. The API key is intentionally shown as a YOUR_API_KEY placeholder — the real secret is only displayed in the dedicated secret dialog.

UX guardrails

  • Every step has a Skip walkthrough button (except the final one); clicking the dimmed overlay or pressing Escape does not exit the tour.
  • Portaled dropdowns (environment selector, tags) stay clickable above the walkthrough overlay.
  • The API-key submit button is locked (dimmed) until its dedicated step; Enter-key submits are blocked on the form step.
  • Full English and Japanese translations.

Configuration

  • Helm: web.env.walkthroughEnabled (default true) → rendered into window.env.WALKTHROUGH_ENABLED, hides the Get Started entry when false.
  • Docker Compose (env.js) and Vite (VITE_WALKTHROUGH_ENABLED) equivalents included.

Backend change

GetMe now returns the pre-update lastSeen (while still bumping it), restoring the first-login signal that #2185 unintentionally removed — previously lastSeen always read as "just now", so clients could never detect a first login (this had also broken the existing first-login profile form).

How to test

  1. Click Get Started at the bottom of the sidebar and follow the tour end to end (flag → API key → SDK snippet).
  2. First-login auto-start: reset an account's last_seen to 0 in the DB (requires a rebuilt backend), then sign in.
  3. Toggle off: set web.env.walkthroughEnabled: false (or WALKTHROUGH_ENABLED: false in env.js) and confirm the Get Started entry disappears.

demo

Screen.Recording.2026-07-28.at.17.21.11.mov

Copilot AI review requested due to automatic review settings July 24, 2026 09:13
@hvn2k1
hvn2k1 requested review from cre8ivejp and t-kikuc as code owners July 24, 2026 09:13
@hvn2k1
hvn2k1 marked this pull request as draft July 24, 2026 09:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements an onboarding walkthrough for first-time dashboard users, guiding them through creating a feature flag, creating an API key, and then showing SDK connection starter snippets. This is enabled/disabled via a new WALKTHROUGH_ENABLED config flag and relies on backend lastSeen behavior to detect first login.

Changes:

  • Add a Driver.js-based walkthrough hook, storage flag, UI tour targets, and “Get started” navigation entry.
  • Add “Connect SDK” modal with multi-language install/init snippets and i18n strings.
  • Add WALKTHROUGH_ENABLED configuration across Vite env, window.env, Helm values, and docker-compose; update GetMe to return pre-update lastSeen to detect first login.

Reviewed changes

Copilot reviewed 26 out of 29 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ui/dashboard/package.json Adds driver.js dependency for the walkthrough UI.
ui/dashboard/yarn.lock Locks driver.js@1.8.0.
ui/dashboard/src/storage/walkthrough.ts Adds localStorage helpers to mark walkthrough pending on first login.
ui/dashboard/src/hooks/use-walkthrough.tsx New walkthrough orchestrator hook (Driver.js steps, polling for API key creation, SDK modal trigger).
ui/dashboard/src/hooks/index.ts Re-exports use-walkthrough from the hooks barrel.
ui/dashboard/src/components/navigation/menu-item.tsx Adds optional tourId to attach data-tour attributes to nav items.
ui/dashboard/src/components/navigation/index.tsx Adds “Get started” entry, wires useWalkthrough, and renders ConnectSdkModal.
ui/dashboard/src/pages/feature-flags/page-content.tsx Adds data-tour target to “Create flag” button.
ui/dashboard/src/pages/create-flag/flag-form/index.tsx Adds data-tour target to “Create flag” submit button.
ui/dashboard/src/pages/create-flag/flag-form/general-info.tsx Adds data-tour target to general info section container.
ui/dashboard/src/pages/create-flag/flag-form/flag-variations/index.tsx Adds data-tour target to variations section container.
ui/dashboard/src/pages/api-keys/page-content.tsx Adds data-tour target to “New API key” button.
ui/dashboard/src/pages/api-keys/api-key-modal/api-key-create-update-modal/index.tsx Adds data-tour targets to API key form + submit button.
ui/dashboard/src/index.css Adds Driver.js-related z-index/pointer-event overrides.
ui/dashboard/src/elements/connect-sdk-modal/index.tsx Adds new modal UI showing SDK snippets and copy actions.
ui/dashboard/src/elements/connect-sdk-modal/snippets.ts Adds SDK snippet definitions used by the modal.
ui/dashboard/src/env.d.ts Adds VITE_WALKTHROUGH_ENABLED env typing.
ui/dashboard/src/configs/index.ts Adds WALKTHROUGH_ENABLED config resolution (Vite env vs window.env).
ui/dashboard/src/auth/auth-context.tsx Sets walkthrough pending flag on first login.
ui/dashboard/src/@locales/en/common.json Adds walkthrough strings + “Get started” label.
ui/dashboard/src/@locales/ja/common.json Adds walkthrough strings + “Get started” label (JP).
ui/dashboard/src/@icons/sidebar-icons/rocket.svg Adds rocket icon for the “Get started” menu item.
ui/dashboard/src/@icons/index.tsx Exports new rocket icon.
ui/dashboard/.env.example Adds VITE_WALKTHROUGH_ENABLED example value.
pkg/account/api/admin_account.go Returns pre-update lastSeen to let clients detect first login while still updating storage.
pkg/account/api/admin_account_test.go Updates test fixture to account for lastSeen behavior change.
manifests/bucketeer/charts/web/values.yaml Adds Helm value walkthroughEnabled (default true).
manifests/bucketeer/charts/web/templates/env-js-configmap.yaml Exposes WALKTHROUGH_ENABLED via window.env.
docker-compose/static-files/js/env.js Enables walkthrough in docker-compose env defaults.
Comments suppressed due to low confidence (2)

ui/dashboard/src/hooks/use-walkthrough.tsx:233

  • This polling effect also uses consoleAccount!. If auth state is not ready, getCurrentEnvironment(consoleAccount!) can throw. Guard on consoleAccount and avoid the non-null assertion.
  useEffect(() => {
    if (stage !== 'await-apikey-created') return;
    const currentEnvironment = getCurrentEnvironment(consoleAccount!);
    const startedAt = Date.now();

ui/dashboard/src/hooks/use-walkthrough.tsx:260

  • startWalkthrough also relies on consoleAccount!. Add a guard so clicking "Get started" (or auto-start) can't crash during initial auth loading.
  const startWalkthrough = useCallback(() => {
    const currentEnvironment = getCurrentEnvironment(consoleAccount!);
    navigate(`/${currentEnvironment.urlCode}${PAGE_PATH_FEATURES}`);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ui/dashboard/src/hooks/index.ts
Comment thread ui/dashboard/src/hooks/use-walkthrough.tsx
Comment thread ui/dashboard/src/hooks/use-walkthrough.tsx
Comment thread ui/dashboard/src/elements/connect-sdk-modal/snippets.ts Outdated
@hvn2k1
hvn2k1 requested a review from steveninhle July 24, 2026 09:38
Address review comments on PR #2712:
- Move WALKTHROUGH_TARGETS to side-effect-free constants/walkthrough.ts
  so pages don't pull driver.js via the hooks barrel
- Guard consoleAccount instead of non-null assertions in use-walkthrough
- Remove blockEnterSubmit listener in onDestroyed as a safety net
- Add missing stdlib imports to the Go SDK snippet

Also show a welcome dialog before the auto-started walkthrough for
first-time users.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hvn2k1
hvn2k1 marked this pull request as ready for review July 24, 2026 09:44
Comment thread ui/dashboard/src/hooks/use-walkthrough.tsx
Comment thread ui/dashboard/src/components/navigation/index.tsx Outdated
Comment thread ui/dashboard/src/components/navigation/index.tsx Outdated
hvn2k1 and others added 2 commits July 27, 2026 12:48
Address review comments on PR #2712:
- Move the walkthrough entry from the sidebar to Settings as a
  "Replay tutorial" action (walkthrough state now lives in a shared
  WalkthroughProvider so any page can start it)
- Sync the sliding settings panel with navigation so starting the
  tour from the settings area highlights the right elements
- Guide users to enable the created flag: add a note to the SDK
  modal and land on the flag's targeting page when closing it

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Inherit the console font (Sofia Pro / Noto Sans JP) in driver.js
  popovers instead of its bundled font stack
- Replace emoji in walkthrough titles with the sidebar SVG icons

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread ui/dashboard/src/pages/settings/page-content.tsx Outdated
hvn2k1 and others added 2 commits July 27, 2026 17:18
Address review comments on PR #2712:
- Start the tour only after the flag list page is reached, so the
  unsaved-changes dialog no longer leaves a stray tour running when
  replaying from Settings
- Refresh the spotlight when panels/modals finish animating in

Also keep highlighted scrollable containers scrollable (refreshing the
spotlight on nested scrolls) and enlarge the welcome dialog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Replace the Settings page tutorial card with a "Tutorial" item in the
  sliding settings menu so it is visible without scrolling, including
  for system admins
- Skip spotlight refreshes while the step transition tween is running,
  which made the animation replay and feel laggy, and shorten the tween
  to match the console's animation timing
Comment thread ui/dashboard/src/components/navigation/index.tsx
hvn2k1 and others added 2 commits July 28, 2026 15:17
- Move the tutorial entry into the user menu, under the language choice
- Ignore navigation attempts and block Escape during the walkthrough so
  the API key panel cannot be closed and the leave-page confirm never
  interrupts a tour
- Show the SDK snippet immediately after the key-created dialog closes
  and keep the snippet modal open on outside clicks

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread ui/dashboard/src/hooks/use-walkthrough.tsx
Cancelling the leave-page dialog now drops the pending tour request, and
any navigation consumes the request, so the tour can no longer start
unexpectedly when the user later returns to the flag list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread ui/dashboard/src/index.css
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
overlayClickBehavior: () => undefined,
allowKeyboardControl: false,
nextBtnText: t('walkthrough.next'),
doneBtnText: t('walkthrough.done'),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also noticed a couple of minor issues while testing:

  1. Some text is still missing i18n support, such as the previous button and the progress text.
  2. The walkthrough dialog could be slightly wider to accommodate both the English and Japanese versions better.
Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, I fixed in d54291a

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 40 out of 43 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

ui/dashboard/src/components/navigation/user-menu.tsx:124

  • The PR description says there is a “Get Started” button pinned at the bottom of the sidebar to start the walkthrough at any time, but the only entry point added in the UI code here is a “Tutorial” item in the user menu (no sidebar-pinned entry). Either add the promised sidebar entry point (likely in the main navigation) or adjust the PR description so it matches the implemented UI.
    WALKTHROUGH_ENABLED && {
      label: t(`walkthrough.tutorial`),
      icon: IconRocket,
      onClick: () => {
        popoverCloseRef?.current?.click();
        startWalkthrough();
      }
    },

ui/dashboard/src/components/navigation/index.tsx:149

  • The effect uses settingPaths, onOpenSetting, and onCloseSetting but they are not included in the dependency array. This can lead to stale values being captured (and will typically trip react-hooks/exhaustive-deps). Include the referenced values in the dependency list or otherwise ensure they are stable/memoized.
  useEffect(() => {
    if (settingPaths.some(path => pathname.startsWith(path))) {
      onOpenSetting();
    } else {
      onCloseSetting();
    }
  }, [pathname]);

ui/dashboard/src/elements/connect-sdk-modal/index.tsx:79

  • getCurrentEnvironment(consoleAccount!) relies on a non-null assertion. If consoleAccount is temporarily undefined (auth still loading, or during logout/unmount races) this will throw and break the modal. Add a guard and bail out (or render a loading state) when consoleAccount is not available.
const ConnectSdkModal = ({ isOpen, flagId, onClose }: ConnectSdkModalProps) => {
  const { t } = useTranslation(['common', 'message']);
  const { notify } = useToast();
  const navigate = useNavigate();
  const { consoleAccount } = useAuth();
  const currentEnvironment = getCurrentEnvironment(consoleAccount!);

cre8ivejp
cre8ivejp previously approved these changes Jul 30, 2026

@cre8ivejp cre8ivejp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Nice work!

@hvn2k1
hvn2k1 requested a review from steveninhle July 30, 2026 05:56

@steveninhle steveninhle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@hvn2k1
hvn2k1 merged commit 5b475f6 into main Jul 30, 2026
12 checks passed
@hvn2k1
hvn2k1 deleted the onboard-walkthrough branch July 30, 2026 07:10
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.

feat: improve the onboarding process

5 participants