-
Notifications
You must be signed in to change notification settings - Fork 1
Architecture Overview
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.) │
└─────────────────────────────────────────────────────┘
All state is client-side localStorage. This means:
- Zero server costs
- Complete user privacy
- Instant data access
- No cross-device sync (tradeoff)
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
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.
100+ visualization components are individually lazy-loaded via next/dynamic. Monaco Editor is also dynamically imported. Initial bundle stays small.
generateStaticParams() pre-renders all 25 language pages and 4 framework pages at build time for fast initial loads.
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
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)
| 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 |