F.1 How Browsers Execute Code
Trace the six-stage browser rendering pipeline — from HTML parsing and CSSOM construction through layout, paint, and compositing — and understand the JavaScript event loop well enough to diagnose why Make previews jank, flash, or block the main thread.
> When a user clicks "Preview" in Figma Make and a working app appears in 2 seconds, what happened between their click and the pixels on screen? List every step you can think of. ---
Those two seconds contain one of the most complex pipelines in software. Understanding it is not optional for a Platform PM — every performance complaint, every "why is preview slow," every decision about server-rendered versus client-rendered output traces back to this pipeline.
The Browser Execution Pipeline
When the browser receives HTML (from a server, a blob URL, or an injected string), it runs through six sequential stages:
1. HTML Parsing → DOM Construction
The browser reads HTML as a byte stream and tokenizes it — <div class="app"> becomes an open-tag token with an attribute. These tokens are assembled into nodes, and nodes are assembled into a tree: the Document Object Model (DOM — a live, programmatic tree of every element on the page). Scripts and stylesheets block this process — a <script> tag without async or defer halts parsing entirely while the JS downloads and executes.
2. CSSOM Construction In parallel with HTML parsing, the browser parses CSS into its own tree — the CSS Object Model (CSSOM — a parallel tree that maps every CSS rule to the nodes it styles). Every selector rule maps to computed styles for matching nodes. The CSSOM cannot be constructed incrementally the way the DOM can; CSS is "render-blocking" (it halts further rendering until the entire stylesheet is processed) because a later rule can override an earlier one, so the browser must process the entire stylesheet before it knows what anything looks like.
3. Render Tree
The DOM and CSSOM are combined into the Render Tree — a tree that contains only visible nodes with their computed styles. display: none nodes are excluded entirely. visibility: hidden nodes are included (they still take up space). This is the first structure that represents "what will actually appear on screen."
4. Layout (Reflow) The browser traverses the Render Tree and calculates the exact position and size of every element. This is called layout, or reflow. Box model calculations happen here — margins, padding, width, height, flexbox and grid algorithms all resolve in this phase. Layout is expensive, especially for deeply nested trees or when triggered repeatedly by JavaScript.
5. Paint Layout gives coordinates; paint fills in the pixels. The browser determines what to draw in each layer — background colors, borders, text, shadows. Paint produces a series of draw calls, not pixels directly. Complex visual effects (box-shadow, filter, opacity) can make this phase expensive.
6. Composite
Modern browsers separate the page into layers (like Photoshop layers). The compositor thread assembles those layers into the final frame and sends it to the GPU. Animations that only affect transform and opacity can be composited without triggering layout or paint — this is why those properties are preferred for smooth animation.
CSS is described as 'render-blocking.' What does that mean in practice, and why can't the browser just skip incomplete CSS and fill it in later?
JavaScript Execution: V8 and the Event Loop
JavaScript runs inside an engine — in Chrome and Node.js, that engine is V8 (Google's open-source JavaScript runtime). V8 compiles JavaScript to machine code using a JIT (just-in-time) compiler (a technique that compiles code to native machine instructions on-the-fly during execution, rather than ahead of time — making frequently-run code nearly as fast as compiled C). The first execution is interpreted; hot code paths are identified and recompiled to optimized machine code.
JavaScript is single-threaded. There is one call stack. This is not a bug — it eliminates an entire class of race conditions. But it means that any synchronous operation that takes a long time (a large sort, a synchronous HTTP request) blocks everything else, including UI updates. This is why "don't block the main thread" is a core browser performance axiom.
The Event Loop is the mechanism that makes JavaScript feel concurrent without threads:
- Execute whatever is on the call stack
- When the stack is empty, check the microtask queue (Promise callbacks — high-priority async callbacks that run before the browser can do anything else) — drain it completely
- Check the macrotask queue (setTimeout, setInterval, I/O callbacks — lower-priority scheduled work) — run one task
- Repeat
This means Promise chains resolve before timeouts, and a deeply nested Promise chain can still block the UI if it runs long enough.
Why This Matters for Make
Every time a user clicks Preview, this entire pipeline runs on code that an AI just wrote. The AI does not know the user's screen resolution, does not know their browser's rendering quirks, and does not know that a deeply nested flexbox grid will trigger an expensive reflow on every keystroke. Make's preview environment is essentially a bet that the generated code will be performant enough to feel instant.
The practical implications:
- Generated code that synchronously fetches data in the component body will block rendering
- Generated CSS that changes layout properties inside animations will cause jank
- Generated JavaScript that runs a synchronous loop over a large array will freeze the UI
- The preview iframe (a sandboxed page embedded within the main page) must load, parse, and execute all of this while the user watches
The quality bar for "working preview" is actually higher than it looks. The code doesn't just need to be syntactically valid — it needs to clear the entire browser pipeline without producing a broken or slow experience.
Server-Rendered vs. Client-Rendered: Make's Fork in the Road
In client-side rendering (CSR), the server sends a nearly empty HTML file and a JavaScript bundle. The browser downloads the JS, executes it, and the JS builds the DOM. First Contentful Paint is delayed until JS executes. React's standard model is CSR by default.
In server-side rendering (SSR), the server runs the JavaScript and sends completed HTML. The browser paints immediately. Then JavaScript loads and "hydrates" (attaches event listeners to already-rendered server HTML, making it interactive without rebuilding the DOM from scratch) the page. First paint is faster; the complexity of hydration is real.
Make must choose: does a generated app render on the client, the server, or both? This choice affects:
- Where the runtime lives (browser sandbox vs. server container)
- What the deployment target looks like
- How quickly previews appear
- Whether the output is a static file or requires a persistent server process
Most early-stage code-gen tools default to CSR because it's simpler — no server required, output is just static files. But CSR apps have worse SEO and slower initial load. The moment Make wants to support server components, database queries at render time, or meaningful SEO — it needs SSR infrastructure. That infrastructure cost is substantial.
A user reports that their Make preview feels "janky" — elements jump around after the initial load. A bug report says "layout shift." Which phase of the browser pipeline is most likely responsible, and what category of generated code would cause it?
Open Chrome DevTools → Performance tab. Record a 5-second session of a Make preview loading. Identify the four colored sections in the flame chart: blue (HTML parsing/scripting), purple (rendering/layout), green (painting), gray (compositing). Find the longest task. If it exceeds 50ms, it's a "long task" that blocked the main thread. ---
Explain the browser rendering pipeline to a non-technical Figma designer on your team who asked why previews sometimes "flash" before the correct layout appears. Your explanation should take less than 90 seconds. ---
1. Think of a time a product you shipped had a performance problem that traced to generated code, template output, or third-party content. Which phase of the browser pipeline caused it — layout, paint, scripting — and why wasn't it caught before release?
2. When you've worked on preview or prototyping tools — even low-fidelity ones — where did the gap between 'looks right in the tool' and 'behaves correctly in the browser' tend to show up? What does that tell you about where Make's real quality risk lives? ---
Every Make preview is the full browser execution pipeline running on untested AI-generated code — performance problems in generated output are not bugs in the preview system, they are failures of code quality that the platform must either prevent or gracefully surface.
> If Make defaults to generating React — and React has specific behavior in this pipeline — what does that lock-in mean for the runtime environment that has to execute it? That's what F.2 covers. --- ---
Ready to move on? Mark this module as complete.