Flex Engineers
5 min read

How We Help Engineers Rebuild Their JavaScript Fundamentals, One Module at a Time

JavaScriptWeb SecuritySoftware DevelopmentTechnical MentoringCode Review

Why we invest in fundamentals, not just frameworks

Most of the work at Flex Engineers is building and shipping full products — TrackPulse, MediaKing, InfoSysCS, ApexDv and the rest all involve React/Next.js, APIs, and production infrastructure. It's easy, at that altitude, for an engineer to lean on framework conventions without ever re-examining the JavaScript underneath them. So as part of our internal growth track, we set aside dedicated time for engineers to work through a structured JavaScript curriculum end to end — no framework, no build tool doing the thinking for them — and to commit every module to git as they finish it, so a mentor can review the progression, not just the final result.

One of our engineers ran the full track this way. The repo isn't a product. It's 30-plus numbered modules, each a small, runnable exercise, tracked with commits like Day 1 Module 1, Day 3 Module 8, Day 6 Module 28 — a paper trail of exactly what was covered and when, reviewable by a lead the same way we review a client PR. The commit dates show the full pass happened over about three weeks, and the engineer later did a second, lighter pass (02. Javascript) revisiting the early modules — DOM, control flow, ES6 — as a refresher rather than first-time learning.

What the curriculum actually covers

The module list reads like a map of the JavaScript features that separate "can write React components" from "understands the language React is built on" — exactly the gap our senior engineers look for when pairing a newer hire onto client work:

RangeTopicWhy it matters in practice
02–04Basics, debugging, control structuresBaseline, but debugging tooling (breakpoints, call stack reading) pays off constantly
09–11Objects, OOP, constructor functions & prototypesExplains why class in JS behaves differently from class in Java/C#
15, 26Advanced functions, metaprogramming (Symbol, Proxy, Reflect)Rarely needed day-to-day, but essential for understanding how libraries like Vue's reactivity or ORMs intercept property access
17–18Async, Promises, callbacks, HTTPThe actual mental model behind every await fetch(...) in our codebases
22, 28Browser storage, securityWhere naive DOM code turns into an XSS vector
27, 29–31Node.js, deploying, performance, testingThe parts that don't show up in tutorials but show up in production

A concrete example: the same app, done unsafely and then safely

Modules 24 and 28 (Share_My_Place and Security) are the same small geolocation-sharing app, built twice. The first pass renders a place name straight from the URL query string into the page title:

// 24. Share_My_Place/src/MyPlace.js
const headerTitleEl = document.querySelector('header h1');
headerTitleEl.textContent = address;

textContent happens to be safe here — but the Security module rebuilds the same feature using innerHTML, the way a less careful implementation (or one that needs to render formatted HTML, not just text) might:

// 28. Security/src/MyPlace.js
import sanitizeHtml from 'sanitize-html';

const headerTitleEl = document.querySelector('header h1');
headerTitleEl.innerHTML = sanitizeHtml(address);

The point of rebuilding it isn't to prove innerHTML is bad in the abstract — it's to internalize the specific moment where user-controlled input (a query parameter, in this case) crosses into the DOM, and to make sanitization a reflex rather than a code-review afterthought. That's the outcome we care about as a studio: an engineer who has personally rebuilt the vulnerable version once catches XSS-shaped code in review months later without needing to look it up, which is exactly what happened the next time this engineer reviewed a teammate's PR touching user-supplied HTML.

Metaprogramming: understanding the tools before reaching for a library

Module 26 walks through Symbol, Reflect, and Proxy directly, without a library wrapping them:

const courseHandler = {
  get(obj, propertyName) {
    if (propertyName === 'length') return 0;
    return obj[propertyName] || 'NOT FOUND';
  },
  set(obj, propertyName, newValue) {
    if (propertyName === 'rating') return; // silently reject writes
    obj[propertyName] = newValue;
  }
};

const pCourse = new Proxy(course, courseHandler);
pCourse.rating = 5; // no-op, blocked by the trap

This is the exact mechanism behind Vue 3's reactivity system and behind ORMs that intercept property access to lazily load relations. Having built a get/set trap by hand makes reading (and debugging) that kind of library code dramatically faster for our engineers, because "magic" behavior stops being magic — it's a Proxy handler they can mentally trace, which shortens the ramp-up time whenever a client project leans on a library with this kind of implicit behavior.

Why we run this as a company program, not a personal side project

We don't present this repo as a product, and we're not claiming to have invented these exercises — the curriculum follows Maximilian Schwarzmüller's JavaScript – The Complete Guide. What we think is worth investing company time in is:

  • Deliberate identification of gaps. Rather than assuming framework fluency implies language fluency, we have engineers go and check, module by module, with a mentor reviewing the commits.
  • A traceable process. Every module is its own commit, so a lead can see the progression is auditable rather than asserted, the same way we'd review a client-facing feature branch.
  • Security as a first-class module, not an afterthought. Rebuilding the same feature vulnerable-then-fixed is a more durable way to internalize XSS mitigation than reading about it once — and it shows up directly in how carefully that engineer now handles user input on client projects.
  • Depth on primitives that most tutorials skip — Proxy, Reflect, generators, prototype chains — which are exactly the primitives that explain how the frameworks our teams use in client work actually behave under the hood.

Takeaway

Shipping products teaches an engineer how to compose tools. Working through a language curriculum like this, commit by commit, with a mentor watching the progression, is how we keep the layer underneath those tools from turning into a black box for the people on our team — which is what lets an engineer debug the framework, not just the app built on top of it, the next time something breaks in a client's codebase. That's a direct return on the time we invest in structured learning, not a nice-to-have.