figma

Building a professional design tool on the web | Figma Blog (opens in new tab)

Figma set out to prove that a professional, high-fidelity design tool could run reliably in the browser. The challenge was that the web exposed specialized features rather than general-purpose graphics primitives, so Figma effectively had to build “a browser inside a browser.” Its solution combined C++ compiled through Emscripten with a custom rendering engine, enabling tighter control over memory, performance, and cross-platform consistency.

Building Beyond the Web’s Original Design

  • The web was originally designed for documents, with application features added later as isolated APIs.
  • This limits advanced applications:
    • CSS provides sophisticated text layout but does not expose or customize the layout process.
    • Browsers have optimized GPU compositors, but developers cannot directly modify compositing or add custom blend modes.
    • Image decoders are highly optimized but offer limited control over details such as EXIF orientation and color-space handling.
  • Technologies such as WebGL and asm.js began exposing lower-level access to hardware, making demanding browser-based graphics applications practical.

C++ and Emscripten

  • Figma’s editor was written in C++ and cross-compiled to JavaScript using Emscripten.
  • Emscripten targeted asm.js, allowing JavaScript engines to generate predictable and compact machine code.
  • This approach provided:
    • Direct control over memory layout, including compact 32-bit floats and bytes instead of JavaScript’s 64-bit numbers.
    • Manual allocation that avoids garbage-collection pauses and helps maintain 60 fps.
    • LLVM optimization and C++ template specialization for performance approaching native code.
    • More predictable execution because asm.js avoids the deoptimization points common in regular JavaScript.

Memory Constraints and Indirect Buffers

  • Large contiguous typed-array allocations caused problems, especially in 32-bit Chrome on Windows, where address-space fragmentation from ASLR could prevent allocations as small as 256 MB.
  • Figma created an IndirectBuffer API to reference external typed arrays from C++.
  • Moving large image and geometry buffers outside the main heap:
    • Reduced fragmentation during long sessions.
    • Allowed better use of limited 32-bit address space.
    • Helped bypass typed-array size limits in 64-bit browsers.
  • The post also points toward future improvements from WebAssembly, which would reduce asm.js parsing costs, and shared typed arrays, which would enable shared-memory multithreading.

Custom Rendering

  • Figma implemented its own rendering engine to achieve fast, consistent output across platforms.
  • Rather than relying entirely on browser graphics implementations, the team began building the rendering layer needed for a professional design application.

Figma’s broader recommendation is to use low-level browser capabilities such as WebGL and compiled code when standard web APIs cannot provide the required performance or control.