I got off FrontDesk not satisfied with its UI/UX, and figured: FrontDesk already taught me some things, so why not build something frontend-heavy and actually learn useRef, useMemo, rendering, and state management properly this time.
Back in early college, I'd built a simple typing checker: a plain <textarea> where typing checked against the target word and swapped CSS classes. Very simple. This time, with more knowledge and AI tools to ask for help and explain things along the way, I figured I'd rebuild it properly as a retro RobCo CRT terminal app: Typedesk.
I was completely blown away by how miserable the experience got.
1. Where It Worked: Modules 1 & 2
Up through Module 2 (Setup, Design System & Event Architecture), I could actually keep up and understand what was happening.
I set up localStorage persistence, built useLocalStorage and useThemeSwitcher hooks, and put together a 5-theme CRT design system (FALLOUT green, WYSE amber, RADAR emerald, CODEX parchment, CYBER hot magenta).
I was tracking every decision:
Managing root
[data-theme="..."]CSS custom properties on<html>as the single source of truth, so theme switches bypassed React's Virtual DOM diffing entirely.Writing an anti-FOUT hydration script to kill theme flashes on load.
Using a render-phase state-adjustment pattern to update state during render instead of chasing cascading
useEffectre-renders.
I was thinking, "okay, I'll drop a useMemo here and there" - everything felt under control.
The 5-theme CRT switcher: Fallout Green, Wyse Amber, Cold War Radar, Monastic Codex, Cyberpunk Edo.
2. The Wall: Module 3 (Hot-Path Rendering & Caret Math)
Then I hit Module 3: Hot-Path Rendering & Caret Math. That's where the typing engine came in, and I got completely floored.
My god. Both Gemini and Claude started hallucinating and couldn't figure it out. Forget teaching me best practicesโthey couldn't even implement a working approach once React's Virtual DOM state loops got mixed with monospace caret pixel math. One prompt would fix caret drift but break line wrapping; the next would fix wrapping and trigger infinite re-renders instead.
The caret math wasn't just "move right after each character." I had to calculate the exact pixel width of every character across different monitors, handle monospace line-breaking, sync it with CSS transitions, and run a high-precision performance.now() monotonic timer on top of all of it.
It felt more like designing an operating system than building a website. Like, damn.
I was in a rush, so I thought: fuck it, let's push. I pushed again, and again, juggling prompts from here and there. The sheer complexity was unfathomable to me: how does a typing engine website get this fucking hard and require this much goddamn complexity?
I just gave up. Understood: React just ain't it, man.
3. The Reframe: Turns Out I Was Half Right
My gut reaction at the time was blunt: React just isn't it for this. Turns out I was half right.
I checked how the actual Monkeytype is built. Monkeytype uses no framework at all: plain vanilla TypeScript, direct DOM manipulation, no Virtual DOM, no state reconciliation.
The caret coordinate math is inherent to any real-time positioned-cursor UI: that part was never React's fault. But wrapping high-frequency keydown events (10+ per second) inside React's rendering model (useState, useRef, referential equality, component re-renders) piled a whole extra layer of state-management hell on top of an already hard problem.
The real takeaway: match your stack to the problem, not the other way around. Don't take on a rendering-engine-grade problem and a new framework's mental model at the exact same time.
4. What's Next
The idea itself was solid, and I actually pulled it off with AI's help. It's the optimization layer, the React re-render chasing, the state-management spiral, where I hit the wall.
Despite that, Typedesk is finished, responsive, and deployed:
๐ Live Demo: https://shoytanbaba99.github.io/typedesk/
๐ฆ Typedesk GitHub Repo: https://github.com/Shoytanbaba99/typedesk
๐ Monkeytype Source Code: https://github.com/monkeytypegame/monkeytype
Next up: something more bearable. Got a college assignment, asked a friend for ideas, and he said: "just build a complaint management system, just pass, man." Fair enough.
That's the next target, back to CRUD, forms, and state transitions, where I can actually hold the whole thing in my head, and hopefully learn something new instead of just surviving it. Cheers for now.

Top comments (0)