Concepts — Capstone: From Component to Pixel

Phase 7 · Spec areas §46 (complexity notebook), §47 (comparison matrix), §48 (design challenges), §50 (capstone), §51 (mastery criteria).


0. Orientation

The 60-second version

The capstone asks one question — what happens between a line of component code and a lit pixel? — and it is chosen because no single module can answer it. Answering it requires every layer, and the ability to say where one ends and the next begins.

By this point the tracks have been converging on a small number of ideas that keep reappearing in different languages and at different scales. Recognising them is what the track was for; §2.5 enumerates them. The short version:

PatternWhere you met it
The author promises what the runtime cannot derivekey, {passive:true}, contain, sideEffects, aria-setsize
Immutability is the enabling condition for cachingRedux state, layout fragments, display items, computed
An incomplete cache key produces stale output with no errorlayout cache, paint invalidation, bundler hash, query key
Precompute an index at parse time so the hot path does lessRuleFeatureSet, patch flags, module graph
Interruptibility means turning stack state into heap stateFiber, generators, incremental GC, tile raster
Any system that re-runs code must define "undo the previous run"effect cleanup, hot.dispose, teardown
Separate what changes often from what changes rarelyproperty trees, containment, chunking

None of these is a browser fact or a framework fact. They are design moves, and the point of running both tracks is that seeing the same move in C++ and in JavaScript is what promotes it from trivia to technique.

What the capstone is actually testing

Not recall. Whether you can take an unfamiliar cross-layer question, decompose it, say which layer owns each part, name what you would measure, and be explicit about where your knowledge stops. That last part is not a weakness in the answer — it is the answer.

What you should be able to do after this module

CapabilityEvidence you have it
Answer a full-stack questionDecompose it by layer, with no hand-waved boundaries
Name the recurring patternsIdentify a design move you have not seen before as an instance of one
Compare architecturesFill the §47 matrix from your own implementations, on axes that are not speed
State your limitsSay precisely where your model ends, rather than smoothing over it

1. The deliverable

Build a real application using your own implementations:

your JSX/template compiler (fw-06)
   -> your component runtime (fw-02/fw-04)
   -> your reactive store (fw-01 or fw-03)
   -> your router (fw-08) + query cache (fw-09)
   -> DOM
   -> Blink -> style -> layout -> paint -> compositor -> GPU -> pixels

Instrument every layer you can observe. Then answer, in full, what happens after:

setCount(count + 1)

covering framework scheduling, state update, reconciliation or reactive effect, DOM operations, Blink invalidation, style, layout if required, paint if required, compositing if required, and frame presentation — and which stages are skipped, and why.

The application should be small and real: a list with filtering, a detail route with async data, and one animation. That is enough surface to exercise every layer and small enough to instrument honestly.


2. The three analytical artefacts

2.1 Complexity notebook (§46)

One entry per confrontation with production complexity, using the template in PROGRESS.md. Required: Fiber · Vue scheduler · HTML parser insertion modes · layout fragmentation · Mojo / multiprocess IPC · browser security boundaries · concurrent rendering · hydration · event delegation · property trees · style invalidation sets.

Each entry must classify the complexity as essential architecture, production hardening, or accretion — and defend the classification with evidence. Guessing is not classification.

2.2 Comparison matrix (§47)

Rows: mini-react · React · mini-vue · Vue · signals · Redux · Blink style invalidation. Columns: change detection · scheduling · memory · consistency · debuggability · incremental work · failure modes · extensibility · compile-time knowledge · runtime knowledge.

Never reduce to "which is faster."

2.3 Design challenges (§48)

For each: constraints, invariants, failure modes.

A. A UI framework with no virtual DOM · B. Dependency analysis at compile time · C. Canvas instead of DOM · D. Asynchronous rendering · E. SSR + hydration · F. Partial hydration · G. Offline-first state


2.5 The patterns this track keeps finding

By the capstone you should be able to name these unprompted. Each appears in both strands, which is the evidence that they are properties of the problem rather than of any one codebase.

1. Author-supplied guarantees unlock impossible optimisations

GuaranteeUnlocks
key (fw-02)identity-based reconciliation
{passive: true} (bi-10)compositor scrolling without consulting the main thread
contain / content-visibility (bi-07)skipping style, layout, paint for a subtree
sideEffects: false (fw-07)tree shaking
aria-setsize (fw-10)correct AT semantics for virtualized content
Origin-Agent-Cluster (bi-02)origin-keyed process isolation

