Why Not Fabric.js or Konva?

"Just use Fabric.js."

We heard this a lot. And for most canvas apps, it's good advice. Fabric.js and Konva handle object management, selection, transforms, serialization. Months of work, free.

So why build from scratch?

What These Libraries Do Well

Object model. Shapes are objects with properties:

const rect = new fabric.Rect({
  left: 100,
  top: 100,
  fill: 'red',
  width: 50,
  height: 50
});
canvas.add(rect);

Selection and transforms. Built-in selection boxes, rotation handles, scaling. All the interaction work we'd have to build.

Events. Click, drag, hover—all wired up.

Serialization. canvas.toJSON() and back. Persistence solved.

For most apps, this is 80% of the work done for you.

The Vector Network Problem

Figma introduced vector networks. A vertex can connect to any number of segments. Lines branch, merge, form complex topologies.

     ●
    /|\
   / | \
  ●──●──●
  |  |  |
  ●──●──●

Fabric.js has fabric.Path. One stroke, one fill. No branching.

// Fabric can do this:
new fabric.Path('M 0 0 L 100 100 L 200 0');

// But not this: one vertex connected to 3 segments
// Paths are sequences, not networks

This isn't a bug. Fabric.js models SVG paths correctly. But SVG paths are linear sequences, not graphs.

Per-Segment Styling

In Figma, each segment can have different:

●────●╌╌╌╌●━━━━●
(solid)  (dashed) (thick)

Fabric.js applies stroke properties to the entire path. You can't dash one segment and solid another.

Workaround: Split into multiple paths. Now they're not connected. Move one vertex, the others don't follow.

Custom Render Pipeline

These libraries use Canvas2D internally. All the Canvas2D limitations apply.

Need Linear Burn blend mode? Not happening. Need efficient GPU caching? Not without rewriting the renderer. Need custom shader effects? Go build it yourself.

They abstract Canvas2D. They don't transcend it.

Performance at Scale

Fabric.js stores objects as JavaScript objects. Renders with Canvas2D. For hundreds of objects, fine.

Design tools have thousands of objects. Nested groups. Effects stacked on effects.

// Every frame
canvas.renderAll();  // Loops through all objects
                     // Calculates transforms
                     // Redraws everything

No spatial indexing. No GPU texture caching. No retained mode.

Konva improves on this with layers and caching, but it's still JavaScript loops calling Canvas2D.

Feature Gaps

What Figma has that these libraries don't:

Feature Fabric.js Konva Figma
Vector networks
Per-segment styling
All blend modes
GPU acceleration Partial
Layer effects Basic Basic
Boolean operations
Constraints
Component system

This isn't criticism. These libraries solve different problems. They're not trying to be Figma.

When Fabric.js/Konva Make Sense

Image editors. Filter photos, add text overlays, crop and resize. Perfect fit.

Diagram tools. Flowcharts, organizational charts. Shapes with connectors.

Whiteboards. Freeform drawing, sticky notes, simple shapes.

Presentation builders. Slides with text, images, basic shapes.

Annotation tools. Mark up images or documents.

For these, building from scratch is wasted effort.

When to Build Custom

Vector editing. The core data model (vector networks) isn't supported.

Professional rendering. Need blend modes and effects Canvas2D can't provide.

Performance critical. Thousands of objects, 60fps, complex scenes.

Novel interaction patterns. If you're inventing new ways to manipulate graphics, libraries constrain you.

The Real Answer

Use them for prototyping. Seriously.

We prototyped in Fabric.js. Learned what worked, what didn't. Understood the object model, the transform math, the event handling.

Then we rebuilt with:

The prototype taught us what to build. The custom implementation delivered what Fabric.js couldn't.

Summary

Fabric.js and Konva are excellent libraries. For their use cases.

Figma-level vector editing isn't their use case.

The gaps:

If you need these, no library saves you. You build it.

Next: Why Not SVG? →