Why we built this learning environment
When I first picked up JavaScript in 2015, the only practice resource that did not feel like a textbook was W3Schools. The examples worked, but the moment I broke one I had nowhere to land. I wanted a place where I could break code, watch it explode, and then read why it exploded — without spinning up a Node project on my laptop.
That is the only reason this site exists. We built it for the version of us that was twenty minutes into a topic, hit a wall, and could not tell whether we misunderstood closures or just typed a stray semicolon. Every problem is meant to be opened, attempted in the editor, and either solved or failed in under five minutes. If a problem takes longer than that, we usually consider that a problem-design bug and rewrite the prompt.
We are not trying to be Codewars. We are not trying to be LeetCode. Both are excellent at what they do — competitive grinding and interview prep. We are trying to be the place a self-taught developer goes between tutorials, when they want to actually feel a concept stick before moving on.
What makes our problems different
Each problem we publish goes through hand-tested edge cases — on average eight per problem, sometimes twelve for the harder algorithm sets. We test empty inputs, single-element inputs, large inputs (we cap at 100,000 elements for medium problems and 1,000,000 for hard), negative numbers, floating-point drift, Unicode strings with surrogate pairs, and at least one input that triggers stack overflow if you wrote a naive recursion.
We also do not accept AI-generated explanations. Every solution walkthrough is written by a developer who has actually shipped JavaScript to production. That sounds like a small distinction, but it changes the writing. AI explanations average around 240 words and tend to repeat the question back at you. Our walkthroughs average 410 words and explain the wrong answer first, because the wrong answer is the one you wrote.
We measure problem quality by the ratio of attempts to solves. If a problem has more than ten attempts per solve and the average attempt time is under sixty seconds, that means people are guessing — the prompt is unclear. We rewrite anything in that bucket within a week.
Tools we use behind the scenes
The editor is Monaco, the same editor that powers VS Code. We chose it after benchmarking against CodeMirror 6 and Ace. CodeMirror was 38 KB lighter on initial load, but Monaco gave us multi-cursor editing, the same keybindings VS Code users already have, and JavaScript IntelliSense that actually understands ES2026. For a learning site, the muscle-memory match matters more than the kilobytes.
Code execution happens inside a Web Worker, isolated from the main page. We use a sandboxed `new Function()` constructor with a timeout (currently 4 seconds for normal problems, 10 seconds for benchmark problems) and a memory ceiling enforced through periodic checks. We do not send your code to a server. The closest thing to a server-side execution is when you click 'Save' on a problem, which writes the source to your localStorage, not ours.
On a 2024 M2 MacBook Pro, the playground starts a fresh execution context in around 38 microseconds, averaged over a thousand runs. On a five-year-old Windows laptop with Chrome 130, the same number is 142 microseconds. Both are fast enough that the round-trip from clicking Run to seeing output feels instant — that was the bar we set, and we missed it twice before getting there.
What's actually changed in 2026
ES2026 finally landed the Pipeline operator at Stage 4, which means `value |> fn1 |> fn2` is no longer a Babel-only luxury. We rewrote 12 of our intermediate problems last month to either use it as the canonical solution or accept it as an alternative. We left the classic functional composition examples in place — both styles are now correct.
The Temporal API is also finally Stage 4. If you took a date-handling problem here a year ago, you saw `new Date()` and `getTime()` everywhere. We have now migrated those problems to use `Temporal.PlainDate` and `Temporal.Instant` where the semantics actually matter. The Date object remains in the legacy track, because real codebases will keep using it for at least another five years.
Records and Tuples slipped to Stage 3 again, so we still teach `Object.freeze` and structural cloning as the practical answer for immutable data. We will revisit when the spec stabilizes — until then, deep equality with frozen objects is what production code actually does.
Things we do not do
We do not run a discussion forum. There are good ones already (Stack Overflow, dev.to, the JavaScript subreddit). Building a moderation pipeline for one more is not where we want to spend our time, so we link out instead.
We do not have a paid tier. The site is supported entirely by Google AdSense and a tiny amount of affiliate revenue when someone clicks through to a book recommendation. If ads ever become annoying enough that they hurt the learning flow, we will move them, not add them.
We do not track which problems you got wrong on the server. Your progress lives in your browser's localStorage. If you clear your storage, your streak is gone. We considered adding accounts. We measured how much that would cost in maintenance time. We decided your privacy was more valuable than our retention dashboards.