BigBlocks Docs
Components/Authentication

SignupFlow

Multi-step signup process for creating new Bitcoin wallets

A comprehensive multi-step signup component for creating new Bitcoin wallets with built-in identity generation, password setup, and backup management. It provides a complete onboarding experience with proper error handling and state management.

Installation

npx bigblocks add signup-flow

Import

import { SignupFlow } from 'bigblocks';

Props

PropTypeRequiredDefaultDescription
onSuccess(user: AuthUser) => voidNo-Callback when signup succeeds
onError(error: AuthError) => voidNo-Callback for error handling
classNamestringNo-Additional CSS classes

Basic Usage

import { SignupFlow, BitcoinAuthProvider } from 'bigblocks';
import { useRouter } from 'next/navigation';

export default function SignupPage() {
  const router = useRouter();

  const handleSuccess = (user) => {
    console.log('Signup successful:', user);
    router.push('/dashboard');
  };

  const handleError = (error) => {
    console.error('Signup failed:', error);
  };

  return (
    <BitcoinAuthProvider config={{ apiUrl: '/api' }}>
      <SignupFlow
        onSuccess={handleSuccess}
        onError={handleError}
      />
    </BitcoinAuthProvider>
  );
}

Advanced Usage

With Custom Error Handling

import { SignupFlow } from 'bigblocks';
import { toast } from 'sonner';

export default function SignupWithErrorHandling() {
  return (
    <SignupFlow 
      onSuccess={(user) => {
        toast.success('Account created successfully!');
        router.push('/onboarding');
      }}
      onError={(error) => {
        // Handle specific error types
        switch (error.code) {
          case 'USER_EXISTS':
            toast.error('An account already exists. Please sign in.');
            router.push('/signin');
            break;
          case 'NETWORK_ERROR':
            toast.error('Network error. Please check your connection.');
            break;
          case 'INVALID_PASSWORD':
            toast.error('Password does not meet requirements.');
            break;
          default:
            toast.error(error.message || 'Signup failed. Please try again.');
        }
      }}
    />
  );
}

With Analytics Tracking

import { SignupFlow } from 'bigblocks';
import { analytics } from '@/lib/analytics';

export default function TrackedSignup() {
  const startTime = Date.now();

  return (
    <SignupFlow 
      onSuccess={(user) => {
        const duration = Date.now() - startTime;
        
        analytics.track('signup_completed', {
          userId: user.id,
          duration: duration,
          profileCount: user.profiles.length,
          hasMultipleProfiles: user.profiles.length > 1
        });
        
        // Set user for future analytics
        analytics.identify(user.id, {
          address: user.address,
          createdAt: new Date().toISOString()
        });
        
        router.push('/welcome');
      }}
      onError={(error) => {
        analytics.track('signup_failed', {
          error: error.code,
          duration: Date.now() - startTime
        });
      }}
    />
  );
}

With Custom Styling

import { SignupFlow } from 'bigblocks';

export default function StyledSignup() {
  return (
    <div className="min-h-screen bg-gradient-to-br from-orange-50 to-orange-100">
      <div className="flex items-center justify-center p-4">
        <SignupFlow 
          className="max-w-md w-full shadow-xl"
          onSuccess={(user) => {
            router.push('/dashboard');
          }}
        />
      </div>
    </div>
  );
}

In Modal

import { SignupFlow } from 'bigblocks';
import { Modal } from '@radix-ui/themes';

export function SignupModal({ isOpen, onClose }) {
  return (
    <Modal open={isOpen} onOpenChange={onClose}>
      <Modal.Content maxWidth="500px">
        <Modal.Title>Create Your Bitcoin Wallet</Modal.Title>
        
        <SignupFlow
          onSuccess={(user) => {
            console.log('Signup completed:', user);
            onClose();
            router.push('/dashboard');
          }}
          onError={(error) => {
            if (error.code !== 'USER_CANCELLED') {
              toast.error('Signup failed');
            }
          }}
        />
      </Modal.Content>
    </Modal>
  );
}

Signup Flow Steps

The SignupFlow component guides users through these steps:

1. Welcome Step

  • Introduction to Bitcoin wallet creation
  • Terms of service acceptance (if configured)
  • Clear value proposition

2. Identity Generation

  • Automatic Bitcoin keypair generation
  • Visual feedback during generation
  • Secure client-side process

3. Password Setup

  • Password creation for encryption
  • Password strength indicator
  • Confirmation field
  • Requirements display

4. Backup Creation

  • Encrypted backup generation
  • Download prompt
  • Security instructions
  • Verification checkbox

