VeztaVezta
Guides

Frontend Development

Next.js patterns, feature modules, and code generation

The Vezta frontend is a Next.js 16 App Router application built with React 19, Tailwind CSS v4, and TanStack Query v5. It runs on port 3000 and connects to the backend API at localhost:3001.

Project Structure

app/
├── (landing)/          # Public marketing pages (1440px max-width)
├── (dashboard)/        # Main app with AppLayout (Navbar + BottomStatusBar)
└── (auth)/             # Login, onboarding, access-key (no shell chrome)
features/
├── markets/            # Market browsing, search, terminal
├── portfolio/          # Positions, orders, analytics
├── trading/            # Order form, execution
├── social/             # Leaderboard, copy trade, wallet tracker
├── monitor/            # News feed, signal detection
├── rewards/            # Points, missions, challenges
└── ...                 # auth, events, overlays, settings
components/
├── ui/                 # shadcn/ui primitives (new-york style)
├── layout/             # AppLayout, Navbar, BottomStatusBar
└── states/             # Skeletons, empty states, error states
lib/
├── api/gen/            # Auto-generated (never hand-edit)
├── api/client.ts       # Fetch wrapper with auth + retry
├── api/auth.ts         # In-memory access token management
├── ws/                 # Socket.IO + Jotai atoms
├── trading/            # PnL helpers, price impact
├── types/              # TypeScript interfaces
├── utils.ts            # cn(), formatUsd, timeAgo, etc.
└── constants.ts        # Categories, filters, nav items
hooks/                  # Custom hooks (order form, media query, etc.)
providers/              # ThemeProvider, QueryProvider, AuthProvider, etc.

Key Patterns

Feature Modules

Business logic lives in features/{domain}/components/, not in flat component directories. Each feature domain contains its own components and hooks. Pages in app/ compose these feature components.

State Management

  • TanStack Query v5 -- server state, caching, and data fetching via auto-generated hooks
  • Zustand -- UI state (e.g., terminal sidebar panel order and visibility)
  • Jotai -- WebSocket atoms for real-time data (prices, orderbook, trades)
  • URL state -- route params for market slugs (/market/[slug])

TanStack Query is configured with refetchOnWindowFocus: false, which differs from the default. This is intentional for a trading terminal where stale data is refreshed via WebSocket, not tab focus.

API Integration

All API hooks are auto-generated by Kubb from the backend's OpenAPI spec. The generated code lives in lib/api/gen/ and must never be hand-edited. See API Client Generation for the full pipeline.

The custom fetch wrapper at lib/api/client.ts provides Bearer token injection, automatic 401 refresh-and-retry with a promise lock (preventing multiple simultaneous refreshes), and credentials: 'include' for cookies. All generated hooks use this wrapper via a Kubb fetch alias in next.config.ts.

Auth System

Wallet-based auth with a two-cookie system:

  1. Backend sets an httpOnly refresh_token cookie (7 days)
  2. Frontend sets a non-httpOnly logged_in=1 cookie for middleware route protection
  3. Access token is stored in-memory (not localStorage) to prevent XSS
  4. Middleware only reads logged_in -- never the actual refresh token

Design System

  • Dark mode only (forced via ThemeProvider)
  • Accent color: lime-green #D4FF2B (bg-primary / text-primary)
  • Fonts: Space Grotesk for headings/UI, JetBrains Mono for prices/data
  • Green (#22C55E) = YES/Buy/Profit; Red (#EF4444) = NO/Sell/Loss
  • Tailwind v4 with CSS-first config via @theme block in app/globals.css
  • Icons from lucide-react

There is no tailwind.config.js. Tailwind v4 uses CSS variables defined in the @theme block in app/globals.css. Do not create a JS config file.

Dev Commands

pnpm dev              # Dev server on port 3000 (uses --webpack for WASM)
pnpm build            # Production build (Turbopack, no --webpack)
pnpm test             # Vitest
pnpm test -- --testPathPattern=navbar   # Run a single test
pnpm lint             # ESLint
pnpm generate         # Kubb: regenerate API client from OpenAPI spec

Environment Variables

VariableDefaultPurpose
NEXT_PUBLIC_API_URLhttp://localhost:3001/api/v1Backend API base
NEXT_PUBLIC_WS_URLws://localhost:3001WebSocket endpoint
OPENAPI_PATHhttp://localhost:3001/docs-jsonKubb OpenAPI source
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID--Reown WalletConnect ID
NEXT_PUBLIC_SOLANA_RPC_URLmainnet-betaSolana RPC endpoint

On this page