The runtime cannot derive these facts. Rather than staying conservative forever, the platform adds a way for the author to promise. When you build something that must be conservative, ask what the smallest promise would be.

2. Record cheaply, resolve precisely, once per frame

Style invalidation (bi-07), dirty layout (bi-08), paint invalidation (bi-09), reactive scheduling (fw-03), React batching (fw-04). Every one separates marking from computing.

This is what makes a system incremental, and it is why interleaving a read into a write loop is catastrophic rather than merely slow: the read forces resolution, destroying the batching the whole architecture was built around.

3. Immutability is the enabling condition for caching

Layout results (bi-08), display items and fragments (bi-09), Redux state (fw-01), Fiber's double buffer (fw-04). If a value can change under you, "is this still valid?" is unanswerable.

4. A cache key must capture every input — and incomplete keys fail silently

Constraint spaces (bi-08), paint subsequences (bi-09), computed (fw-03), bundler content hashes (fw-07), query keys (fw-09). The failure is always the same: stale output, no error.

5. Author code must never observe a half-built state

Parser construction site (bi-03), custom element reactions and MutationObserver (bi-04), commit atomicity (fw-04). All three queue or batch for this reason, and all three chose it over a simpler synchronous design that was impossible to make safe.

6. Speculation is safe only when it cannot be observed

Preload and background scanners (bi-03), compositor scrolling before the main thread answers (bi-10), discardable render work (fw-04). Wrong is acceptable; observable is not.

7. Restrictions make circular systems analysable

Container queries require containment (bi-07); percentage heights against auto resolve to auto (bi-08); ResizeObserver has a depth limit (bi-11). Each time, the specification adds a restriction rather than an iteration limit — because restrictions keep the system analysable while limits merely keep it terminating.

8. Some complexity exists because of who owns what

Two GCs, because V8 and Blink are separate projects (bi-04). Two Mojo type namespaces, because Blink uses WTF types and the browser uses STL (bi-06). Generated bindings, partly because consistency across thousands of interfaces cannot rely on humans (bi-05).

Organisational boundaries become architectural boundaries. This is the most Principal-level observation in the track, and the one most worth carrying into your own org design.


2.6 The capstone question, decomposed

