Ydesign
Ydesign is a JavaScript SDK for building Canva-style online design editors. It's not a finished product — it's a collection of ready-to-use JS modules, component libraries, and a canvas rendering engine that lets developers ship a feature-complete, deeply customizable design editor in a matter of days.
🎯 Typical use cases: e-commerce product customization, social-media design tools, print production, ID-photo editors, poster / banner generators, enterprise VI templates... See showcase for real scenarios.
Why build another editor?
There are already excellent canvas libraries (fabric.js, Konva) and closed-source SaaS options (like Polotno). But rolling your own editor still hurts:
- Low-level libraries only solve "rendering": selection, snapping, rulers, guidelines, undo/redo, layers, grouping, filters, crop, AI eraser — you have to write all of them.
- SaaS is not flexible enough: customizing UI, swapping components, or plugging in private asset / AI services hits walls fast.
- React / Vue integration needs glue: Fabric is imperative, React / Vue are declarative. Keeping canvas state in sync with UI and building reactive layers is a rite of passage every team repeats.
Ydesign's goals:
- ✅ Ship mature canvas business layers (20+ Handlers: filters, crop, guidelines, rulers, history, lock, groups, hotkeys, AI eraser...) — ready to use
- ✅ Keep the architecture clean and layered so every UI piece stays replaceable
- ✅ Use MobX + MST on the data layer so React / Vue feels declarative while wrapping imperative Fabric
- ✅ Publish as a monorepo with separate packages — pick React, Vue, or headless as you need
Three packages form one ecosystem
Ydesign is a pnpm + turborepo monorepo split into three independently published npm packages by responsibility:
┌─────────────────────────────┐
│ @ydesign/core │
│ Canvas rendering core │
│ (pure TS + fabric.js v6) │
└──────────────┬──────────────┘
│
┌─────────────────┴─────────────────┐
│ │
┌───────────▼───────────┐ ┌───────────▼───────────┐
│ @ydesign/react-editor │ │ @ydesign/vue-editor │
│ React UI layer │ │ Vue UI (planned) │
│ React 18 + Antd v6 │ │ Vue 3 + Ant Design V │
└───────────────────────┘ └───────────────────────┘
Each layer is usable on its own; they communicate via the shared @ydesign/core.
@ydesign/core
canvas rendering core
A pure-TypeScript canvas business engine with zero UI dependencies and not a single line of CSS. It wraps a Fabric canvas and exposes 20+ independent Handlers (one per responsibility), orchestrated by a top-level Editor class.
| Domain | Representative handlers |
|---|---|
| Canvas basics | WorkareaHandler / ZoomHandler / RendererHandler / RulerHandler / ResizeHandler |
| Objects & layers | ObjectsHandler / LayerHandler / AlignmentHandler / LockHandler / GuidelinesHandler |
| Interaction | EventHandler / HotkeyHandler / CustomHandler |
| History | HistoryHandler / SceneHandler |
| Images & AI | ImageCropHandler / ImageFiltersHandler / ImageStrokeHandler / InpaintHandler |
Good for canvas-only scenarios (you build your own UI) or for extending with new element types (QR codes, barcodes, custom shapes...).
@ydesign/react-editor
React UI layer (shipped)
Built on React 18 + Ant Design v6 + MobX + mobx-state-tree. This is Ydesign's most mature and recommended UI layer today. Internally it follows the "single-source MST store + observer reactive rendering" pattern, so writing components feels declarative even though Fabric underneath is imperative.
Includes:
<Workspace />canvas area<Toolbar />top toolbar (switches by selection type)<SidePanel />business panels (10 built-in: templates / text / photos / shapes / upload / background / layers / size / ID photo / AI eraser)<ZoomButtons />zoom controlscreateStore/createDesignEditorAppfactory entries
@ydesign/vue-editor
Vue UI layer (planned)
Will be built on Vue 3 + Composition API + Pinia, with feature parity, matching API naming, and identical JSON schema to the React version. Currently in design phase; prioritized after the v1.0 stable release.
Both UI layers share the same @ydesign/core, which means:
- Designs exported from the React version open directly in the Vue version (and vice versa)
- Only one canvas engine to maintain; both UIs evolve in parallel
- Teams pick based on their stack, no lock-in
See the Vue integration page for the roadmap.
Layering principle
One-liner: Canvas business in core, UI on top; UI only reads store, state flows one-way.
┌──────────────────────────────────────────────────────────────┐
│ React / Vue components (your application) │
└──────────────────────────┬───────────────────────────────────┘
│ observer reads / actions write
▼
┌──────────────────────────────────────────────────────────────┐
│ MST store (single source of truth) │
│ width / height / fonts / selectedElementsIds… │
└──────────────────────────┬───────────────────────────────────┘
│ store.editor.xxxHandler.xxx()
▼
┌──────────────────────────────────────────────────────────────┐
│ @ydesign/core · Editor + 20+ Handlers │
└──────────────────────────┬───────────────────────────────────┘
│
▼
fabric.Canvas (fabric.js v6)
What this means in practice:
- 🎨 Want to swap UI for Solid / native Web Components? Rewrite the UI layer — core is 100% reusable
- 🧩 Want to embed your own UI system (Chakra / MUI)? Replace individual panels in
react-editor - 🎯 Need a headless canvas only? Use
@ydesign/coredirectly, bring your own UI
Quick start
🚀 Want to generate a runnable project with a single command? See Getting Started · Scaffolding. The section below covers adding Ydesign to an existing project.
Install
# React project: install the full UI package (recommended)
npm install @ydesign/react-editor
# Canvas only (headless / Vue / Angular projects)
npm install @ydesign/core
# Vue project (planned — stay tuned)
# npm install @ydesign/vue-editor
One-line full editor
import { createDesignEditorApp } from '@ydesign/react-editor';
import '@ydesign/react-editor/style.css';
const { store, root } = createDesignEditorApp({
container: document.getElementById('root')!,
key: 'YOUR_API_KEY',
// Trim to the panels you need
sections: ['templates', 'text', 'photos', 'shapes', 'background', 'layers'],
});
// store is an MST instance
store.setSize({ width: 1200, height: 800 });
Composition (maximum freedom)
When you want custom layout:
import { DesignEditorContainer, SidePanelWrap, WorkspaceWrap, createStore, SidePanel } from '@ydesign/react-editor';
import Workspace from '@ydesign/react-editor/canvas/workspace';
import Toolbar from '@ydesign/react-editor/toolbar';
import ZoomButtons from '@ydesign/react-editor/toolbar/zoom-buttons';
import '@ydesign/react-editor/style.css';
export const App = () => {
const store = createStore({ key: 'YOUR_API_KEY' });
return (
<DesignEditorContainer>
<SidePanelWrap>
<SidePanel store={store} />
</SidePanelWrap>
<WorkspaceWrap>
<Toolbar store={store} />
<Workspace store={store} />
<ZoomButtons store={store} />
</WorkspaceWrap>
</DesignEditorContainer>
);
};
Headless (core only)
import { Editor } from '@ydesign/core';
const editor = new Editor({
id: 'my-canvas',
container: document.getElementById('stage')!,
config: {
size: { width: 1920, height: 1080 },
},
});
// Add a text element
editor.objectsHandler.add({
type: 'text',
text: 'Hello Ydesign',
left: 100,
top: 100,
fill: '#111',
});
// Bind hotkeys
editor.hotkeyHandler.bind({
'ctrl+z,command+z': () => editor.historyHandler.undo(),
'ctrl+shift+z,command+shift+z': () => editor.historyHandler.redo(),
});
Tech stack
@ydesign/core | @ydesign/react-editor | @ydesign/vue-editor | |
|---|---|---|---|
| Canvas | fabric.js v6 | (shares core) | (shares core) |
| Framework | Pure TS, zero deps | React 18 | Vue 3 |
| UI kit | — | Ant Design v6 | Ant Design Vue (planned) |
| State | Internal State | MobX + mobx-state-tree | Pinia (planned) |
| Styling | — | styled-components + Tailwind v4 | planned |
| Icons | — | lucide-react + Antd Icons | planned |
| Language | TypeScript 5 | TypeScript 5 | TypeScript 5 |
| Status | Public preview (0.1.x) | Public preview (0.2.x) | 🚧 Planned |
Toolchain: pnpm workspace + turborepo + tsup + tsc.
Versus similar options
| Dimension | Ydesign | Pure fabric.js | Konva | Polotno |
|---|---|---|---|---|
| Renderer | fabric.js v6 | ✓ | custom | custom (closed) |
| Business layer | ✅ 20+ Handlers | ✗ | ✗ | ✅ |
| Ready-to-use UI | ✅ Antd | ✗ | ✗ | ✅ Blueprint |
| Supported frameworks | React ✅ + Vue 🚧 + headless ✅ | Plain JS | JS + react-konva / vue-konva | React only |
| Reactive data flow | ✅ MobX + MST | ✗ | ✗ | ✅ MST |
| Core / UI split | ✅ 3 packages | — | — | ❌ (single bundle) |
| Open source | ✅ | ✅ | ✅ | ❌ (licensed) |
| TypeScript | ✅ end-to-end | ⚠️ partial types | ✅ | ✅ |
Next steps
- 👉 Getting Started — scaffold a project with
create-ydesign - 👉 Customizations
- 👉 Integrations overview — compare React / Vue / frameworkless / iframe
- 👉 Side panel overview
- 👉 Cloud Render API
- 👉 Showcase
Hit an issue or have a feature idea? File on GitHub Issues. Want to vote on the roadmap? See Roadmap.