Quick Start
The example below is not hand-copied into this page — it's pulled directly, at build time, from packages/react/src/quickstart.example.tsx in the repository. That file is typechecked on every CI run (packages-ci.yml's "Typecheck packages" step), so this page can never silently drift from a working example the way a copy-pasted snippet could.
import type { ReactElement } from "react";
import type { EditorPlugin } from "@rifrocket/fabricjs-design-tool";
import { Editor, useEditor } from "./index";
// Type-checked by the package's "typecheck" script on every build, so the documented Quick Start
// can never silently drift from the real public API — v1's README example didn't compile against
// real props. Not exported from index.ts, so it never reaches the published bundle.
const examplePlugin: EditorPlugin = {
name: "example",
install(engine) {
engine.registry.registerTool("select", { shortcut: "v" });
},
};
function QuickStartApp(): ReactElement {
return (
<Editor
plugins={[examplePlugin]}
theme="dark"
width={800}
height={600}
onReady={(engine) => {
engine.setZoom(1);
}}
/>
);
}
function AddRectangleButton(): ReactElement {
const engine = useEditor();
return (
<button type="button" onClick={() => engine.addObjectOfType("rect", { left: 10, top: 10 })}>
Add rectangle
</button>
);
}
export { QuickStartApp, AddRectangleButton };
A few things worth noticing:
pluginsis construction-time only.<Editor plugins={[examplePlugin]}>reads itspluginsarray exactly once, when the engine is constructed — changing the array on a live, already-mounted<Editor>does nothing. There's no safe general story for hot-swapping an installed plugin set (uninstall ordering, plugin-held state), so this is deliberate, not a bug. To swap plugins, remount with a differentkey(e.g.key={documentId}). The same rule applies to<DesignEditor preset="...">and itspluginsoverride prop — see Installing Plugins for the full explanation.onReadyfires once, synchronously, right after the engine is constructed — it's the place to run first-time setup likeengine.setZoom(1)above, or to restore a previously-saved document.useEditor()(used byAddRectangleButtonabove) gives any descendant component access to the liveCanvasEngineinstance, as long as it's rendered somewhere inside<Editor>— no prop drilling required.
Batteries-included: <DesignEditor>
The example above uses <Editor> with a single, hand-written example plugin — useful for understanding the underlying contract, but not how most apps start. For a general-purpose editor, <DesignEditor preset="default"> bundles a curated, dependency-light set of plugins (shapes, clipboard, SVG import, images, effects, PDF export, QR codes) with zero configuration:
import { DesignEditor } from "@rifrocket/fdt-react";
function App() {
return <DesignEditor preset="default" theme="system" width={800} height={600} />;
}
See Choosing your entry point for how to decide between <DesignEditor>, <Editor>, and the framework-agnostic createEngine().
Next steps
- Choosing your entry point — decision guide.
- Architecture overview — what
CanvasEngineactually composes under the hood. - Plugins overview — the full plugin list, and an important distinction between two plugin shapes you should know before installing one.