Skip to main content

Suite Web Architecture

Trezor Suite Web is a browser-based application that provides access to Trezor wallet functionality without requiring installation. It’s built with modern web technologies and optimized for security and performance.

Overview

Suite Web is accessible at suite.trezor.io/web and runs entirely in the browser.

React 19.1.0

Modern UI with hooks and concurrent features

Redux Toolkit

Predictable state management

WebUSB API

Direct browser-to-device communication

Webpack 5

Optimized bundling and code splitting

Architecture Overview

┌────────────────────────────────────────┐
│              Browser                      │
│  ┌──────────────────────────────────┐  │
│  │  React Application              │  │
│  │  - @trezor/suite                │  │
│  │  - Redux Store                  │  │
│  │  - React Router                 │  │
│  └──────────────────────────────────┘  │
│  ┌──────────────────────────────────┐  │
│  │  @trezor/connect-web            │  │
│  │  - WebUSB Transport             │  │
│  │  - Device Communication         │  │
│  └──────────────────────────────────┘  │
│  ┌──────────────────────────────────┐  │
│  │  Browser APIs                   │  │
│  │  - IndexedDB (Storage)          │  │
│  │  - WebUSB (Device Access)       │  │
│  │  - Crypto (Encryption)          │  │
│  │  - Service Worker (Caching)     │  │
│  └──────────────────────────────────┘  │
└──────────────────┬─────────────────────┘

┌──────────────────┴─────────────────────┐
│          CDN / Backend                  │
│  - Static Assets                        │
│  - Firmware Binaries                    │
│  - Blockchain APIs                      │
│  - Fiat Rate Services                   │
└────────────────────────────────────────┘

Key Components

Application Layer

Core Application PackageThe main Suite package provides:
  • React components and screens
  • Redux store and middleware
  • Business logic
  • Routing and navigation
  • Hooks and utilities
// Entry point: packages/suite-web/src/index.tsx
import { Suite } from '@trezor/suite';
import { render } from 'react-dom';

render(
  <Suite />,
  document.getElementById('app')
);
The same @trezor/suite package is used in both Web and Desktop builds.

Key Differences: Web vs Desktop

Web

// @trezor/connect-web is part of bundle
import TrezorConnect from '@trezor/connect';
// ↑ Webpack replaces with '@trezor/connect-web'

// Direct WebUSB communication
const result = await TrezorConnect.getPublicKey(...);

Desktop

// @trezor/ipc-proxy in renderer
import TrezorConnect from '@trezor/connect';
// ↑ Proxies to main process via IPC

// Main process has real Connect with USB/HID
const result = await TrezorConnect.getPublicKey(...);
Web uses direct WebUSB; Desktop uses IPC to Node.js main process.

Build System

Package Structure

packages/suite-web/
├── src/
│   ├── index.tsx              # Entry point
│   ├── support/               # Support pages
│   └── static/                # Static assets
├── build/                     # Production output
│   ├── static/
│   │   ├── css/
│   │   ├── js/
│   │   └── connect/
│   │       └── data/
│   │           └── firmware/
│   └── index.html
├── package.json
└── preview.vite.config.mts    # Preview server config

Build Process

1

Development Build

yarn suite:dev
  • Webpack dev server on http://localhost:8000
  • Hot Module Replacement (HMR)
  • Source maps
  • Fast refresh
Experimental Vite:
yarn suite:dev:vite
Vite is experimental for development only. Production uses Webpack.
2

Production Build

yarn suite:build:web
Output: packages/suite-web/build/Optimizations:
  • Minification (Terser)
  • Code splitting
  • Tree shaking
  • Asset optimization
  • Gzip/Brotli compression
3

Bundle Analysis

yarn workspace @trezor/suite-web analyze
Opens Webpack Bundle Analyzer showing:
  • Bundle size breakdown
  • Module dependencies
  • Duplicate code
  • Optimization opportunities
4

Preview Production Build

yarn suite:build:web:preview
Runs Vite preview server with:
  • Production build
  • Security headers applied
  • Localhost testing
Access at: http://localhost:4173

Webpack Configuration

Key configurations in packages/suite-build/configs/web.webpack.config.ts:
Replace imports for web environment:
alias: {
  '@trezor/connect': '@trezor/connect-web',
  // Other platform-specific replacements
}
optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        priority: -10,
      },
      common: {
        minChunks: 2,
        priority: -20,
      },
    },
  },
}
  • Images: image-webpack-loader
  • SVGs: @svgr/webpack
  • Fonts: Subset and compress
  • Compression: Gzip + Brotli plugins

Security

Content Security Policy (CSP)

Production builds include strict CSP headers:
Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'wasm-unsafe-eval';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://suite.trezor.io https://*.trezor.io wss://blockbook.trezor.io;
  font-src 'self' data:;
  object-src 'none';
  base-uri 'self';
  form-action 'none';
  frame-ancestors 'none';
