GrapesJS Vue 3: Build Custom Editor
What's Included
- Free to download & use
- Open for personal & commercial use
Support The Creator
Use one-time or monthly support to thank the creator for this free product.
GrapesJS Compatible
Tested with GrapesJS 0.22.x
Open Source on GitHub
Free to use, fork, and contribute
Editor Compatible
Designed for the GrapesJS open-source editor
Free to Use
Open for personal and commercial projects
Vue 3 wrapper components and composables for building custom editor UIs around GrapesJS.
grapesjs-vuelets you integrate GrapesJS into a Vue 3 application with a declarative, idiomatic API. The library is focused on the UI controlsaroundthe canvas — sidebars, toolbars, panels, modals — while GrapesJS continues to own canvas rendering. This split keeps the editor's native behavior intact and lets you design any shell you want with Vue.
Features
- Drop-in
<Editor>component— pass in the GrapesJS module (or a CDN URL) plus standard editor options and you're up and running with the default UI. - Custom UI mode— place a
<Canvas />anywhere in your layout to mount the GrapesJS canvas, and the wrapper automatically initializes GrapesJS incustomUImode so Vue owns the chrome. - Composables—
useEditor()returns the loaded GrapesJS instance (throws if called before ready);useEditorMaybe()returnsundefineduntil the editor is available. Use<WithEditor>to guarantee children render only once the editor is ready. - Provider components with scoped slotsfor every major GrapesJS Manager:
BlocksProvider,DevicesProvider,PagesProvider,LayersProvider,SelectorsProvider,StylesProvider,TraitsProvider,AssetsProvider,ModalProvider
- Flexible plugin loading— pass plugins as strings, functions, or
{ id, src, options }descriptors. - CDN-friendly— load GrapesJS itself via a script URL and the wrapper handles the rest, including stylesheet injection via
grapesjsCss. waitReadyoptionto defer exposing the editor instance until a specific event fires.- TypeScript-first— ships full type declarations (
EditorProps,PluginToLoad,PluginTypeToLoad, and per-provider*ResultProps). - Ships asESM,CJS, and.d.tsbundles.
Compatibility
- Vue≥ 3.5
- GrapesJS≥ 0.22.16
Installation
pnpm add grapesjs-vue grapesjs vue # or npm install grapesjs-vue grapesjs vue Don't forget to import the GrapesJS stylesheet (or pass a stylesheet URL when loading GrapesJS via script).
Custom UI with built-in canvas
Place<Canvas />wherever you want the GrapesJS canvas mounted. Once aCanvasis provided, the wrapper initializes GrapesJS incustomUImode and Vue takes over the surrounding controls.
<script setup lang="ts"> import grapesjs from 'grapesjs' import 'grapesjs/dist/css/grapes.min.css' import { Canvas, Editor } from 'grapesjs-vue' </script> <template> <Editor :grapesjs="grapesjs" :options="{ height: '100%', storageManager: false }"> <div class="editor-shell"> <aside class="sidebar">Your custom panel</aside> <Canvas class="canvas" /> </div> </Editor> </template> Editor composables
<!-- EditorStatus.vue --> <script setup lang="ts"> import { useEditorMaybe } from 'grapesjs-vue' const maybeEditor = useEditorMaybe() const ready = Boolean(maybeEditor) </script> <template> <span>{{ ready ? 'Ready' : 'Loading' }}</span> </template> <!-- ClearCanvasButton.vue --> <script setup lang="ts"> import { useEditor } from 'grapesjs-vue' const editor = useEditor() </script> <template> <button type="button" @click="editor.runCommand('core:canvas-clear')"> Clear canvas </button> </template> Wrap children in<WithEditor>to guaranteeuseEditor()is safe to call inside:
<script setup lang="ts"> import { WithEditor } from 'grapesjs-vue' import ClearCanvasButton from './ClearCanvasButton.vue' </script> <template> <WithEditor> <ClearCanvasButton /> </WithEditor> </template> Provider components
Providers expose each GrapesJS Manager's state and actions through Vue scoped slots — so your custom UI stays declarative while preserving GrapesJS's native behavior.
<script setup lang="ts"> import { BlocksProvider } from 'grapesjs-vue' </script> <template> <BlocksProvider v-slot="{ blocks, dragStart, dragStop }"> <button v-for="block in blocks" :key="block.getId()" type="button" draggable="true" @dragstart="dragStart(block, $event)" @dragend="dragStop" > {{ block.getLabel() }} </button> </BlocksProvider> </template> Built-in providers:
| Component | GrapesJS Manager |
|---|---|
BlocksProvider | Blocks |
DevicesProvider | Devices |
PagesProvider | Pages |
LayersProvider | Layers |
SelectorsProvider | Selectors |
StylesProvider | Styles |
TraitsProvider | Traits |
AssetsProvider | Assets |
ModalProvider | Modal |
API overview
Exports
- Components:
Editor(default export, also exported asGjsEditor),Canvas,WithEditor - Providers:
BlocksProvider,DevicesProvider,PagesProvider,LayersProvider, SelectorsProvider,StylesProvider,TraitsProvider,AssetsProvider,ModalProvider- Composables:
useEditor,useEditorMaybe - Types:
EditorProps,PluginToLoad,PluginTypeToLoad, and*ResultPropsfor each provider
<Editor>props
| Prop | Type | Description |
|---|---|---|
grapesjs | string | GrapesJsModule | GrapesJS module, or CDN script URL |
options | EditorConfig | Standard GrapesJS config |
grapesjsCss | string | Stylesheet URL when loading GrapesJS via script |
plugins | PluginTypeToLoad[] | Plugin list — strings, functions, or{ id, src, options } |
waitReady | boolean | string | object | Wait for a specific ready event before exposing the editor |
Build output
- ESM:
dist/grapesjs-vue.js - CJS:
dist/grapesjs-vue.cjs.js - Types:
dist/index.d.ts
License
MIT
Ratings:
No reviews yet. Be the first to share your experience.
Questions & Answers
No questions yet. Have something to ask?
Common problems this plugin can help fix
Real community questions on the same topic — see how others worked around them.
