Skip to content

feat(onboarding): allow moving profile-building to background after 10s#1295

Merged
senamakel merged 1 commit intotinyhumansai:mainfrom
graycyrus:feat/onboarding-background-profile-build
May 6, 2026
Merged

feat(onboarding): allow moving profile-building to background after 10s#1295
senamakel merged 1 commit intotinyhumansai:mainfrom
graycyrus:feat/onboarding-background-profile-build

Conversation

@graycyrus
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus commented May 6, 2026

Summary

  • After 10 seconds of pipeline runtime in the context-gathering onboarding step, a "Keep building in background & continue" link fades in
  • Clicking it completes onboarding and navigates to /home while the pipeline finishes asynchronously — the profile is saved once done
  • Auto-navigate guard prevents double onNext if pipeline finishes around the same time as the click

Changes

File Change
app/src/pages/onboarding/steps/ContextGatheringStep.tsx Added showBackgroundLink state, 10s timer effect, background link JSX, backgroundClickedRef guard
app/src/pages/onboarding/steps/__tests__/ContextGatheringStep.test.tsx 5 new tests: threshold timing, fade-in, click behavior, early-finish guard, post-unmount pipeline continuation

Design decisions

  • No global store or detached promise needed — the pipeline's async promise chain already survives component unmount naturally (plain HTTP fetches, no AbortController)
  • Uses existing animate-fade-in CSS class and ocean-600 color
  • backgroundClickedRef (not state) prevents auto-navigate race without extra re-renders

Test plan

  • Link hidden before 10s
  • Link visible after 10s with animate-fade-in
  • Click calls onNext
  • Link doesn't appear if pipeline finishes within 10s
  • Pipeline saves profile after unmount (background continuation)
  • All 10 tests pass (5 existing + 5 new)
  • pnpm typecheck clean
  • pnpm lint 0 errors (warnings are pre-existing)
  • pnpm format:check clean
  • pnpm build clean

Closes #1228

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced an optional background continuation option in account setup. After 10 seconds, users can select "Keep building in background & continue" to proceed without blocking the interface while the setup process continues in the background.
  • Tests

    • Added comprehensive tests for the new background continuation feature, including timer-based visibility and user interaction scenarios.

After 10 seconds of pipeline runtime, a "Keep building in background
& continue" link fades in. Clicking it completes onboarding and
navigates to /home while the pipeline finishes asynchronously —
the profile is saved once done, no user action needed.

Closes tinyhumansai#1228
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

The PR introduces a "Keep building in background" UX option to ContextGatheringStep that appears after 10 seconds of pipeline execution. Users can click to proceed without waiting for the full pipeline, while profile building continues asynchronously in the background.

Changes

Profile Building Background Option

Layer / File(s) Summary
State & Timer Effect
app/src/pages/onboarding/steps/ContextGatheringStep.tsx
Added showBackgroundLink state and backgroundClickedRef to track user engagement. New effect waits 10 seconds when Gmail is connected and pipeline is not finished, then shows the background link.
Navigation Control
app/src/pages/onboarding/steps/ContextGatheringStep.tsx
Modified auto-advance effect to skip auto-navigation if backgroundClickedRef is set, preventing unwanted navigation when user explicitly engages the background option.
UI Rendering
app/src/pages/onboarding/steps/ContextGatheringStep.tsx
Added "Keep building in background & continue" button that appears after the 10-second threshold, marks the ref on click, and triggers onNext to complete onboarding.
Test Coverage
app/src/pages/onboarding/steps/__tests__/ContextGatheringStep.test.tsx
Added comprehensive test suite validating 10-second threshold behavior, fade-in animation, link interactivity, pipeline continuation after unmount, and edge cases where pipeline finishes before threshold.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • tinyhumansai/openhuman#1219: Modifies auto-start and auto-advance behavior in ContextGatheringStep; this PR's background option and navigation guard extend that pattern.

Suggested reviewers

  • senamakel
  • Al629176

Poem

🐰 Ten seconds pass, a choice appears—
Keep building while you disappear!
The pipeline hums both loud and low,
While onward through the home you go. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: introducing a background continuation feature after 10 seconds in the onboarding step.
Linked Issues check ✅ Passed The pull request implements all coding requirements from issue #1228: 10s delay before link appears, fade-in animation, click handler to call onNext, background pipeline continuation, and comprehensive unit tests covering the specified scenarios.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue #1228: the ContextGatheringStep component updates and corresponding test additions for the background continuation feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@graycyrus graycyrus marked this pull request as ready for review May 6, 2026 12:00
@graycyrus graycyrus requested a review from a team May 6, 2026 12:00
@graycyrus graycyrus marked this pull request as draft May 6, 2026 12:01
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/pages/onboarding/steps/ContextGatheringStep.tsx (1)

