BigBlocks Docs
Components/Backup & Recovery

CloudBackupManager

Component for managing encrypted cloud backups stored with OAuth providers

A streamlined component for managing cloud-stored wallet backups via OAuth providers. It provides status checking, update capabilities, and automatic synchronization of encrypted backups.

Cloud Backup ManagerManage cloud backup providers and sync your Bitcoin identity across multiple platforms.
Checking backup status...
Current Status
Cloud Backup
current
Last updated: 6/7/2025, 1:30:38 PM
Features
Status CheckingAutomatic UpdatesProvider ManagementSync Monitoring

Privacy Note: All backups are encrypted before being stored in the cloud. Your private keys never leave your device in plain text.

Installation

npx bigblocks add cloud-backup-manager

Import

import { CloudBackupManager } from 'bigblocks';

Props

PropTypeRequiredDefaultDescription
checkBackupStatus() => Promise<CloudBackupStatus>No-Function to check backup status
updateCloudBackup() => Promise<void>No-Function to update cloud backup
onStatusChange(status: CloudBackupStatus) => voidNo-Callback when status changes
classNamestringNo-Additional CSS classes

Types

interface CloudBackupStatus {
  hasCloudBackup: boolean;
  isOutdated?: boolean;
  lastUpdated?: number;
  provider?: string;
}

Basic Usage

import { CloudBackupManager } from 'bigblocks';

export default function BackupSettings() {
  const checkStatus = async () => {
    // Check backup status from your backend
    const response = await fetch('/api/backup/status');
    return response.json();
  };

  const updateBackup = async () => {
    // Update cloud backup
    await fetch('/api/backup/sync', { method: 'POST' });
  };

  return (
    <CloudBackupManager
      checkBackupStatus={checkStatus}
      updateCloudBackup={updateBackup}
      onStatusChange={(status) => {
        console.log('Backup status:', status);
      }}
    />
  );
}

Advanced Usage

With Authentication Context

import { CloudBackupManager } from 'bigblocks';
import { useAuth } from '@/hooks/useAuth';

export default function AuthenticatedBackup() {
  const { user, backup } = useAuth();

  const checkBackupStatus = async () => {
    if (!user) throw new Error('Not authenticated');
    
    const response = await fetch('/api/backup/status', {
      headers: {
        'X-Auth-Token': user.authToken,
      },
    });
    
    return response.json();
  };

  const updateCloudBackup = async () => {
    if (!backup) throw new Error('No backup available');
    
    await fetch('/api/backup/sync', {
      method: 'POST',
      headers: {
        'X-Auth-Token': user.authToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ backup }),
    });
  };

  return (
    <CloudBackupManager
      checkBackupStatus={checkBackupStatus}
      updateCloudBackup={updateCloudBackup}
      onStatusChange={(status) => {
        if (status.isOutdated) {
          console.log('Backup is outdated, consider updating');
        }
      }}
    />
  );
}

With Custom Status Handling

import { CloudBackupManager } from 'bigblocks';
import { useState, useEffect } from 'react';

export default function CustomStatusHandling() {
  const [lastSync, setLastSync] = useState<Date | null>(null);
  const [provider, setProvider] = useState<string | null>(null);

  const handleStatusChange = (status: CloudBackupStatus) => {
    if (status.lastUpdated) {
      setLastSync(new Date(status.lastUpdated));
    }
    if (status.provider) {
      setProvider(status.provider);
    }
  };

  return (
    <div>
      <CloudBackupManager
        checkBackupStatus={checkStatus}
        updateCloudBackup={updateBackup}
        onStatusChange={handleStatusChange}
      />
      
      {lastSync && (
        <p className="text-sm text-gray-600 mt-2">
          Last synced: {lastSync.toLocaleString()}
        </p>
      )}
      
      {provider && (
        <p className="text-sm text-gray-600">
          Backed up with: {provider}
        </p>
      )}
    </div>
  );
}

Auto-sync Implementation

import { CloudBackupManager } from 'bigblocks';
import { useEffect, useRef } from 'react';

export default function AutoSyncBackup() {
  const intervalRef = useRef<NodeJS.Timeout | null>(null);
  
  const checkBackupStatus = async () => {
    const response = await fetch('/api/backup/status');
    const status = await response.json();
    
    // Auto-update if backup is outdated by more than 24 hours
    if (status.lastUpdated) {
      const hoursSinceUpdate = (Date.now() - status.lastUpdated) / (1000 * 60 * 60);
      if (hoursSinceUpdate > 24) {
        status.isOutdated = true;
      }
    }
    
    return status;
  };

  useEffect(() => {
    // Check status every 5 minutes
    intervalRef.current = setInterval(() => {
      checkBackupStatus();
    }, 5 * 60 * 1000);

    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
    };
  }, []);

  return (
    <CloudBackupManager
      checkBackupStatus={checkBackupStatus}
      updateCloudBackup={updateCloudBackup}
      onStatusChange={(status) => {
        if (status.isOutdated) {
          // Trigger notification
          showNotification('Your backup is outdated');
        }
      }}
    />
  );
}

With Error Handling

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

export default function ErrorHandlingExample() {
  const [error, setError] = useState<string | null>(null);

  const checkBackupStatus = async () => {
    try {
      setError(null);
      const response = await fetch('/api/backup/status');
      
      if (!response.ok) {
        throw new Error('Failed to check backup status');
      }
      
      return response.json();
    } catch (err) {
      setError(err.message);
      throw err;
    }
  };

  const updateCloudBackup = async () => {
    try {
      setError(null);
      const response = await fetch('/api/backup/sync', {
        method: 'POST',
      });
      
      if (!response.ok) {
        throw new Error('Failed to update backup');
      }
    } catch (err) {
      setError(err.message);
      throw err;
    }
  };

  return (
    <div>
      {error && (
        <div className="bg-red-100 text-red-700 p-3 rounded mb-4">
          {error}
        </div>
      )}
      
      <CloudBackupManager
        checkBackupStatus={checkBackupStatus}
        updateCloudBackup={updateCloudBackup}
      />
    </div>
  );
}

