Skip to main content

Documentation Index

Fetch the complete documentation index at: https://stackauth-e0affa27-chore-move-mcp-to-a-sep-app.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Sometimes, you may want to collect additional information from users during sign-up, for example a real name or address. The most straightforward approach is to redirect users to an onboarding page right after they sign up. However, this is not recommended for the following reasons:
  1. Users can accidentally (or purposefully) close or navigate away from the page before completing the onboarding.
  2. Redirect URLs may vary depending on the context. For instance, if a user is redirected to a sign-in page after trying to access a protected page, they’ll expect to return to the original protected page post-authentication.
Instead, a more reliable strategy is to store an onboarded flag in the user’s metadata and redirect users to the onboarding page if they haven’t completed it yet.

Example implementation

Let’s say you have an onboarding page that asks for an address and stores it in the user’s metadata:
export default function OnboardingPage() {
  const user = useUser();
  const router = useRouter();
  const [address, setAddress] = useState('');

  return <>
    <input 
      type="text" 
      value={address} 
      onChange={(e) => setAddress(e.target.value)} 
    />

    <button onClick={async () => {
      await user.update({
        clientMetadata: {
          onboarded: true,
          address,
        },
      });
      router.push('/');
    }}>
      Submit
    </button>
    </>
  );
}
While the above implementation offers a basic onboarding process, users can still skip onboarding by directly sending an API request to update the clientMetadata.onboarded flag. If you want to ensure that onboarding cannot be bypassed on the API level, you should create a server endpoint to validate and store the data, then save the onboarded flag in the clientReadOnlyMetadata on the server side after validation.
Next, we can create a hook/function to check if the user has completed onboarding and redirect them to the onboarding page:
'use client';
import { useEffect } from 'react';
import { useUser } from '@stackframe/stack';
import { useRouter } from 'next/navigation';

export function useOnboarding() {
  const user = useUser();
  const router = useRouter();

  useEffect(() => {
    if (!user.clientReadOnlyMetadata.onboarded) {
      router.push('/onboarding');
    }
  }, [user]);
}
You can then use these functions wherever onboarding is required:
import { useOnboarding } from '@/app/onboarding-hooks';
import { useUser } from '@stackframe/stack';

export default function HomePage() {
  useOnboarding();
  const user = useUser();

  return (
    <div>Welcome to the app, {user.displayName}</div>
  );
}