Fabric.js and Next.js: Building a Canvas-Based AI Image Studio
Clay Imaginary is a drag-and-drop AI image studio where creators generate, composite, edit and export visuals in one place, and it is now live as HookFeed. This is how the Fabric.js canvas engine, the layers and the AI generation pipeline fit together.
By Wasif Rehman · · 3D & web graphics
In short
- Use Fabric.js rather than raw canvas for an editor: selection, transforms, grouping and serialization come built in.
- Proxy AI generation through a server-side route so API keys stay off the client and providers can be swapped.
- Templates beat a blank canvas, and a showcase gallery can double as the landing page.
- Edit at social-post resolution and upscale on export to keep interactions smooth.
- Build the undo/redo history stack early, because bolting it on later is painful.
Why creators want an AI image studio, not another prompt box
Creators do not want another text-to-image tool. They want a studio: one workspace where they can generate, composite, edit and export polished visuals without bouncing between Photoshop, Figma and five AI tabs.
Clay Imaginary is that studio. I built it with the AIDEVGEN team using Next.js 15, React 19 and Fabric.js. Clay Imaginary was the working name: the product is now live as HookFeed, and the case study covers what it became.
| Part | Tool |
|---|---|
| App | Next.js 15 and React 19 |
| Canvas engine | Fabric.js |
| Layer reordering | react-draggable |
| AI generation | A server-side API route that proxies to the image model |
| Export | html2canvas |
| Sign-in | Google OAuth through @react-oauth/google |
| Saved projects | Fabric JSON from canvas.toJSON(), stored per user |
Fabric.js vs the raw Canvas API for an image editor
Raw <canvas> is great for drawing and terrible for editing. With it, you would have to build the editing basics from scratch.
| Editing feature | Raw canvas | Fabric.js |
|---|---|---|
| Selection | Build it yourself | Built in |
| Transformation (move, rotate, scale) | Build it yourself | Built in |
| Grouping | Build it yourself | Built in |
| Serialization | Build it yourself | Built in (canvas.toJSON()) |
| Undo and redo | Build it yourself | Still yours to build, but the event model makes it possible |
In Fabric.js, objects are first-class. Each one has a position, rotation, scale and event handlers. That meant we could focus on the creative features, such as AI generation, templates and exports, instead of reinventing a scene graph.
Building a Figma-style layers panel with Fabric.js
Every element on the canvas is a Fabric object with a layerId: an AI-generated image, a text headline, a shape or an uploaded asset.
- Drag in the layer panel A side panel renders the layer stack, and react-draggable lets users reorder it with a drag.
- Update the z-index Reordering updates Fabric's internal z-index.
- Re-render and sync The canvas re-renders, and a shared state store keeps the layer panel in sync.
It feels like Figma. It is a few hundred lines of code.
Adding AI image generation to a canvas editor
The user types a prompt, picks a style preset and hits generate. The request goes to a server-side API route that proxies to the image model.
- Prompt and style preset
- Server-side API route
- Image model
- Image URL returned
- Fabric image on the canvas
The returned image URL is loaded into a Fabric image object and dropped onto the canvas at the last click position, ready to be moved, scaled or composited with other layers.
Solving the blank canvas problem with templates
Cold start is the enemy of creative tools. A blank canvas intimidates users, so Clay Imaginary shipped with a showcase gallery of templates, including:
- Product mockups
- Recipe cards
- Finance infographics
- Meme formats
- Quote cards
- AI tech news layouts
- Gym posts
Each template is a pre-populated Fabric scene the user can remix. This is also how the product sells itself: the showcase page doubles as a landing page and a starting point.
Exporting with html2canvas and keeping Fabric.js fast
Fabric has its own toDataURL method, but we use html2canvas for the final export. The studio overlays HTML UI on top of the canvas: annotations, watermarks for free users and branding frames. html2canvas captures the composed DOM and canvas region as a single PNG, which is what users actually want to post to Instagram or LinkedIn.
Fabric handles editing; html2canvas handles shipping.
For performance, the naive approach is to render at full 4K resolution while editing. Do not. We edit at a lower working resolution and upscale on export:
| Format | Working resolution |
|---|---|
| Square | 1024×1024 |
| Portrait social post | 1080×1350 |
This keeps drag, rotate and scale interactions smooth, even on mid-range laptops.
Saving Fabric.js projects with toJSON, and why undo comes first
Google OAuth through @react-oauth/google handles sign-in. Projects serialise as Fabric JSON through canvas.toJSON() and live in a backend store keyed by user ID.
Deserialising a project restores every layer with its exact state: position, rotation, opacity and filters. That makes sharing simple. A URL plus a JSON blob is a fully editable remix.
For another browser-based editor, with time-travel undo on a Zustand store, see Designing a Real House in the Browser.
Frequently asked questions
Why use Fabric.js instead of the raw Canvas API?
Raw canvas is good for drawing but poor for editing. Fabric.js gives you first-class objects with position, rotation, scale and event handlers, plus selection, transformation, grouping and serialization, so you can focus on product features instead of building a scene graph.
Does Fabric.js have undo and redo built in?
Not for free. Fabric's event model makes it possible, but you need to snapshot state on every mutation. Build the history stack early rather than bolting it on later.
How do you export a Fabric.js canvas with HTML overlays?
Clay Imaginary uses html2canvas instead of Fabric's own toDataURL, because annotations, free-user watermarks and branding frames are HTML overlays. html2canvas captures the composed DOM and canvas region as one PNG.
How do you keep a Fabric.js editor fast?
Edit at a lower working resolution, usually 1024×1024 or 1080×1350 for social ratios, and upscale on export. For very large compositions, set renderOnAddRemove: false and batch updates manually.
Is Clay Imaginary the same product as HookFeed?
Yes. Clay Imaginary was the working name while we built it. The product is now live as HookFeed at hookfeed.ai.
Case study: HookFeed