Skip to main content
The Monkeytype frontend is a high-performance single-page application built with SolidJS, a reactive UI framework that compiles to efficient vanilla JavaScript.

Technology Overview

Core Stack

Source location: frontend/src/ts/

Why SolidJS?

Solid was chosen for its performance characteristics:
  • Fine-grained reactivity: Updates only what changes, no virtual DOM
  • Compiled output: No runtime overhead
  • Small bundle size: Efficient for a typing test application
  • React-like syntax: Familiar JSX with better performance

Project Structure

Application Entry Point

The application bootstraps through a carefully orchestrated initialization sequence:
frontend/src/ts/index.ts

Component Architecture

Component Mounting System

Solid components are mounted to specific mount points in the HTML:
frontend/src/ts/components/mount.tsx:1
HTML mount points:

Component Types

1. Page Components (components/pages/)
  • Top-level route components
  • Example: ProfilePage, AboutPage
  • Handle data fetching via TanStack Query
2. Layout Components (components/layout/)
  • Structural components
  • Example: Footer, Overlays
3. Common Components (components/common/)
  • Reusable UI components
  • Shared across pages
4. Modal Components (components/modals/)
  • Dialog and modal implementations
  • Centralized in Modals component

State Management

Monkeytype uses a multi-layered state management approach:

1. Solid Signals (Reactive State)

frontend/src/ts/signals/
Used for: UI state, temporary state, derived state

2. Solid Stores (Complex State)

frontend/src/ts/stores/
Used for: Complex nested state, performance-critical state

3. Observable Pattern (Legacy State)

frontend/src/ts/observables/
Used for: Legacy code, gradual migration to Solid

4. TanStack Query (Server State)

frontend/src/ts/queries/
Features:
  • Automatic caching
  • Background refetching
  • Optimistic updates
  • Request deduplication

5. Local Storage (Persistent State)

frontend/src/ts/config.ts:1
Used for: User preferences, theme settings, test configuration

6. IndexedDB (Local Database)

frontend/src/ts/db.ts:1
Used for: Caching user data, offline support, PWA functionality

Routing

Monkeytype uses a custom routing system rather than a traditional SPA router:
frontend/src/ts/controllers/route-controller.ts
Why custom routing?
  • Typing test needs to stay mounted (preserve state)
  • Avoids full component unmount/remount
  • Optimized for the specific use case

API Client (APE)

The frontend uses ts-rest for type-safe API calls:
frontend/src/ts/ape/
Benefits:
  • Full type safety from backend to frontend
  • Autocomplete for all endpoints
  • Compile-time error checking
  • Single source of truth (contracts package)

Build System (Vite)

Development Build

frontend/vite.config.ts:327
Dev server features:
  • Hot Module Replacement (HMR)
  • Fast refresh for Solid components
  • TypeScript type checking
  • Instant server start (under 1 second)

Production Build

frontend/vite.config.ts:217
Build optimizations:
  • Code splitting by route
  • Tree shaking unused code
  • Asset optimization (images, fonts)
  • Vendor chunk splitting
  • Brotli compression

Bundle Analysis

frontend/vite.config.ts:259
Output bundles:
  • vendor.js - Third-party libraries
  • vendor-firebase.js - Firebase SDK
  • vendor-sentry.js - Error tracking
  • monkeytype-packages.js - Shared packages
  • [page].js - Page-specific code

Performance Optimizations

1. Lazy Loading

2. Memoization

3. Virtual Scrolling

4. PWA Caching

frontend/vite.config.ts:157

Testing

Unit Tests (Vitest)

Run tests:

Next Steps