5. Success Confirmation

  • Account creation confirmation
  • Next steps guidance
  • Navigation to dashboard

Common Patterns

Full Page Signup

import { SignupFlow } from 'bigblocks';

export function SignupPage() {
  return (
    <div className="min-h-screen flex flex-col">
      <header className="border-b">
        <div className="container mx-auto px-4 py-3">
          <h1 className="text-xl font-bold">Create Account</h1>
        </div>
      </header>
      
      <main className="flex-1 flex items-center justify-center p-4">
        <SignupFlow
          className="w-full max-w-lg"
          onSuccess={(user) => {
            router.push('/onboarding');
          }}
        />
      </main>
    </div>
  );
}

With Navigation Options

import { SignupFlow } from 'bigblocks';
import Link from 'next/link';

export function SignupWithNav() {
  return (
    <div className="space-y-4">
      <SignupFlow
        onSuccess={(user) => {
          router.push('/dashboard');
        }}
      />
      
      <div className="text-center">
        <p className="text-sm text-gray-600">
          Already have an account?{' '}
          <Link href="/signin" className="text-blue-600 hover:underline">
            Sign in
          </Link>
        </p>
      </div>
    </div>
  );
}

With Loading Overlay

import { SignupFlow } from 'bigblocks';
import { useState } from 'react';

export function SignupWithLoading() {
  const [isProcessing, setIsProcessing] = useState(false);

  return (
    <>
      {isProcessing && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6">
            <Spinner size="lg" />
            <p className="mt-2">Setting up your account...</p>
          </div>
        </div>
      )}
      
      <SignupFlow
        onSuccess={async (user) => {
          setIsProcessing(true);
          try {
            // Additional setup
            await setupUserProfile(user);
            await createDefaultSettings(user.id);
            
            router.push('/welcome');
          } finally {
            setIsProcessing(false);
          }
        }}
      />
    </>
  );
}

Security Features

  1. Client-Side Key Generation: All cryptographic operations happen in the browser
  2. Password Encryption: Private keys are encrypted before any storage
  3. No Password Transmission: Passwords never leave the client
  4. Secure Backup Format: Industry-standard encryption for backups
  5. Session Management: Secure session creation after signup

Error Types

interface AuthError {
  code: 
    | 'USER_EXISTS'        // Account already exists
    | 'NETWORK_ERROR'      // Network connectivity issues
    | 'INVALID_PASSWORD'   // Password requirements not met
    | 'GENERATION_FAILED'  // Key generation failed
    | 'BACKUP_FAILED'      // Backup creation failed
    | 'SESSION_FAILED'     // Session creation failed
    | 'USER_CANCELLED';    // User cancelled the flow
  message: string;
}

Styling

The SignupFlow uses Radix Themes and respects the BitcoinThemeProvider:

/* Component structure */
.signup-flow-container {
  /* Inherits theme styles */
}

.signup-step {
  /* Individual step styling */
}

.signup-navigation {
  /* Step navigation buttons */
}

State Management

The component internally manages:

  • Current step tracking
  • Form data across steps
  • Loading states
  • Error states
  • Validation state
  • Backup generation status

Best Practices

  1. Error Handling: Always implement onError to handle failures gracefully
  2. Success Routing: Navigate users appropriately after signup
  3. Loading States: Show feedback during async operations
  4. Backup Emphasis: Ensure users understand backup importance
  5. Mobile Optimization: Test on mobile devices for touch interactions

Troubleshooting

Component Not Rendering

  • Ensure wrapped in BitcoinAuthProvider
  • Check that React Query is properly configured
  • Verify API endpoints are accessible

Key Generation Failing

  • Check browser crypto API support
  • Ensure sufficient entropy available
  • Verify no browser extensions blocking crypto

Backup Download Issues

  • Check browser download permissions
  • Ensure popup blockers aren't interfering
  • Verify file download API compatibility

API Reference

AuthUser Type

interface AuthUser {
  id: string;              // User's BAP ID
  address: string;         // Bitcoin address
  idKey: string;          // Identity key
  profiles: ProfileInfo[]; // User profiles
  activeProfileId: string; // Current profile
}

Internal Flow

  1. Generate Bitcoin keypair
  2. Create password
  3. Encrypt private key
  4. Generate backup file
  5. Store encrypted backup
  6. Create server session
  7. Return authenticated user

Notes for Improvement

Implementation Differences: The actual component is simpler than the prompt described:

  • No onCancel callback
  • No showBackupStep or showOAuthStep props to control flow
  • No configurable steps
  • OAuth linking is not part of the current implementation
  • The flow is more streamlined with fewer customization options