Tech Stack
Technologies used across frontend and backend
Vezta is built on a modern TypeScript stack. This page lists every major dependency and its role in the system.
Frontend (vezta-fe/)
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 16 | App Router, SSR, API proxy rewrites |
| React | 19 | UI rendering with Server Components |
| Tailwind CSS | v4 | CSS-first utility styling via @theme block in app/globals.css (no tailwind.config.js) |
| TanStack Query | v5 | Server state (90s staleTime, 10min gcTime, no refetch on focus) |
| Kubb | latest | OpenAPI code generation (types, Zod, fetch clients, hooks) |
| Socket.IO Client | v4 | Real-time WebSocket connection to /ws namespace |
| Jotai | latest | Atomic state for WebSocket data |
| Zustand | latest | Terminal sidebar panel state |
| shadcn/ui | new-york | Component primitives (dark mode, neutral base, sharp corners) |
| Lightweight Charts | v5 | TradingView financial charting |
| Recharts | -- | Data visualization for portfolio analytics |
| React Three Fiber | -- | 3D globe visualization on the monitor page |
| GSAP | -- | Landing page animations |
@thumbmarkjs/thumbmarkjs | -- | Device fingerprinting |
| Vitest | -- | Unit testing with jsdom + MSW v2 |
| Playwright | -- | End-to-end browser testing |
Key Patterns
- Kubb fetch alias -- All generated hooks route through
lib/api/kubb-fetch.tswhich injects Bearer tokens, handles 401 auto-refresh-and-retry with a promise lock, and setscredentials: 'include'. Aliased innext.config.tsfor both webpack and turbopack. - API proxy rewrite --
/api/:path*is rewritten toBACKEND_URL/api/:path*, keeping cookies same-origin in production. - Three-cookie auth --
refresh_token(httpOnly, set by backend),logged_in=1andbeta_access=1(frontend-set markers, read by middleware). - Dark mode only -- Forced via ThemeProvider. Lime-green accent
#D4FF2B, Space Grotesk for UI, JetBrains Mono for prices.
Backend (vezta-be/)
| Technology | Version | Purpose |
|---|---|---|
| NestJS | latest | Module-based application framework with DI |
| Fastify | latest | HTTP server (not Express) with cookie, helmet, rate-limit plugins |
| Prisma | 6.x | ORM with PostgreSQL, ~40 models, Decimal for financial values |
| PostgreSQL | 17 | Primary database (Docker container on each VM) |
| Redis | latest | Caching, Socket.IO adapter, BullMQ job queue backend |
| BullMQ | latest | Background job processing (market sync, signals, leaderboard, insider) |
| Socket.IO | v4 | WebSocket server at /ws, Redis adapter for horizontal scaling |
tweetnacl | -- | Solana wallet signature verification |
ethers | -- | EVM wallet signature verification |
class-validator | -- | DTO validation with decorators |
| Swagger | -- | Auto-generated OpenAPI spec at /docs (disabled in production) |
@react-email/components | -- | Email templates for notifications and waitlist |
grammy | ^1.42.0 | Telegram bot framework (signal-dispatch + interactive trading bots) |
gramjs | -- | Telegram MTProto client (real-time channel events when configured) |
argon2 | -- | Password hashing (admin/access-key) |
satori + @resvg/resvg-js + sharp | -- | OG image / share-card generation |
openai | -- | LLM client pointed at OpenRouter for AI predictions |
| Jest | -- | Unit and E2E testing with Testcontainers |
fast-check | -- | Property-based testing |
Key Patterns
- Global JWT guard -- All routes require authentication by default. Use
@Public()to exempt endpoints. - Structured errors -- All exceptions normalize to
{ statusCode, code, message }viaGlobalExceptionFilter. UseApiException(code, message, status). - Decimal precision --
@db.Decimal(18,2)for USD,@db.Decimal(10,6)for prices,@db.Decimal(18,6)for fees,@db.Decimal(5,4)for rates. - Multi-layer rate limiting -- Nginx (
api_general30r/s,api_auth5r/s) +@fastify/rate-limit(500/min global) + endpoint-level@RateLimitdecorator with Redis-backed sliding window. - CORS at Nginx -- Production CORS is set by Nginx, not NestJS. Modifying
enableCors()has no effect in prod -- update Nginx config on the VMs instead. - Bot UA filtering -- Fastify
onRequesthook returns 403 for curl/wget/scrapy/etc (exempts/api/v1/health).
Never use JavaScript floating-point numbers for financial values. The backend enforces Decimal types in Prisma for all monetary fields. On the frontend, decimal values from the API arrive as strings -- parse with care.
Mobile (vezta-mobile/) -- Planned
The mobile app is in design, with implementation planned but not yet shipped. The intended stack:
| Technology | Version | Purpose |
|---|---|---|
| Expo SDK | 55 | Managed workflow with EAS Build |
| React Native | 0.83 | Cross-platform mobile rendering |
| Expo Router | -- | File-based routing with typed routes |
| NativeWind | v4 | Tailwind CSS for React Native |
| React Native Reanimated | v4 | High-performance animations |
| TanStack Query | v5 | Server state with offline persistence via AsyncStorage |
expo-secure-store | -- | Secure refresh-token storage |
expo-local-authentication | -- | Biometric (Face ID / Touch ID) |
expo-notifications | -- | Push notifications |
@gorhom/bottom-sheet | -- | Trading sheet and modals |
The backend already has supporting modules (push-notification, app-version, device-token endpoints) ready for the mobile client.
Package Manager
All subprojects use pnpm. There is no root-level workspace package.json -- each subproject is independent with its own node_modules and lock file.
Node Version
Backend and frontend CI both use Node 20. Local development should run Node 20+ to match CI.