237-246: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make the background-continue path truly single-shot and handle failures.

Line 239 only checks backgroundClickedRef before the 800ms auto-advance timeout is scheduled. If the pipeline finishes first and the user clicks the link during that 800ms window, the pending timeout still fires and onNext() runs a second time. Lines 293-296 also drop rejected onNext() promises entirely, so a failed completeAndExit() becomes a silent/unhandled failure.

Suggested fix
   const [finished, setFinished] = useState(false);
   const [hasError, setHasError] = useState(false);
   const [showBackgroundLink, setShowBackgroundLink] = useState(false);
   const backgroundClickedRef = useRef(false);
+  const autoAdvanceTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
   const ranRef = useRef(false);

   // Auto-navigate on successful completion (skip if user already clicked background link)
   useEffect(() => {
     if (finished && !hasError && !backgroundClickedRef.current) {
-      const t = setTimeout(() => {
-        void Promise.resolve(onNext()).catch(e => {
+      autoAdvanceTimeoutRef.current = setTimeout(() => {
+        if (backgroundClickedRef.current) return;
+        backgroundClickedRef.current = true;
+        void Promise.resolve(onNext()).catch(e => {
           console.warn('[onboarding:context] auto-advance failed', e);
           setHasError(true);
         });
       }, 800);
-      return () => clearTimeout(t);
+      return () => {
+        if (autoAdvanceTimeoutRef.current) {
+          clearTimeout(autoAdvanceTimeoutRef.current);
+          autoAdvanceTimeoutRef.current = null;
+        }
+      };
     }
   }, [finished, hasError, onNext]);

         {showBackgroundLink && (
           <button
             type="button"
             className="animate-fade-in text-sm text-ocean-600 hover:text-ocean-700 underline underline-offset-2 transition-colors mt-2"
             onClick={() => {
+              if (backgroundClickedRef.current) return;
               backgroundClickedRef.current = true;
-              void onNext();
+              if (autoAdvanceTimeoutRef.current) {
+                clearTimeout(autoAdvanceTimeoutRef.current);
+                autoAdvanceTimeoutRef.current = null;
+              }
+              void Promise.resolve(onNext()).catch(e => {
+                console.warn('[onboarding:context] background continue failed', e);
+                setHasError(true);
+              });
             }}>
             Keep building in background &amp; continue
           </button>
         )}

Also applies to: 289-296

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/pages/onboarding/steps/ContextGatheringStep.tsx` around lines 237 -
246, The auto-advance and background-continue paths can both trigger
onNext()/completeAndExit() causing double-invocation and unhandled rejections;
make the backgroundClickedRef a true single-shot guard by setting
backgroundClickedRef.current = true immediately when the user clicks the
background-continue link (the handler that calls completeAndExit/onNext), and
before invoking onNext() inside the setTimeout also re-check
backgroundClickedRef.current and return early if set (symbols:
backgroundClickedRef, onNext, completeAndExit, finished). Additionally, ensure
every call site that calls onNext() or completeAndExit() wraps the returned
promise with a .catch that logs the error and calls setHasError(true) (or awaits
in an async handler with try/catch) so failures are not dropped (references:
setHasError). Finally, clear the pending timeout when
backgroundClickedRef.current becomes true to avoid the timeout firing after a
manual click.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@app/src/pages/onboarding/steps/ContextGatheringStep.tsx`:
- Around line 237-246: The auto-advance and background-continue paths can both
trigger onNext()/completeAndExit() causing double-invocation and unhandled
rejections; make the backgroundClickedRef a true single-shot guard by setting
backgroundClickedRef.current = true immediately when the user clicks the
background-continue link (the handler that calls completeAndExit/onNext), and
before invoking onNext() inside the setTimeout also re-check
backgroundClickedRef.current and return early if set (symbols:
backgroundClickedRef, onNext, completeAndExit, finished). Additionally, ensure
every call site that calls onNext() or completeAndExit() wraps the returned
promise with a .catch that logs the error and calls setHasError(true) (or awaits
in an async handler with try/catch) so failures are not dropped (references:
setHasError). Finally, clear the pending timeout when
backgroundClickedRef.current becomes true to avoid the timeout firing after a
manual click.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b321cc87-b55b-43ce-abb6-b718f03521f2

📥 Commits

Reviewing files that changed from the base of the PR and between a3a1843 and 58ae83f.

📒 Files selected for processing (2)
  • app/src/pages/onboarding/steps/ContextGatheringStep.tsx
  • app/src/pages/onboarding/steps/__tests__/ContextGatheringStep.test.tsx

@graycyrus graycyrus marked this pull request as ready for review May 6, 2026 13:24
@senamakel senamakel merged commit fcf2880 into tinyhumansai:main May 6, 2026
20 checks passed
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(onboarding): allow moving profile-building to background after 10s threshold

2 participants