Common Patterns

In Settings Page

import { CloudBackupManager } from 'bigblocks';

export function BackupSettingsSection() {
  return (
    <div className="space-y-6">
      <div>
        <h3 className="text-lg font-semibold mb-2">Backup Management</h3>
        <p className="text-sm text-gray-600 mb-4">
          Keep your wallet backup synchronized with your cloud provider
        </p>
        
        <CloudBackupManager
          checkBackupStatus={checkStatus}
          updateCloudBackup={updateBackup}
          className="border rounded-lg p-4"
        />
      </div>
      
      <div className="border-t pt-4">
        <h4 className="font-medium mb-2">Backup Tips</h4>
        <ul className="text-sm text-gray-600 space-y-1">
          <li>• Keep your backup password secure</li>
          <li>• Update your backup after profile changes</li>
          <li>• Backups are end-to-end encrypted</li>
        </ul>
      </div>
    </div>
  );
}

With Multiple Providers

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

export function MultiProviderBackup() {
  const [activeProvider, setActiveProvider] = useState<string | null>(null);

  const checkBackupStatus = async () => {
    // Check status across multiple providers
    const providers = ['google', 'github', 'dropbox'];
    
    for (const provider of providers) {
      const response = await fetch(`/api/backup/status?provider=${provider}`);
      const status = await response.json();
      
      if (status.hasCloudBackup) {
        setActiveProvider(provider);
        return status;
      }
    }
    
    return { hasCloudBackup: false };
  };

  return (
    <div>
      <CloudBackupManager
        checkBackupStatus={checkBackupStatus}
        updateCloudBackup={updateCloudBackup}
      />
      
      {activeProvider && (
        <p className="mt-2 text-sm">
          Active provider: {activeProvider}
        </p>
      )}
    </div>
  );
}

In Dashboard Widget

import { CloudBackupManager } from 'bigblocks';

export function DashboardBackupWidget() {
  return (
    <div className="bg-white rounded-lg shadow p-6">
      <div className="flex items-center justify-between mb-4">
        <h3 className="font-semibold">Cloud Backup</h3>
        <span className="text-sm text-gray-500">Auto-sync enabled</span>
      </div>
      
      <CloudBackupManager
        checkBackupStatus={checkStatus}
        updateCloudBackup={updateBackup}
        onStatusChange={(status) => {
          // Update dashboard metrics
          updateDashboardMetrics({
            backupStatus: status.hasCloudBackup ? 'active' : 'none',
            lastSync: status.lastUpdated,
          });
        }}
      />
    </div>
  );
}

API Reference

This component provides cloud backup management functionality with configurable status checking and update capabilities.

API Integration

Status Check Endpoint

// GET /api/backup/status
interface BackupStatusResponse {
  hasCloudBackup: boolean;
  isOutdated?: boolean;
  lastUpdated?: number;
  provider?: string;
  size?: number;
  profileCount?: number;
}

Sync Endpoint

// POST /api/backup/sync
interface BackupSyncRequest {
  backup?: string; // Optional encrypted backup data
  forceUpdate?: boolean;
}

interface BackupSyncResponse {
  success: boolean;
  provider: string;
  timestamp: number;
  backupId: string;
}

Features

  • Status Monitoring: Real-time backup status checking
  • Automatic Updates: Detect and update outdated backups
  • Provider Display: Show which OAuth provider stores the backup
  • Last Update Time: Display when backup was last synchronized
  • Status Callbacks: React to backup status changes
  • Error Handling: Graceful error handling with user feedback

Styling

The component uses Radix Themes and can be customized:

/* Custom styling */
.cloud-backup-manager {
  padding: 1rem;
  border: 1px solid var(--gray-5);
  border-radius: var(--radius-3);
}

.backup-status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.update-button {
  margin-top: 0.5rem;
}

Best Practices

  1. Regular Checks: Implement periodic status checks
  2. Error Handling: Always handle API errors gracefully
  3. User Feedback: Show clear status messages
  4. Auto-sync: Consider implementing automatic synchronization
  5. Security: Ensure all backups are encrypted before cloud storage

Security Considerations

  1. Encryption: All backups are encrypted client-side
  2. OAuth Only: Uses OAuth providers as storage, not authentication
  3. No Credentials: Never store provider credentials
  4. Token Handling: Secure handling of auth tokens
  5. HTTPS Only: Always use secure connections

Troubleshooting

Status Not Updating

  • Verify checkBackupStatus returns correct format
  • Check network connectivity
  • Ensure proper authentication headers

Update Failing

  • Verify updateCloudBackup is properly implemented
  • Check OAuth provider permissions
  • Ensure backup data is properly formatted

Provider Not Showing

  • Confirm provider field is returned from status check
  • Verify OAuth connection is active
  • Check provider permissions

Notes for Improvement

Simplified Implementation: The actual component is more focused than the prompt suggested:

  • No multi-provider UI management (handled by callbacks)
  • No built-in auto-sync configuration
  • No direct provider linking/unlinking
  • Delegates all API operations to parent component
  • Focus on status display and update triggering

The actual implementation provides a clean interface for backup status management while leaving the complex provider and sync logic to the implementing application.