CSP headers are configured in the CDN/hosting platform (Cloudflare, Nginx, etc.).

Other Security Headers

X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()

HTTPS Only

Suite Web requires HTTPS. WebUSB API is only available on secure origins.

Browser Compatibility

Supported Browsers

BrowserVersionWebUSBNotes
Chrome90+✅ YesRecommended
Edge90+✅ YesChromium-based
Brave1.24+✅ YesPrivacy-focused
Opera76+✅ YesChromium-based
Firefox88+❌ NoNo WebUSB support
Safari14+❌ NoLimited support
Recommended: Chrome or Brave for full functionality.

Feature Detection

// Check WebUSB support
if ('usb' in navigator) {
  // WebUSB available
  await navigator.usb.requestDevice({ filters: [{ vendorId: 0x1209 }] });
} else {
  // Show warning or redirect to desktop download
  showWebUSBNotSupported();
}

Polyfills

Included polyfills:
  • Core-js for ES6+ features
  • Crypto polyfills for older browsers
  • Fetch polyfill

Development

Local Development

# Start dev server
yarn suite:dev

# Open browser
open http://localhost:8000

Environment Variables

Create .env.local in repository root:
# Enable React Query DevTools
TANSTACK_REACT_QUERY_DEV_TOOLS=true

# Custom backend URLs (optional)
BLOCKCHAIN_LINK_URL=http://localhost:8080

# Feature flags
FEATURE_FLAG_EXPERIMENTAL=true

Hot Module Replacement

// Enable HMR for Redux store
if (module.hot) {
  module.hot.accept('./store/rootReducer', () => {
    store.replaceReducer(require('./store/rootReducer').default);
  });
}

Development Tools

Redux DevTools

Browser extension for Redux debugging

React DevTools

Component tree inspection

Network Tab

Monitor API calls and WebUSB

Console

Debug logs and errors

Deployment

Build & Deploy

1

Build Production

yarn suite:build:web
2

Review Output

Check packages/suite-web/build/ directory:
  • Verify file sizes
  • Test bundle loading
  • Check source maps
3

Deploy to CDN

Upload build/ contents to CDN:
  • Cloudflare Workers
  • AWS S3 + CloudFront
  • Vercel
  • Netlify
4

Configure Headers

Set security headers on CDN:
  • Content-Security-Policy
  • X-Frame-Options
  • Cache-Control
5

Test Deployment

  • Test on multiple browsers
  • Verify WebUSB functionality
  • Check error tracking (Sentry)
  • Monitor performance

CI/CD Pipeline

Automated deployment via GitHub Actions:
# .github/workflows/deploy-web.yml
name: Deploy Suite Web

on:
  push:
    branches: [main, develop]

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node
        uses: actions/setup-node@v3
      - name: Install dependencies
        run: yarn
      - name: Build
        run: yarn suite:build:web
      - name: Deploy to CDN
        # ... deployment steps

Performance Optimization

Techniques:
  • Code splitting by route
  • Lazy loading components
  • Tree shaking unused code
  • Dynamic imports
// Lazy load heavy components
const AccountDetail = lazy(() => import('./screens/AccountDetail'));

// Render with Suspense
<Suspense fallback={<Loading />}>
  <AccountDetail />
</Suspense>
Target sizes:
  • Initial bundle: < 500 KB (gzipped)
  • Total app: < 5 MB (gzipped)

Monitoring & Analytics

Error Tracking

Sentry Integration:
import * as Sentry from '@sentry/browser';

Sentry.init({
  dsn: 'https://[email protected]/project',
  environment: 'production',
  release: `suite-web@${APP_VERSION}`,
  beforeSend(event) {
    // Filter sensitive data
    return sanitizeEvent(event);
  },
});

Performance Monitoring

// Web Vitals
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

getCLS(console.log);
getFID(console.log);
getFCP(console.log);
getLCP(console.log);
getTTFB(console.log);

Usage Analytics

Suite includes privacy-respecting analytics:
  • No personal data collected
  • Anonymized user IDs
  • Opt-out available
  • Compliant with GDPR

Troubleshooting

Possible causes:
  1. Unsupported browser (use Chrome/Brave)
  2. Non-HTTPS connection
  3. Missing USB permissions
  4. Another app is using the device
Solutions:
// Request permissions explicitly
await navigator.usb.requestDevice({
  filters: [{ vendorId: 0x1209, productId: 0x53C1 }]
});
# Clean build
rm -rf packages/suite-web/build
rm -rf node_modules/.cache

# Rebuild
yarn build:essential
yarn suite:build:web
  1. Check bundle size: yarn suite:analyze
  2. Profile with React DevTools
  3. Check network waterfall
  4. Verify CDN caching

Next Steps

Suite Desktop

Compare with desktop architecture

Suite Mobile

Explore mobile architecture

Connect API

Learn about Trezor Connect

Contributing

Contribute to Suite Web

Build docs developers (and LLMs) love