> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Post-login user setup

> SyncAuthFlow is gone — migrate the automatic post-login orchestration (onboarding, MFA, device registration, wallet creation) to an explicit chain you own.

This is the biggest behavioral change in the migration. In the React SDK, `SyncAuthFlow` ran automatically after authentication and chained every remaining setup step for you. The JavaScript SDK does none of this — you decide which steps to run, detect what's pending, and render each screen.

## What SyncAuthFlow did

After a user authenticated, `SyncAuthFlow` silently orchestrated, in order:

1. Onboarding / required-field collection
2. Captcha (when enabled)
3. MFA enrollment
4. Device registration
5. Embedded wallet creation

You never called these — the widget detected what was missing (`useSyncOnboardingFlow` watched `userWithMissingInfo.missingFields`, `useSyncMfaFlow` watched MFA state, etc.) and pushed the matching view.

## What you own now

There is no automatic orchestration. After auth resolves, you run the chain yourself: check each step, show UI for whatever is pending, and let the user in once everything is done.

```
signed in → required fields? → MFA? → device registration? → embedded wallet? → ready
```

Each legacy sync hook maps to a detection call you make explicitly:

| React SDK (automatic)                              | JavaScript SDK (you call)                                            |
| -------------------------------------------------- | -------------------------------------------------------------------- |
| `useSyncOnboardingFlow` (required fields)          | inspect `user.missingFields`, save with `updateUser({ userFields })` |
| `useSyncMfaFlow`                                   | `isUserMissingMfaAuth()`                                             |
| `useSyncDeviceRegistrationFlow`                    | `isDeviceRegistrationRequired(user)`                                 |
| `useSyncEmbeddedWalletFlow` / `useSyncDynamicWaas` | `isDynamicWaasEnabled()` + `getChainsMissingWaasWalletAccounts()`    |

<Warning>
  Do not gate access on a single "onboarding complete" flag. Compose the per-step checks above so you control exactly which steps block entry.
</Warning>

## The orchestration pattern

Only handle the steps that apply to your app. Every step below is independent and optional — if your app doesn't use MFA, skip the MFA check; if it has no embedded wallets, skip wallet creation; and so on. Compose only the checks for the features you've actually enabled, in the order that fits your flow. The `show*` functions below are **your UI** — the SDK owns the logic, you own the screens.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"system"}
    import { getDefaultClient, updateUser } from '@dynamic-labs-sdk/client';
    import { isUserMissingMfaAuth } from '@dynamic-labs-sdk/client';
    import {
      isDynamicWaasEnabled,
      getChainsMissingWaasWalletAccounts,
      createWaasWalletAccounts,
    } from '@dynamic-labs-sdk/client/waas';

    async function runSetup() {
      const user = getDefaultClient().user;
      if (!user) return;

      // Required fields
      if (user.missingFields?.length) {
        const values = await showFieldForm(user.missingFields);
        await updateUser({ userFields: values });
      }

      // MFA enrollment
      if (isUserMissingMfaAuth()) {
        await showMfaEnrollment();
      }

      // Embedded wallet creation
      if (isDynamicWaasEnabled() && getChainsMissingWaasWalletAccounts().length) {
        await createWaasWalletAccounts();
      }

      // The user is ready — render your app.
    }
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { useUser } from '@dynamic-labs-sdk/react-hooks';
    import { isUserMissingMfaAuth } from '@dynamic-labs-sdk/client';
    import {
      isDynamicWaasEnabled,
      getChainsMissingWaasWalletAccounts,
    } from '@dynamic-labs-sdk/client/waas';

    export function SetupGate({ children }: { children: React.ReactNode }) {
      const { data: user } = useUser();
      if (!user) return null;

      if (user.missingFields?.length) return <FieldForm fields={user.missingFields} />;
      if (isUserMissingMfaAuth()) return <MfaEnrollment />;
      if (isDynamicWaasEnabled() && getChainsMissingWaasWalletAccounts().length) {
        return <CreateWallet />;
      }

      return <>{children}</>;
    }
    ```
  </Tab>
</Tabs>

The complete implementation — every step's UI, recovery-code acknowledgment, device registration, and lazy wallet creation — is in [Post-login user setup](/docs/javascript/building-ui/post-auth-user-setup).

## See also

* [Post-login user setup (Building UI)](/docs/javascript/building-ui/post-auth-user-setup)
* MFA
* Embedded wallets: setup & creation
* Account conflict resolution