"Explain what happens after setCount(count + 1)" is really eight questions. A complete answer addresses each:

  1. Which framework work is scheduled, at what priority, and is it batched? (fw-04)
  2. Which components re-render, and why those? (fw-02 / fw-05 — and the answer differs by architecture, which is the point)
  3. Which DOM operations result? Count them. (fw-02's instrumented DOM)
  4. What does that mutation invalidate? Which elements, which stages — cite css_properties.json5 (bi-07)
  5. Does layout run? For which boxes, and does anything force it early? (bi-08)
  6. Does paint re-record, or is this a property-tree change? (bi-09)
  7. Which thread and process does each step run on, and where are the hops? (bi-02, bi-10)
  8. When is the frame presented, and what could have made it late? (bi-10, bi-11)

And then the question that demonstrates mastery rather than recall:

Construct two variants of the same visible change — one that reaches the GPU having skipped style, layout and paint entirely, and one that runs every stage. Explain the difference at each of the eight layers.

If you can do that from your own instrumented application, with measurements, you have completed the track's actual objective. Everything else is instrumental to it.

3. Mastery criteria (§51)

The track is complete when you can independently:

  • Draw Chromium's processes and explain the trust boundaries
  • Given a browser behaviour, locate the likely subsystem and its implementation
  • Explain HTML → DOM → style → layout → paint → compositing in implementation terms
  • Determine whether a change triggers style, layout, paint, or compositor work
  • Trace a Web API from JS through the bindings
  • Set native breakpoints and follow meaningful execution
  • Locate, run, and modify browser-engine tests
  • Connect implementation behaviour to specifications
  • Produce at least one upstream-quality Chromium/Blink change
  • Have working simplified implementations of: React-like runtime, Vue-like reactive/runtime/compiler system, Redux-like store, router, query cache, signals, virtualized list, bundler/compiler
  • Explain not only how these systems work, but why their complexity exists

The last criterion is the actual target. Everything else is instrumental to it.


Core terminology

TermDefinition
Complexity notebook (§46)Per-mechanism entries classifying complexity as essential, hardening, or accretion
Comparison matrix (§47)Architectures scored on axes that are deliberately not speed
Design challenge (§48)An open-ended problem exercised against your own implementations
Vertical traceOne behaviour followed through every layer it touches (bi-15)
Layer-skipping tableThe honest record of which layers you could not explain
Essential / hardening / accretionThe classification from fw-11, applied across both tracks
Author assertionAn optimisation unlocked by a promise the runtime cannot derive
Change detectionThe problem Redux, React, Vue, signals and Blink invalidation all solve differently

Mental models

A pattern seen once is trivia; seen in two languages at two scales, it is technique. The reason both tracks exist is that Blink's style invalidation and Vue's reactivity solve the same abstract problem, and holding both is what lets you recognise the problem in a system you have never seen.

"Where does my model stop?" is a stronger answer than a confident guess. Every senior engineer can produce a plausible full-stack story. The distinguishing capability is knowing which parts of yours are load-bearing and which are narrative — and being willing to say so.

Never reduce a comparison to "which is faster." The §47 axes — change detection, scheduling, memory, consistency, debuggability, incremental work, failure modes, extensibility, compile-time and runtime knowledge — exist because speed is the least decision-relevant of them at organisational scale. fw-05's conclusion is the template: the real question was where performance work lands, not which benchmark won.

Classify complexity, and defend the classification with evidence. Essential architecture, from which a capability follows. Hardening, which is a fast path or guard. Accretion, which has a CL and a date. Most engineers see only the first, and the ability to identify the third is what lets you argue for removing complexity in systems you own.

The capstone question is a template, not a trivia item. "What happens between X and the thing the user perceives?" is the shape of most Principal-level diagnostic questions. Practise the decomposition, not the specific answer.


Common misconceptions

  1. "The capstone tests recall." It tests decomposition, layer ownership, and honesty about limits.

  2. "Admitting a gap weakens the answer." A precisely located gap is stronger than a smooth guess, and far more useful to the people relying on you.

  3. "The patterns are analogies." They are the same design move under different constraints. That is why they transfer to systems neither track covered.

  4. "The comparison matrix should conclude with a winner." It should conclude with the axis that decides for a given product and organisation.

  5. "Complexity in production code is justified." Some of it is accretion, and identifying it with evidence is a distinct and valuable skill.

  6. "Once I finish, I know the stack." You know where your model is solid and where it is thin, which is the durable thing — the specifics will move.


Interview talking points

  • "The question I use to test my own understanding is what happens between a line of component code and a lit pixel, because no single layer can answer it. And the useful part of my answer is knowing precisely where my model stops rather than producing a smooth story that's partly narrative."
  • "Running a browser-internals track and a framework track together was worth it because the same design moves show up in both. Blink's style invalidation and Vue's reactivity solve the same abstract problem — seeing it in C++ and in JavaScript is what turns it from trivia into something I can apply to a system I've never seen."
  • "The one I use most is the author-assertion pattern: the runtime can't derive a fact it needs, so the platform lets the author promise it. List keys, {passive: true}, contain, sideEffects, aria-setsize. When I design a tool that has to be conservative, I ask what the smallest promise a caller could make would be, rather than how to analyse harder."
  • "I never let an architecture comparison reduce to which is faster. The axis that actually decided our framework question was where performance work lands — on every engineer, or absorbed by the framework — and at 200 engineers that dominates any benchmark."
  • "I classify complexity as essential architecture, production hardening, or accretion, and I want evidence for the third — a CL, an issue, a test that exists because of a specific bug. Most people see only the first, and being able to identify accretion is what lets you argue for removing complexity rather than only adding it."

4. Final review

  1. Explain setCount(count + 1) end to end, in ten minutes, to a strong engineer who has never thought below the framework. Then do it again in ninety seconds.

  2. Of everything you built, which mini-implementation taught you the most per hour? Which was least worth the time? What does that say about how to teach this to someone else?

  3. Name three pieces of production complexity you now believe are not essential. Defend each with evidence, and say what you would do instead.

  4. You are given a rendering performance problem in a codebase you have never seen, and two hours. Write the procedure.

  5. What is the most important thing you now know that you cannot easily convince another engineer of without them doing this work themselves?


Connections to other modules

  • bi-15 — the capstone is a vertical trace with the whole stack in scope, and its layer-skipping table is the input.
  • fw-11 — the classification method the complexity notebook depends on.
  • fw-05 — the §47 matrix's template: compare on axes that are not speed.
  • fw-03 — the change-detection comparison that Blink's invalidation belongs in as a row.
  • fe-01–fe-06 — the measured, application-side counterparts to every pipeline stage traced here.