BlockbotX Architecture Overview
This document describes the system architecture of BlockbotX, an AI-powered crypto trading platform built on Next.js 16, PostgreSQL, and Redis. It covers all major layers from the client browser down through the data stores, background workers, and real-time infrastructure.
System Architecture
Client Browser
|
v
+----------------------------+
| proxy.ts |
| (Auth, CSP, Security |
| Headers, Maintenance) |
+----------------------------+
|
v
+----------------------------+
| Next.js 16 App Router |
| |
| +-- (marketing)/ | Public pages (landing, pricing, about)
| +-- (dashboard)/ | Authenticated dashboard
| +-- (admin)/ | Admin panel (role-gated)
| +-- api/ | REST API (232 route files)
+----------------------------+
|
v
+----------------------------+
| server.ts |
| Custom Node.js Server |
| |
| +-- Socket.io | Real-time price feeds + notifications
| +-- Bot Scheduler | 60s interval, per-bot execution
| +-- Portfolio Tracker | Hourly cron snapshots
| +-- Telegram Bot | Notification delivery
| +-- Rate Limiter | Redis-backed, per-path tiers
+----------------------------+
| |
v v
+----------------+ +------------------+
| PostgreSQL 16 | | Redis 7 |
| via Drizzle | | (ioredis) |
| ORM + pg Pool | | |
| | | - Cache |
| | | - Rate Limiting |
| | | - BullMQ Queues |
| | | - Circuit Breaker|
+----------------+ +------------------+
Application Layers
1. Proxy Layer (proxy.ts)
The proxy is the first code that runs on every incoming request. It uses the Next.js 16 convention where proxy.ts with an export async function proxy() replaces the deprecated middleware.ts file.
Runtime: Edge runtime using jose for JWT verification (Edge-compatible, unlike jsonwebtoken).
Responsibilities:
- CSP nonce generation -- A unique nonce is generated per request via
crypto.randomUUID(), encoded to base64, and injected into theContent-Security-Policyheader. The nonce is passed to server components via thex-noncerequest header and consumed inapp/layout.tsxfor script tags (e.g., Stripe JS). - Authentication redirects -- Routes are classified as public, auth (signin/signup), dashboard (protected), or admin (role-gated). Unauthenticated users hitting protected routes are redirected to
/signin?from=<path>. Authenticated users hitting auth routes are redirected to/dashboard. Unverified users are redirected to/verify-email. - Admin route protection -- Defense-in-depth check that verifies JWT contains an admin or superadmin role before allowing access to
/admin/*routes. Primary enforcement remains at the API layer. - Banned/disabled account handling -- Tokens belonging to banned or disabled users trigger an immediate redirect to
/signin?reason=account_restrictedwith cookies cleared. - Maintenance mode -- Fetches maintenance status from
/api/system/statuswith a 30-second in-memory cache. When active, non-admin users receive 503 on API routes and are redirected to/maintenanceon page routes. Admins bypass maintenance mode entirely. - Security headers -- Every response receives:
Content-Security-Policy(withstrict-dynamicand nonce),X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy: strict-origin-when-cross-origin,Permissions-Policy(camera, microphone, geolocation all denied), andStrict-Transport-Securityin production.
Route matcher: Configured to skip _next/static, _next/image, favicon, and common asset extensions. Also skips prefetch requests.
2. Frontend Layer
Framework: Next.js 16.1.6 with the App Router. React 19.2.4.
Route groups:
(marketing)/-- Public-facing pages: landing, features, pricing, about.(dashboard)/-- Authenticated user interface: bot management, portfolio, trading, DeFi, analytics, settings.(admin)/-- Admin panel for system management, user administration, and platform configuration.- Standalone auth pages:
signin/,signup/,forgot-password/,reset-password/,verify-email/. - Legal pages:
terms/,privacy/,disclaimer/. maintenance/-- Displayed when maintenance mode is active.
Styling and UI:
- Tailwind CSS v4 with
tailwindcss-animatefor animations. - Radix UI primitives (shadcn/ui pattern) for accessible, unstyled components -- 30+ Radix packages including dialog, dropdown, tabs, select, accordion, toast, and tooltip.
- Framer Motion for page transitions and complex animations.
- Two fonts: Space Grotesk (display,
--font-display) and JetBrains Mono (monospace,--font-mono). - Dark/light theme support via
next-themeswith dark as default.
Data fetching:
- SWR for client-side data fetching with automatic revalidation.
- Custom
useApihook (hooks/use-api.ts) providing a generic fetch wrapper with URL, response extraction, and empty-value support. - Domain-specific hooks:
use-bots,use-portfolio,use-market-data,use-dashboard-data,use-dca-bot,use-signal-bot,use-pump-screener,use-bot-performance,use-notifications.
Real-time:
useSockethook (hooks/use-socket.ts) manages Socket.io client connections.useWebSockethook (hooks/use-websocket.ts) for raw WebSocket connections (Binance streams).- Events include price updates, portfolio changes, bot status, and notifications.
Error handling:
- Root-level
ErrorBoundarycomponent wraps all children inapp/layout.tsx. - Per-route
error.tsxboundary files for granular error recovery.
3. API Layer
Scale: 232 route files under app/api/, organized by domain.
Consistent patterns:
asyncHandler()wrapper for automatic try/catch and error response formatting.getAuthUser()for JWT-based authentication on protected endpoints.- Zod schema validation on request bodies and query parameters.
- Typed error classes:
BadRequestError,UnauthorizedError,NotFoundError,ConflictError.
Rate limiting: Four tiers applied at the HTTP server level via getLimiterForPath():
api-- General API routes (standard limits).auth-- Authentication endpoints (stricter to prevent brute force).strict-- Sensitive operations (very low limits).user-- Per-user identification via JWT userId extracted from Authorization header oraccessTokencookie, with IP fallback for anonymous requests.
Webhooks (/api/webhooks/) and health checks (/api/health) are exempt from rate limiting.
CSRF protection: Handled at the route level via withCsrfProtection wrapper on mutation endpoints (not in the proxy, due to Edge runtime compatibility constraints).
Webhook security: Stripe webhooks use stripe.webhooks.constructEvent() for HMAC-SHA256 signature verification against the raw request body.
4. Business Logic Layer (lib/)
The lib/ directory contains 35+ domain modules, each with barrel exports (index.ts).
Bot engine (lib/bot/):
- Strategies: Strategy pattern with a factory (
strategy-factory.ts). Implementations:trend-following.ts,mean-reversion.ts,breakout.ts, all extendingbase-strategy.ts. - Engines: Five bot types with dedicated engine files --
arbitrage-bot.ts,dca-bot.ts,signal-bot.ts,pump-screener.ts, plus the generalbot-executor.ts. - Risk management:
drawdown-tracker.ts,position-sizer.ts,risk-validator.ts,stop-loss-manager.ts,take-profit-manager.ts. - Execution:
execution-context.tsfor per-execution state,position-manager.tsfor position tracking,paper-trading.tsfor simulation mode. - Performance: Backtesting (
lib/bot/backtest/), performance tracking (lib/bot/performance/), and technical indicators (lib/bot/indicators/).
Exchange integrations:
- Binance: via
binance-api-nodelibrary (lib/binance/). WebSocket streams for real-time market data. - OKX: Custom raw fetch client with HMAC-SHA256 signing (
lib/okx/client.ts). Base URLhttps://my.okx.com, symbol formatBTC-USDT(hyphen-separated), passphrase-based auth with optionalx-simulated-trading: 1header for demo mode. - Unified exchange interface via
lib/exchange/.
DeFi protocols (lib/defi/): Staking, yield farming, and liquidity provision across Ethereum, BSC, and Polygon networks. Uses ethers v6 and viem for blockchain interaction, @solana/web3.js for Solana.
Financial calculations: All monetary values use Decimal from decimal.js (backed by Decimal(65,30) in PostgreSQL, with automatic conversion via a custom Drizzle type in drizzle/custom-types.ts). Never floating-point arithmetic for financial data.
Other domains:
lib/auth/-- JWT generation/verification, session management (7-day expiry).lib/encryption/-- AES-256-GCM encryption for exchange API keys (format:iv:authTag:encryptedData).lib/security/-- Rate limiter, CORS, CSRF, input sanitization, auth middleware, security logging.lib/notifications/-- Multi-channel: email (Nodemailer), Telegram (Telegraf), in-app (Socket.io), push.lib/stripe/-- Subscription billing, payment processing.lib/analytics/-- User and platform analytics.lib/market-data/-- Price feeds, market data aggregation.lib/portfolio/-- Portfolio calculation and tracking.lib/cache/-- Redis-backed caching layer.lib/queue/-- BullMQ job queue configuration.lib/config/-- Environment validation (validate-env.ts).lib/formatters.ts-- Shared formatting utilities (currency, percentage, date, address truncation, profit/status colors).lib/api-endpoints.ts-- Typed API route constants (~180 routes).lib/styles/constants.ts-- UI color constants (profit, status, risk) and layout values.
5. Data Layer
PostgreSQL 16:
- Accessed via Drizzle ORM 0.45 with the pg (node-postgres) driver.
- Connection pooling via a
pg.Poolinstance (max 20 connections in production, 5 in test, with 10-second connection timeout). - Singleton pattern in
lib/db.tsprevents multiple Drizzle instances in development (attached toglobalThis). - Schema defined in
drizzle/schema/*.tswith migrations indrizzle/migrations/. - All financial fields use
Decimal(65,30)-- including prices, quantities, P&L, percentages, APY, TVL, and portfolio values.
Redis 7:
- Client:
iorediswith automatic reconnection (exponential backoff, max 2 seconds). maxRetriesPerRequest: nullas required by BullMQ.- Dedicated subscriber connection (
redis.duplicate()) for BullMQ pub/sub. - Circuit breaker:
isRedisReady()tracks connection state via event listeners (ready,error,close,end). Safe wrappers (safeGet,safeSet,safeDel) return null/false when Redis is down instead of throwing. - Uses: Response caching, rate limit counters, BullMQ job queues, distributed locks for bot execution, maintenance status.
6. Real-time Layer
Architecture: Socket.io server attached to the custom HTTP server created in server.ts. Two Socket.io modules exist:
lib/socket/server.ts-- Notification-focused server with per-user rooms (user:{userId}) for targeted event delivery. UsesverifySocketAuthfromlib/socket/auth.ts.lib/websocket/server.ts-- Market data server handling price feed subscriptions and portfolio updates. Integrates with Binance WebSocket manager for real-time price streams.
Authentication: JWT verified on WebSocket handshake. Token sourced from (in order): socket.handshake.auth.token, Authorization header, or accessToken cookie.
Room structure:
user:{userId}-- Per-user notification delivery.prices:{sorted-symbols}-- Shared price feed rooms (subscribers join/leave dynamically; Binance WebSocket subscriptions are created/destroyed based on room occupancy).portfolio:{userId}-- Per-user portfolio update delivery.
Events:
price:update-- Real-time price changes from Binance streams.prices:initial-- Initial price snapshot on subscription.portfolio:update-- Portfolio value changes (emitted by portfolio tracker).notification:read-- Client acknowledgment of notification read.ping/pong-- Keep-alive mechanism.
Custom Server (server.ts)
BlockbotX uses a custom Node.js server instead of next start to co-locate several services in a single process.
Startup sequence:
- Load environment variables from
.env.localand.env. - Validate environment variables (
validateEnv()-- exits on failure). - Call
app.prepare()to initialize Next.js. - Create HTTP server with rate limiting applied to all
/api/routes (excluding webhooks and health checks). - Initialize services in parallel:
- Socket.io WebSocket server (
initSocketServer). - Portfolio tracker (
initPortfolioTracker). - Telegram bot (
startTelegramBot).
- Socket.io WebSocket server (
- Rebuild bot state from database in parallel:
- Rebuild open positions (
rebuildPositions). - Rebuild paper trading states (
rebuildPaperTradingStates). - Rebuild drawdown tracking states (
rebuildDrawdownStates).
- Rebuild open positions (
- Start the bot scheduler (
startScheduler). - Listen on configured host and port (default
0.0.0.0:3000).
Graceful shutdown: Handles SIGTERM and SIGINT. Sequentially closes the HTTP server, Socket.io server, bot scheduler, and database connection before exiting.
Resilience: Service initialization failures (Socket.io, portfolio tracker, bot scheduler) are logged but do not crash the server. The application can still serve HTTP requests without these services.
Background Workers
Bot Scheduler (lib/bot/engine/scheduler.ts)
- Singleton
BotSchedulerclass with a 60-second polling interval. - On startup, loads all bots with
status: "active"from the database. - Each bot has a configurable
executionInterval(default 5 minutes). The scheduler trackslastExecutionAtandnextExecutionAtper bot. - Every 60 seconds, identifies due bots and calls
executeBots()for parallel execution. - Supports dynamic management:
addBot,removeBot,updateBot,executeNow(force immediate execution). - Auto-starts the interval timer when the first bot is added, even if
start()was not called. - Exposes status via
getSchedulerStatus()(running state, bot count, next 10 upcoming executions).
Portfolio Tracker (lib/workers/portfolio-tracker.ts)
- Singleton
PortfolioTrackerclass usingnode-cron. - Hourly tracking (
0 * * * *): Iterates all active exchange connections, decrypts API keys, calculates portfolio value via the Binance API, saves snapshots toPortfolioHistory, and emits updates via Socket.io. - Daily cleanup (
0 0 * * *): Deletes portfolio history older than 90 days. - Tracks one user at a time within each cycle, with success/error counting and logging.
- Includes
trackUserPortfolio()for on-demand single-user tracking.
Telegram Bot (lib/notifications/telegram-bot.ts)
- Initialized during server startup via
startTelegramBot(). - Uses the Telegraf library for Telegram Bot API integration.
- Delivers notifications to users who have linked their Telegram accounts.
Key Design Decisions
| Decision | Rationale |
|---|---|
Custom server.ts instead of next start | Enables Socket.io, bot scheduler, portfolio tracker, and Telegram bot to run in the same Node.js process, avoiding the complexity of separate microservices. |
proxy.ts instead of middleware.ts | Next.js 16.1.6 convention. The proxy.ts file with export async function proxy() replaces the deprecated middleware pattern. Build output confirms: f Proxy (Middleware). |
| AES-256-GCM for exchange API key encryption | Keys are never stored in plaintext. Encryption uses native Node.js crypto (no third-party libraries). Format: iv:authTag:encryptedData. Requires a 32-character ENCRYPTION_KEY environment variable. |
Decimal(65,30) for all financial fields | Prevents floating-point precision loss in financial calculations. Accumulated rounding errors in float-based systems can lead to incorrect P&L, balances, and trading decisions. Decimal columns return decimal.js Decimal objects via a custom Drizzle type (drizzle/custom-types.ts) -- use .toNumber() for display or Decimal methods for arithmetic. |
| JWT in httpOnly cookies (not localStorage) | Prevents XSS-based token theft. Tokens are set as httpOnly, Secure (in production), SameSite=Strict cookies. |
| Redis circuit breaker | isRedisReady() and safe wrappers (safeGet, safeSet, safeDel) allow the application to degrade gracefully when Redis is unavailable instead of crashing. |
| Edge-compatible JWT in proxy | The proxy runs on the Edge runtime, which does not support Node.js jsonwebtoken. The jose library provides Edge-compatible JWT verification. |
| Per-user rate limiting via JWT userId | Rate limits are tied to the authenticated user (extracted from JWT in Authorization header or cookie), not just IP address. This prevents a single user from consuming rate limits across multiple IPs, and ensures users behind shared IPs are not unfairly limited. Falls back to IP for anonymous requests. |
| Session expiry: 7 days | Consistent across NextAuth, JWT refresh tokens, and session cookies. Reduced from 30 days for improved security posture. |
CSP with strict-dynamic | Nonce-based CSP with strict-dynamic allows scripts loaded by trusted (nonced) scripts without listing every CDN domain. No unsafe-eval or unsafe-inline in production. |
Directory Overview
BlockbotX/
|
|-- app/ Next.js App Router pages and API routes
| |-- (admin)/ Admin panel (role-gated)
| |-- (dashboard)/ Authenticated user dashboard
| |-- (marketing)/ Public marketing pages
| |-- api/ REST API routes (232 route files)
| |-- signin/ Sign-in page
| |-- signup/ Registration page
| |-- verify-email/ Email verification flow
| |-- forgot-password/ Password reset request
| |-- reset-password/ Password reset completion
| |-- maintenance/ Maintenance mode page
| |-- terms/ Terms of service
| |-- privacy/ Privacy policy
| |-- disclaimer/ Legal disclaimer
| +-- layout.tsx Root layout (fonts, theme, CSP nonce, error boundary)
|
|-- components/ React components
| |-- ui/ shadcn/ui primitives (30+ Radix-based components)
| |-- shared/ Shared components (KpiCard, ConfirmModal)
| |-- marketing/ Landing page and marketing components
| |-- admin/ Admin panel components
| |-- dashboard-content/ Dashboard page content components
| |-- *-dashboard/ Bot-specific dashboard components (ai, arbitrage, dca, signal, pump-screener)
| |-- *-interface/ Feature interface components (defi, portfolio, staking, strategies, etc.)
| +-- trading-interface/ Trading UI components
|
|-- hooks/ React hooks
| |-- use-api.ts Generic API fetch hook
| |-- use-auth.ts Authentication state hook
| |-- use-socket.ts Socket.io client hook
| |-- use-websocket.ts Raw WebSocket hook
| +-- use-*.ts Domain-specific data hooks (bots, portfolio, market-data, etc.)
|
|-- lib/ Business logic and infrastructure (35+ modules)
| |-- auth/ JWT generation, verification, session management
| |-- binance/ Binance API client and WebSocket manager
| |-- blockchain/ Blockchain interaction utilities
| |-- bot/ Bot engine, strategies, risk management, backtesting
| |-- cache/ Redis-backed caching layer
| |-- config/ Environment validation
| |-- constants/ Application constants (DCA, exchanges)
| |-- db.ts Drizzle client singleton
| |-- defi/ DeFi protocol integrations (staking, farming, liquidity)
| |-- email/ Email sending via Nodemailer
| |-- encryption/ AES-256-GCM encryption for API keys
| |-- exchange/ Unified exchange interface
| |-- formatters.ts Shared formatting utilities
| |-- logger.ts Winston logger with sensitive field redaction
| |-- market-data/ Price feeds and market data aggregation
| |-- notifications/ Multi-channel notifications (email, Telegram, in-app)
| |-- okx/ OKX exchange client (custom HMAC-SHA256 signing)
| |-- portfolio/ Portfolio calculation engine
| |-- queue/ BullMQ job queue configuration
| |-- redis/ Redis client with circuit breaker
| |-- security/ Rate limiter, CORS, CSRF, sanitization, auth middleware
| |-- signals/ Trading signal processing
| |-- socket/ Socket.io notification server
| |-- storage/ File storage (S3)
| |-- stripe/ Stripe billing integration
| |-- styles/ UI style constants
| |-- subscriptions/ Subscription tier logic
| |-- websocket/ Socket.io market data server
| +-- workers/ Background workers (portfolio tracker)
|
|-- drizzle/ Database schema and migrations
| |-- schema/ Drizzle schema files (users.ts, trading.ts, bots.ts, defi.ts, etc.)
| |-- custom-types.ts Custom Decimal type for Decimal(65,30) columns
| |-- migrations/ SQL migration files
| +-- seed.ts Database seed script
|
|-- types/ TypeScript type definitions
| |-- bot.ts Bot-related types
| |-- trading.ts Trading types
| |-- defi.ts DeFi types
| |-- user.ts User and ExchangeConnectionInfo types
| |-- dashboard.ts Dashboard data types
| |-- api.ts API response types
| |-- common.ts Shared utility types
| |-- admin.ts Admin panel types
| +-- index.ts Barrel export
|
|-- __tests__/ Unit tests (Jest)
|-- tests/ API integration tests (Jest + Supertest)
|-- e2e/ End-to-end tests (Playwright, 11 spec files)
|-- scripts/ Utility scripts (backup, deploy, monitoring, database)
|-- public/ Static assets
|-- docs/ Documentation
|
|-- server.ts Custom Node.js server entry point
|-- proxy.ts Next.js 16 proxy (replaces middleware.ts)
+-- package.json Dependencies and scripts
Technology Stack Summary
| Layer | Technology | Version |
|---|---|---|
| Runtime | Node.js | -- |
| Framework | Next.js (App Router) | 16.1.6 |
| UI Library | React | 19.2.4 |
| Language | TypeScript | 5.9.x |
| Styling | Tailwind CSS | 4.x |
| Components | Radix UI (shadcn/ui) | Various |
| Animation | Framer Motion | 12.x |
| Database | PostgreSQL | 16 |
| ORM | Drizzle ORM | 0.45.x |
| Cache/Queue | Redis (ioredis) | 7 |
| Job Queue | BullMQ | 5.x |
| Real-time | Socket.io | 4.8.x |
| Auth | JWT (jose + jsonwebtoken) | -- |
| Encryption | Node.js native crypto (AES-256-GCM) | -- |
| Payments | Stripe | 20.x |
| Nodemailer | 7.x | |
| Telegram | Telegraf | 4.x |
| Blockchain | ethers v6, viem, @solana/web3.js | Various |
| Validation | Zod | 4.x |
| Monitoring | Sentry | 10.x |
| Logging | Winston | 3.x |
| Testing | Jest, Playwright, Supertest, MSW | Various |
| Package Manager | pnpm | -- |