Skip to content

Architecture Overview

dagustin415 edited this page Feb 12, 2026 · 4 revisions

Architecture Overview

System Design

Coding Drills is a client-heavy SPA with static generation where possible. There is no database — all content is static TypeScript data, all user state lives in localStorage, and AI features run locally via WebGPU.

┌─────────────────────────────────────────────────────┐
│                  Presentation Layer                  │
│   Next.js App Router │ React 19 │ Tailwind CSS 4    │
├─────────────────────────────────────────────────────┤
│                     Data Layer                       │
│  Static TypeScript modules (problems, exercises,     │
│  quizzes, methods, cheatsheets, UI patterns)         │
├─────────────────────────────────────────────────────┤
│                    State Layer                        │
│  React Context (Theme, Progress) │ Custom Hooks      │
│  localStorage persistence │ useSyncExternalStore     │
├─────────────────────────────────────────────────────┤
│                  Execution Layer                      │
│  In-browser JS/TS runner │ Pattern validation         │
│  API route for TS transpilation                      │
├─────────────────────────────────────────────────────┤
│                     AI Layer                         │
│  WebLLM (Llama-3.1-8B local) │ OpenAI (cloud opt.)  │
└─────────────────────────────────────────────────────┘

Key Design Decisions

1. No Database

All state is client-side localStorage. This means:

  • Zero server costs
  • Complete user privacy
  • Instant data access
  • No cross-device sync (tradeoff)

2. Static Data as TypeScript Constants

All problems, exercises, quizzes, and reference content are defined as typed TypeScript constants in /lib/. Benefits:

  • Full type safety at compile time
  • Zero-latency data access
  • Easy to validate with TypeScript compiler
  • Tradeoff: content changes require code changes and redeploy

3. Local-First AI

WebLLM runs Llama-3.1-8B-Instruct locally via WebGPU (~3GB first download, cached after). No API keys needed. OpenAI is an optional cloud fallback.

4. Aggressive Code Splitting

100+ visualization components are individually lazy-loaded via next/dynamic. Monaco Editor is also dynamically imported. Initial bundle stays small.

5. Static Generation

generateStaticParams() pre-renders all 25 language pages and 4 framework pages at build time for fast initial loads.

Project Structure

coding-drills/
├── app/                    # Next.js App Router pages
│   ├── [language]/         # Per-language routes (25 languages)
│   ├── frontend-drills/    # Frontend framework routes (4 frameworks)
│   ├── interview/          # AI mock interview
│   ├── regex/              # Regex trainer
│   ├── pattern-quiz/       # Algorithm pattern quiz
│   ├── links/              # External links
│   └── api/transpile/      # TypeScript transpilation endpoint
├── components/             # React components
│   ├── visualizations/     # 100+ algorithm visualizations
│   └── navigation/         # Nav components
├── hooks/                  # Custom React hooks
├── lib/                    # Business logic & data
│   ├── problems/           # 25 language problem sets
│   ├── exercises/          # Building Blocks exercises
│   ├── methods/            # Method reference data
│   ├── cheatsheets/        # 25 language cheatsheets
│   ├── frontend-drills/    # Frontend drill system
│   ├── regexTrainer/       # Regex trainer engine
│   ├── interview/          # AI interview system
│   ├── core/               # Shared types & constants
│   └── services/           # Storage adapters
├── e2e/                    # Playwright E2E tests
├── stories/                # Storybook stories
└── scripts/                # Build & generation scripts

Dependency Flow

app/ pages ──→ components/ (UI rendering)
     │
     ├──→ lib/ (data + business logic)
     │
     └──→ hooks/ (state management)
              │
              └──→ lib/storage (localStorage persistence)

components/ProgressProvider ──→ localStorage
components/ThemeProvider ──→ localStorage
lib/codeValidator ──→ lib/codeRunner (JS/TS execution)
components/visualizations/ ──→ next/dynamic (lazy loading)

SSR/CSR Split

Component Type Rendering Examples
Layouts Server Component [language]/layout.tsx, [framework]/layout.tsx
Metadata Server generateMetadata() in layouts
Static params Build time generateStaticParams() for languages/frameworks
Interactive pages Client ('use client') Drill, Quiz, Exercise, UI Pattern detail pages
Monaco Editor Client (dynamic import) { ssr: false }
Visualizations Client (dynamic import) { ssr: false } via registry

Clone this wiki locally