Skip to content

Repository files navigation

Crypto Live Markets

Demo project showcasing mastery of React, best practices, advanced patterns, and a modern web stack.

Why this repo

This codebase is intentionally crafted as a teaching/demo project. It highlights production-grade techniques while staying approachable:

  • Modern React 19 with TypeScript and Vite 7
  • Robust data and realtime layers (TanStack Query + resilient WebSocket client)
  • Clean architecture (services, providers, hooks, stores, entities, components)
  • Strong error handling strategy (error boundaries + global error manager + typed API errors)
  • Performance-conscious rendering (rAF batching, memoization, selective subscriptions)
  • Opinionated quality gates (strict TS, type-aware ESLint, tests with Vitest/MSW)

Features at a glance

  • Live market data via WebSocket with:
    • Exponential backoff + jitter reconnection
    • Heartbeat pings and smart close-code handling
    • Message queueing while disconnected
    • Online/offline awareness
  • Markets page and trade page with:
    • Candlestick chart, order book, live trades, and tickers
    • Favorites with cross‑tab sync via localStorage events
    • Sorting, filtering, and search ergonomics
  • HTTP layer built on Axios with a typed APIClient<T> and unified APIError
  • React Query for cache, retries, and error boundary interop
  • Typed global state with Zustand stores
  • Defensive error boundaries with isolation per section

Stack

  • Runtime/UI: React 19, React Router 7, Bootstrap 5
  • Data: TanStack React Query 5, Axios
  • State: Zustand 5
  • Forms/Validation: React Hook Form, Zod
  • Realtime: Custom WebSocket client (browser native WS)
  • Tooling: Vite 7, TypeScript 5 (strict), ESLint (type-aware), Vitest + Testing Library + MSW

Architecture overview

Key directories and responsibilities:

  • src/services/
    • api-client.ts: Generic, typed HTTP client that normalizes errors into APIError
    • ws-client.ts: Resilient WebSocket client (reconnect + queue + heartbeat)
  • src/providers/
    • webSocketProvider.tsx: App-scoped WS instance wired via React Context
  • src/hooks/
    • useMarkets.ts: Markets query with sensible cache times
    • useWireSocket.ts: Batches WS messages with requestAnimationFrame into stores
  • src/store/ (Zustand)
    • tickerStore.ts, bookStore.ts, tradeStore.ts, candleStore.ts
  • src/utils/
    • globalErrorHandler.ts: Catches unhandled rejections/JS errors and filters benign noise
  • src/config/
    • constants.ts: Centralized app, query, WS, and cache configuration
  • src/pages/ and src/components/
    • Error boundaries, candlesticks, order book, trades, tickers, etc.

Vite dev server proxies HTTP and WS requests to Poloniex (see vite.config.ts) to simplify local development and CORS.


Best practices and advanced patterns demonstrated

  • TypeScript strict mode with additional compiler safety checks
  • Type-aware ESLint config; consistent import type usage
  • Error boundaries with per-section isolation and reset keys
  • Global error manager for cases boundaries can’t catch (e.g., unhandled rejections)
  • Unified error shape (APIError) to interop with React Query’s throwOnError
  • Realtime resiliency: reconnect/backoff/jitter, queueing, heartbeat, online/offline listeners
  • Render throughput: requestAnimationFrame batching for fast WS bursts
  • State updates via small focused stores and selectors (Zustand)
  • Cross-tab persistence using the storage event (favorites)
  • Proxying WS/HTTP in dev for clean origins and headers

Getting started

Prerequisites:

  • Node.js 18+ (LTS recommended)
  • npm 9+ (or your favorite package manager)

Install dependencies:

npm install

Run the app (Vite dev server):

npm run dev

Then open http://localhost:5173

Build for production:

npm run build

Preview the production build locally:

npm run preview

Quality and tests:

# Lint (type-aware ESLint)
npm run lint

# Unit/integration tests (Vitest)
npm run test

# Coverage report
npm run test:coverage

# Test UI runner
npm run test:ui

Implementation highlights

Resilient WebSocket client (src/services/ws-client.ts)

  • Exponential backoff with jitter and a max delay cap
  • Differentiates retryable vs non‑retryable close codes
  • Queues outbound messages when disconnected, flushes on open
  • Heartbeat ping to keep idle connections alive
  • Online/offline awareness with auto reconnect when network restores

rAF-batched store updates (src/hooks/useWireSocket.ts)

  • Buffers ticker/candle/book/trade messages and flushes via requestAnimationFrame
  • Minimizes render storms during high‑throughput bursts
  • Normalizes payloads into numeric types before store writes

Error strategy

  • ErrorBoundaryWrapper with section isolation and React Query reset integration
  • APIError for HTTP: status, data payload, and retryability hints
  • GlobalErrorManager to capture unhandled rejections and JS errors, filtering benign browser noise

Local dev notes

  • Dev proxy targets for HTTP (/poloniex) and WS (/pws) are configured in vite.config.ts.
  • No API keys are required for this demo; endpoints are public. If your environment requires different hosts, adjust the proxy targets or wire environment variables (e.g., VITE_API_BASE_URL, VITE_WS_URL).

Roadmap ideas (nice-to-haves)

  • More test coverage around WS reconnection and store logic
  • Storybook for component documentation
  • Accessibility audit (ARIA, keyboard navigation, focus management)
  • Discriminated unions for WS message shapes end‑to‑end
  • Immer‑powered immutable updates for large store merges

License

MIT — use freely for learning and demos.

About

Demo project showcasing mastery of React, best practices, advanced patterns, and a modern web stack.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages