Polotno Design Editor Framework
Polotno is a JavaScript library and React component SDK designed for building versatile, white-label canvas-based design editors. It provides a comprehensive framework for creating applications that handle image, video, and graphic design, as well as template systems and programmatic asset generation. The current stable version is 2.40.0, with frequent minor releases occurring typically on a weekly or bi-weekly basis, as evidenced by its detailed changelog. Key differentiators include its highly customizable React component architecture, which allows developers to replace or extend almost any part of the UI, and its flexible rendering options supporting both client-side and server-side generation via `polotno-node`. Unlike lower-level canvas libraries like Konva.js, Polotno offers a complete, opinionated solution built on MobX for state management, simplifying the development of full-featured design suites for various business applications, including print-on-demand, marketing automation, and digital signage platforms. It supports importing JSON, SVG, and exporting to JSON, PNG, JPEG, PDF, MP4, and more. A commercial API key is required for production use.
Common errors
-
Could not resolve dependency: npm error peer react@"^18.2.0" from polotno@2.x.x
cause Attempting to install Polotno in a project using React 19, which has a conflicting peer dependency range.fixAdd resolutions/overrides to your `package.json` to force `react`, `react-dom`, and `react-konva` (if used) to version 18.2.0, e.g., `"overrides": { "polotno": { "react": "18.2.0", "react-dom": "18.2.0", "react-konva": "^18.2.0" } }`. -
Uncaught TypeError: Cannot read properties of undefined (reading 'ReactCurrentOwner')
cause This error typically occurs when different versions of React are loaded, or React context is lost, often associated with React 19 compatibility issues.fixEnsure all React-related packages (React, ReactDOM, Polotno, and any other UI libraries) resolve to the exact same React 18 version. Use package manager overrides as described for the `peer react` dependency error. -
Error: Minified React error #185; Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.
cause An infinite rendering loop, often when Polotno's MobX store reactivity conflicts with another framework's reactivity system (e.g., Vue 3) or when a React component's `setState` is called synchronously within its render or update phase without proper guarding.fixWhen embedding Polotno in a non-React app, ensure the React part is isolated. For Vue 3, wrap the React editor mount point with `mobx-vue-lite`'s `Observer` component. Review component lifecycle for unintended state updates. -
Memory leak / "Page unresponsive" when combining all text effects with an animation on a Text element.
cause Intensive rendering or state updates, particularly with complex text rendering, filters, and animations, can overwhelm browser resources.fixSimplify design elements, reduce the number of simultaneous effects, or optimize animations for performance. Consider reporting the specific use case to Polotno support for potential library-level optimizations.
Warnings
- breaking Polotno currently relies on React 18.2.0. Using React 19 may cause dependency resolution issues or runtime errors like `Cannot read properties of undefined (reading 'ReactCurrentOwner')`.
- gotcha A Polotno API key is required for production usage. While a free key is available for development, commercial use necessitates obtaining a license.
- gotcha Integrating Polotno (a React-based library using MobX) into other JavaScript frameworks like Vue or Angular directly can lead to 'Maximum update depth exceeded' errors due to reactivity conflicts.
- gotcha Complex text elements combined with multiple filter-based effects and animations can lead to significant memory usage, potentially causing browser tabs to become unresponsive or crash.
- gotcha When using `polotno-node` for server-side rendering, especially in environments like AWS Lambda, complex designs may require a substantial increase in allocated memory to prevent 'Out of Memory' errors or timeouts.
Install
-
npm install polotno -
yarn add polotno -
pnpm add polotno
Imports
- PolotnoContainer
const PolotnoContainer = require('polotno').PolotnoContainer;import { PolotnoContainer } from 'polotno'; - createStore
import createStore from 'polotno/model/store';
import { createStore } from 'polotno/model/store'; - Toolbar
import { Toolbar } from 'polotno';import { Toolbar } from 'polotno/toolbar/toolbar';
Quickstart
import React from 'react';
import ReactDOM from 'react-dom/client';
import { PolotnoContainer, SidePanelWrap, WorkspaceWrap } from 'polotno';
import { Toolbar } from 'polotno/toolbar/toolbar';
import { ZoomButtons } from 'polotno/toolbar/zoom-buttons';
import { SidePanel } from 'polotno/side-panel';
import { Workspace } from 'polotno/canvas/workspace';
import { createStore } from 'polotno/model/store';
import '@blueprintjs/core/lib/css/blueprint.css'; // Polotno uses Blueprint.js styles
const store = createStore({
key: process.env.POLOTNO_API_KEY ?? 'YOUR_FREE_API_KEY_HERE',
showCredit: true // Set to false with a paid license to hide the back-link
});
// Add a default page to the store
store.addPage();
export const PolotnoEditor = () => {
return (
<PolotnoContainer style={{ width: '100vw', height: '100vh' }}>
<SidePanelWrap>
<SidePanel store={store} />
</SidePanelWrap>
<WorkspaceWrap>
<Toolbar store={store} downloadButtonEnabled />
<Workspace store={store} />
<ZoomButtons store={store} />
</WorkspaceWrap>
</PolotnoContainer>
);
};
// Example of how to render it in a root (e.g., in index.tsx)
/*
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<PolotnoEditor />
</React.StrictMode>
);
*/