PageKit — the self-hosted GrapesJS site builder, sold as source. Get early access

Vue 3 · Nuxt · GrapesJS

Vue Page Builder with GrapesJS

Build a visual drag-and-drop page builder for Vue 3 and Nuxt with custom blocks, components, templates, responsive editing and your own storage and publishing workflow.

Vue 3 & NuxtVisual drag & dropCustom componentsReusable blocksResponsive editingYour backendExtensible with plugins
app.yourproduct.com/pages/editor
Vue Page Builder

Blocks

  • Hero
  • Features
  • Pricing
  • Testimonials
  • FAQ

Your page

Desktop · Tablet · Mobile
Three panels and a canvas: a block library on the left, the page in the middle, style controls on the right, device widths along the bottom. That is the interface your users get — and the part you do not have to build.

View the Vue integration guide

0.23.6

GrapesJS version this page is written against

100+

Plugins and templates on GJS.Market

BSD-3-Clause

Licence of the editor core

$0

Cost to run the editor itself

See it first

A real page builder, running on this page

This is GrapesJS itself, not a screenshot. Drag a block in, select an element, restyle it, switch device widths. The editor is created by one `init()` call — in a Vue app that call lives in `onMounted`, and everything you see here behaves identically.

  • Drag & drop
  • Style Manager
  • Layer Manager
  • Desktop / Tablet / Mobile
  • HTML + CSS export
Why not from scratch

Build a visual page builder without starting from scratch

A production page builder is far more than a few Vue components. It is a canvas, a drag-and-drop system, a component model, a style engine, responsive editing, undo history, asset handling, storage and export. Here is the whole surface, and who ends up owning each piece.

  • GrapesJS core

    Editing canvas

    An isolated document users edit directly, with its own styles and scroll.

  • GrapesJS core

    Drag & drop

    Drop targets, insertion points, reordering and nesting rules.

  • GrapesJS core

    Component model

    Typed elements with their own settings, constraints and behaviour.

  • GrapesJS core

    Selection & toolbars

    Click-to-select, hover outlines, per-element toolbars and badges.

  • GrapesJS core

    Style Manager

    Typography, colour, spacing and layout controls bound to selectors.

  • GrapesJS core

    Responsive editing

    Device widths and breakpoint-scoped styles in the same canvas.

  • GrapesJS core

    Layer Manager

    A tree of the page so deep structures stay navigable.

  • GrapesJS core

    Undo & redo

    A command history across every edit, not just text.

  • GrapesJS core

    HTML & CSS export

    Clean markup and stylesheet generated from the current document.

  • Plugins

    Block library

    The ready-made sections users drag in. Yours, or installed.

  • Plugins

    Templates

    Whole starting layouts so nobody meets a blank canvas.

  • Plugins

    Asset management

    Uploads, media libraries and image handling.

  • Plugins

    Rich text editing

    Inline text formatting beyond the built-in editor.

  • Plugins

    Multi-page projects

    More than one page inside a single project.

  • Your Vue app

    Storage

    Where project data is written and read. Your API, your database.

  • Your Vue app

    Authentication & roles

    Who may open, edit and publish which project.

  • Your Vue app

    Multi-tenancy

    Isolating one customer's pages, assets and templates from another's.

  • Your Vue app

    Publishing & hosting

    Turning approved output into a live page on your infrastructure.

  • Your Vue app

    Plans & billing

    What each customer is entitled to, and what they pay for it.

Who owns itGrapesJS corePluginsYour Vue app

The middle column is the point of GJS.Market: it is real capability you install rather than schedule. The right-hand column never becomes someone else's problem — that is your product, and this page is explicit about it in every section that touches it.

See the five-step integration
Architecture

Vue is your framework. GrapesJS is your editor.

GrapesJS is not a replacement for your application and not a hosted service. It is an editing engine that mounts into one element of one route. Everything above and below it in this diagram stays yours.

  1. Your Vue / Nuxt application

    Everything that makes the product yours. GrapesJS has no opinion about any of it.

    • Authentication
    • Users
    • Routing
    • Billing
    • Business logic
    • APIs
  2. The GrapesJS editor

    One mounted instance, inside one component, on one route. This is the layer you are not building.

    • Canvas
    • Blocks
    • Components
    • Styles
    • Layers
    • Assets
  3. Your backend

    The editor hands you two artefacts and one media stream. What happens next is your API's decision.

    • Project JSON
    • HTML + CSS
    • Media
    • Roles
  4. Your database

    Ordinary rows in a schema you designed. Nothing here is a GrapesJS format you have to adopt.

    • Projects
    • Versions
    • Tenants
    • Pages

Read it top to bottom: your Vue application authenticates the user and routes them to an editor page; the editor produces project data; your API writes it to your database. The editor never talks to your database, and your database never has to understand the editor.

How the editor mounts into a Vue component
The objection

Does GrapesJS replace Vue?

No. This is the first question most Vue developers ask, and the answer changes how the rest of the page reads. The two layers do not overlap: one runs your application, the other runs an editing surface inside it.

Vue / Nuxt

Vue stays responsible for

Your application, exactly as you build it today.

  • Application UI
  • Routing
  • Authentication
  • Business logic
  • State management
  • APIs and data fetching
  • Billing and plans
  • Users and permissions
GrapesJS

GrapesJS provides

The visual editing layer, inside one element you give it.

  • Visual canvas
  • Drag & drop
  • Blocks
  • Components
  • Styles
  • Layers
  • Assets
  • Device widths

One honest caveat while we are here: the canvas renders plain DOM inside an iframe, not mounted Vue components. Your app is Vue; what your users edit is HTML and CSS that your app then renders however it likes.

Capabilities

Everything you need for a visual page builder

This is what the editor gives you on day one, before a single plugin is installed. Each one is configurable — panels, categories, constraints and labels are all yours to set.

Drag & drop

Users build layouts by dragging sections and elements into the canvas, with drop targets, reordering and nesting.

Components

Define your own element types with their own settings, constraints and behaviour, and reuse them across every project.

Blocks

The ready-to-use sections users pull from the panel. Group them into categories that match your product's vocabulary.

Style Manager

Typography, colour, spacing and layout controls. Restrict the property set so users cannot style their way out of your design system.

Responsive editing

Switch the canvas between desktop, tablet and mobile widths and write breakpoint-scoped styles in place.

Layers

A structural tree of the page, so a deeply nested layout stays selectable and reorderable.

Assets

An asset manager for images and media, backed by whatever storage or CDN you already use.

Templates

Reusable starting layouts, so a new page begins as something rather than an empty canvas.

Export

Generate HTML and CSS from the current document, or take the project data and render it your own way.

Customisation

Create a page builder around your product

The difference between a generic website builder and a builder that belongs in your product is the component set. Do not force your content model into someone else's element types — register your own.

  1. Your product
  2. Custom components
  3. Custom blocks
  4. Custom templates
  5. Custom commands
  6. Custom UI

Each step is ordinary configuration on the editor instance: a component type, a block that inserts it, a template that arranges several, a command that acts on them, and a panel that exposes it.

builder/registerProductBlocks.tsts
// builder/registerProductBlocks.ts
import type { Editor } from 'grapesjs';

// A plugin is just a function that receives the editor, so everything below
// works identically in Vue, Nuxt, React or a plain HTML page.
export function registerProductBlocks(editor: Editor): void {
  // A custom component type: your own element, with your own settings.
  editor.DomComponents.addType('pricing-table', {
    isComponent: (el) => el.dataset?.gjsType === 'pricing-table',
    model: {
      defaults: {
        droppable: false,
        traits: [
          { name: 'plan', type: 'select', options: ['free', 'pro', 'team'] },
          { name: 'highlight', type: 'checkbox' },
        ],
      },
    },
  });

  // A block: what the user actually drags in from the panel.
  editor.BlockManager.add('pricing-table', {
    label: 'Pricing',
    category: 'Sections',
    content: { type: 'pricing-table' },
  });
}
  • A component type defines what an element is: what it accepts, what it refuses, and which settings it exposes.
  • A block is what users see in the panel — the same type can back several blocks with different presets.
  • Traits become the settings sidebar, so your users configure elements instead of editing markup.
  • `droppable: false` and matching constraints are how you keep a designed component from being taken apart.
  • Commands let you attach your own actions — publish, duplicate to another tenant, request review.
  • None of this is Vue-specific: a plugin is a function that receives the editor, so it also works in Nuxt, React or plain HTML.

Don't force your product into a generic website builder. Customise the editor around your own content model and design system.

Governance

Keep your design system under control

An unrestricted canvas produces pages that embarrass the product they live in. The editor is configurable in both directions — the useful setting is not maximum freedom, it is bounded freedom.

What users should be able to do

  • Assemble pages from approved blocks in any order
  • Write and edit their own copy in place
  • Swap images from the asset library
  • Choose between defined layout variants
  • Adjust content per device width
  • Start from a template and diverge from it

What the editor should hold constant

  • Typography scale and font families
  • The brand palette, exposed as named colours rather than a picker
  • Spacing steps, instead of arbitrary pixel values
  • Which components may nest inside which
  • Which blocks a given role or plan can even see
  • The structural sections a template guarantees

Give users creative freedom without letting them break your product's design system.

Content

Don't start users with a blank canvas

The single biggest driver of whether a page builder gets used is what is waiting in the block panel on the first visit. Build the sections your product actually needs, or install a library and rename it.

  • Hero

    Headline, supporting line and a primary action.

  • Feature grid

    A repeating grid of capabilities or benefits.

  • Pricing

    Plan columns with features and a call to action.

  • Testimonials

    Quotes with attribution, in a row or a carousel.

  • FAQ

    Question and answer pairs, expandable or flat.

  • Contact

    A form section posting to your own endpoint.

  • CTA strip

    A full-width band with one clear action.

  • Footer

    Navigation columns, legal links and brand marks.

Persistence

Save projects to your own backend

GrapesJS does not host anything and does not choose a database. You register a storage adapter with two methods — load and store — and both talk to your API. Nothing leaves your infrastructure.

  1. Visual editor
  2. Project JSON
  3. Your API
  4. Your backend
  5. Your database

The editor only ever knows about `load()` and `store()`. Where those calls end up — Postgres, MySQL, Mongo, S3, a headless CMS — is a decision the editor never participates in.

components/PageBuilder.vue — storage adapterts
const editor = grapesjs.init({
  container: host.value!,
  storageManager: {
    type: 'app-api',
    autosave: true,
    stepsBeforeSave: 10,
  },
  // Registered as a plugin so the adapter exists before the first load().
  plugins: [
    (ed) => {
      ed.Storage.add('app-api', {
        async load() {
          const res = await fetch(`/api/projects/${props.projectId}`);
          if (!res.ok) throw new Error(`Load failed: ${res.status}`);
          return await res.json();
        },
        async store(project) {
          const res = await fetch(`/api/projects/${props.projectId}`, {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(project),
          });
          if (!res.ok) throw new Error(`Save failed: ${res.status}`);
        },
      });
    },
  ],
});
  • Register the adapter as a plugin so it exists before the editor performs its first load.
  • `autosave` with `stepsBeforeSave` batches writes instead of firing one per keystroke.
  • Store the project JSON as the source of truth; it is what the editor reloads.
  • Keep versions as ordinary rows — revision history is a schema decision, not an editor feature.
  • Authorise every load and store on the server. The project id in the request is a claim, not a permission.
  • Surface save state in your own Vue UI by listening to the editor's storage events.

You control your data and your backend. The editor is a client of your API like any other part of your app.

Data model

What should you store?

Two artefacts come out of the editor and they are not interchangeable. Storing the wrong one is the mistake that makes pages uneditable six months later.

Project JSON — the source of truth

The full editable document: components, styles, assets, pages. Feed it back to `load()` and the user resumes exactly where they left off. This is the row you must never lose.

HTML + CSS — the output

A rendering of the current document, produced on demand. Regenerate it on every publish rather than treating it as state; it cannot be turned back into an editable project.

Keep both, for different reasons

The JSON is what the editor reads. The HTML is what your visitors read. Storing only the second is the one-way door — the page renders forever and can never be edited again.

Saving both artefacts on publishts
// The source of truth. Store it; the editor reloads from it.
const projectData = editor.getProjectData();

// The output. Regenerate it every time you publish.
const html = editor.getHtml();
const css = editor.getCss();

await $fetch(`/api/projects/${projectId}/publish`, {
  method: 'POST',
  body: { projectData, html, css },
});

// Authorize the request and sanitize `html` on the server —
// never in the component that produced it.

To edit again

  1. Project JSON
  2. load()
  3. Editable again

To publish

  1. getHtml() + getCss()
  2. Sanitize
  3. Serve

Store project data for editing. Generate HTML and CSS when you need publishable output.

Delivery

From visual editing to production

Authoring and publishing are different jobs. GrapesJS finishes at the moment a user is happy with a page; everything after that is your workflow, on your infrastructure.

  1. Create
  2. Edit
  3. Save
  4. Review
  5. Publish
  6. Live page

Insert review, approval or scheduling wherever your product needs them — the editor has no opinion about the steps between save and live.

Where published output can go

  • A REST endpoint in your own API
  • A headless CMS you already run
  • Static files, built and deployed on publish
  • A custom backend that renders pages on request
  • A CDN in front of any of the above
  • Your existing deployment pipeline, unchanged

GrapesJS handles authoring. Your infrastructure handles publishing — there is no hosting bundled with the editor, and this page will not pretend otherwise.

SaaS architecture

Build a multi-tenant Vue page builder

Every customer gets their own pages, their own assets, their own templates and their own brand. That isolation is a property of your data model and your API — the editor is simply handed the right project.

Your Vue SaaS

  • Org A

    • Pages
    • Assets
    • Templates
    • Brand
  • Org B

    • Pages
    • Assets
    • Templates
    • Brand
  • Org C

    • Pages
    • Assets
    • Templates
    • Brand

What your Vue app and backend implement

  • A tenant id on every project, asset and template row
  • Server-side authorisation on every load, store and publish call
  • Per-tenant asset storage, so one customer's uploads are never listed to another
  • Tenant-scoped template and block sets
  • Per-tenant branding applied when the editor is created
  • Roles inside a tenant: who may edit, who may approve, who may publish

Multi-tenancy is not a GrapesJS feature. Nothing in the editor enforces it, and a page builder that relies on the client to pick the right tenant is not multi-tenant — it is a shared database with a UI convention.

Explore the SaaS page builder page
Branding

Turn your Vue editor into your own product

Nothing in the interface has to look like a library. The panels, the icons, the wording and the workflow are all configuration — most shipped GrapesJS builders are unrecognisable as GrapesJS.

  • Custom logo and colour scheme
  • Custom panels and toolbars
  • Custom blocks and templates per customer
  • Custom terminology throughout the UI
  • Roles that change what the editor exposes
  • Permissions enforced on your server, reflected in the UI
Ecosystem

Extend your Vue page builder with plugins

A plugin is a function that receives the editor instance. That is the whole contract — which is why there is no separate Vue edition of any of these. The same package works in a Vue component, a Nuxt page, a React app or a plain HTML file, because none of them is what it attaches to.
  1. GrapesJS core
  2. Vue / Nuxt integration
  3. Blocks
  4. Templates
  5. Storage
  6. Assets
  7. Pages
  8. Forms
  9. Export
  10. AI & advanced features

To be clear about what does not exist: there is no official GrapesJS wrapper for Vue and no Vue-specific plugin on GJS.Market. You call `grapesjs.init()` yourself from `onMounted`, which is five lines, and every plugin in the catalogue then works unchanged.

Start at the top and add only the layers your product actually reaches. Most builders never install anything from the bottom half.

Marketplace

Plugins that solve the parts you would otherwise schedule

Real listings from GJS.Market, grouped by the problem they remove. Every one of them installs into the same editor instance your Vue component creates.

Shopping lists

Build your Vue page builder stack

The same catalogue, cut by the product you are building. Install the stack that matches your case and ignore the rest — an editor with every plugin loaded is slower and harder to use, not better.

Prices shown are the current GJS.Market listing prices; free plugins are marked.

Catalogue

Every category, in the order you will need them

If a stack above does not match your product, start here instead. These are the catalogue sections, roughly in the order a builder grows into them.

Browse everything
Buy vs build

Build every feature yourself vs extend with plugins

Neither column is free. The question is only which one your team should be spending its time in.

ConsiderationBuild it in-houseInstall from GJS.Market
Getting the capabilityDevelopment time on your roadmapInstall and configure
Keeping it workingYou maintain it foreverMaintained as a published package
ReuseInternal-only codeA solution other products already run
ScopeYou build every feature yourselfAdd only what your product needs
Where the cost landsEngineering timeA listing price, once
What your team works onEditor infrastructureYour product

No cost or time figures appear in this table on purpose — we do not know your team, and any number here would be invented.

The real comparison

Build a Vue page builder from scratch vs GrapesJS

Row by row, what you would be writing yourself and what already exists. "Extensible" means the engine provides the hook and you supply the behaviour — usually a few lines, sometimes a plugin.

CapabilityFrom scratchGrapesJS
Editing canvasBuildIncluded
Drag & dropBuildIncluded
Component modelBuildIncluded
BlocksBuildExtensible
Style ManagerBuildIncluded
Responsive editingBuildIncluded
Layer treeBuildIncluded
Undo & redoBuildIncluded
AssetsBuildExtensible
TemplatesBuildExtensible
StorageBuildExtensible
HTML / CSS exportBuildIncluded
Vue components in the canvasBuildNot included — the canvas renders DOM
Multi-tenancy, roles, publishingBuildNot included — your application

Included = ships with the core. Extensible = a documented extension point, plus plugins where they exist.
Verified against GrapesJS 0.23.6 on 2026-09-02.

Build your Vue product. Don't rebuild the visual editor.

Integration

Integrate GrapesJS with Vue 3

Five steps, one component. There is no official Vue wrapper and you do not need one: GrapesJS renders into a plain element, so the only Vue-specific question is which lifecycle hook calls `init()`. Install grapesjs 0.23.6, create the component, initialise on mount, pass your plugins, destroy on unmount.

  1. Install GrapesJS
  2. Create the editor component
  3. Initialise on mount
  4. Configure plugins
  5. Destroy on unmount
npm install grapesjs
components/PageBuilder.vuevue
<!-- components/PageBuilder.vue -->
<template>
  <div ref="host" class="page-builder" />
</template>

<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, shallowRef } from 'vue';
import grapesjs, { type Editor } from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';

// shallowRef, not ref: the editor is a large non-reactive instance and
// deep-proxying it costs performance for nothing.
const editor = shallowRef<Editor | null>(null);
const host = ref<HTMLElement | null>(null);

onMounted(() => {
  editor.value = grapesjs.init({
    container: host.value!,
    height: '100%',
    fromElement: false,
    storageManager: false,
    plugins: [],          // GJS.Market plugins go here
    blockManager: { blocks: [] },
  });
});

onBeforeUnmount(() => {
  editor.value?.destroy();
  editor.value = null;
});
</script>
  • `shallowRef`, not `ref`: the editor is a large non-reactive object and deep-proxying it costs performance for nothing.
  • `onMounted` never runs on the server, which is what makes this safe in Nuxt without any extra machinery.
  • `destroy()` on unmount matters — a route change that leaves an editor mounted leaks its listeners and its iframe.
  • `storageManager: false` while you are wiring things up, then swap in your adapter when the API is ready.
  • Import the editor stylesheet once; it styles the panels, not your application.
  • Everything past this point — events, wrappers, the composable form — is on the integration guide.
Read the complete Vue integration guide
Nuxt

Vue 3 + Nuxt

GrapesJS needs a browser DOM. Under Nuxt's server render there is no `document`, so the editor has to be created on the client — which `onMounted` already guarantees. `<ClientOnly>` is the belt-and-braces version, and it is where the fallback markup lives.

  1. Nuxt SSR
  2. <ClientOnly>
  3. grapesjs.init()
  4. Browser DOM

The server renders everything around the editor; the editor itself appears once the component is mounted in the browser.

pages/editor.vuevue
<!-- pages/editor.vue -->
<template>
  <ClientOnly>
    <PageBuilder :project-id="route.params.id" />

    <template #fallback>
      <p class="editor-placeholder">Loading the editor…</p>
    </template>
  </ClientOnly>
</template>

<script setup lang="ts">
const route = useRoute();
</script>

Reproduced, not assumed

Runtime
Node 20, no DOM
GrapesJS
0.23.6
Importing the module
import('grapesjs') → resolves
Calling init()
grapesjs.init() → ReferenceError: document is not defined

Run in plain Node with no DOM on 2026-09-02. The distinction matters: the import is safe, so you do not need a dynamic import to keep the bundle server-safe — you need the init call to happen in the browser.

  • Use `<ClientOnly>` when you want a server-rendered fallback in place of the editor.
  • The `.client.vue` suffix is Nuxt's own way of saying the same thing for a whole component.
  • SSR is not the interesting part of this page — it is one boundary, and it is a two-line one.
  • Everything outside the editor route renders on the server exactly as it does today.
Avoid these

4 mistakes to avoid when building a Vue page builder

Each of these is cheap to get right at the start and expensive to fix once customers are in the editor.

  • The mistake

    Initialising during SSR

    Calling `init()` anywhere that runs on the server throws, because there is no `document` to render the canvas into.

    What to do instead

    Create the editor in `onMounted` only, and wrap the route in `<ClientOnly>` if you want a server-rendered fallback.

  • The mistake

    Saving only the HTML

    The rendered output cannot be turned back into an editable document. Every page saved this way is frozen the moment it is published.

    What to do instead

    Store the project JSON as the source of truth and regenerate HTML and CSS whenever you publish.

  • The mistake

    Giving users an unlimited blank canvas

    Total freedom produces pages that break your design system, and a first-run experience with nothing in the panel produces no pages at all.

    What to do instead

    Ship curated blocks and templates, and constrain the style properties users can reach.

  • The mistake

    Installing every plugin

    Each plugin adds panels, bundle weight and a surface your users have to understand. A crowded editor is harder to use, not more capable.

    What to do instead

    Start with the stack for your product shape and add a plugin when a real need appears.

Before launch

Production checklist for a Vue page builder

The things that separate a working demo from something you can put in front of paying customers.

Editor

Lifecycle and configuration

The instance behaves correctly across every route change.

  • `init()` runs once per mount, never on the server
  • `destroy()` runs on unmount and on route change
  • Plugins are registered before the first `load()`
  • Custom components and blocks are registered in one place
  • The editor stylesheet is loaded exactly once
Data

Project data

Nothing a user typed can be lost.

  • Project JSON is the stored source of truth
  • Autosave is on, with sensible batching
  • Versions are retained so a bad edit is recoverable
  • Publish writes HTML and CSS separately from the project
  • Load failures surface as an error, never as an empty canvas
UX

The editing experience

A non-developer can produce a good page unaided.

  • Curated blocks in categories your users recognise
  • At least one template per page type
  • Save state is visible in your own UI
  • Device widths are reachable and obvious
  • Empty states explain what to do next

First-run experience decides adoption more than feature count.

Security

Server-side enforcement

Every rule is enforced where the client cannot reach it.

  • Authentication on every editor route
  • Authorisation on every load, store and publish call
  • Upload validation by type and size, server-side
  • Published HTML sanitised before it is served
  • Tenant isolation checked on the server, not inferred from the request
Publishing

Getting pages live

The path from an approved draft to a live URL is defined.

  • A preview that matches published output
  • An explicit publish action, separate from save
  • Review or approval where your process needs it
  • Cache invalidation after publish
  • A rollback path to a previous version
Performance

Performance considerations

The editor is a heavy dependency and it belongs on exactly one route. Most performance problems in a builder come from loading it where it is not needed.

  • Load the editor only on the routes that actually edit, not in your application shell.
  • Lazy-load heavy plugins and panels rather than registering everything at startup.
  • Keep the editor instance out of deep reactivity — `shallowRef` exists for objects like this.
  • Do not mirror editor state into Vue refs on every change; listen to the events you actually render.
  • Paginate or lazily load large asset libraries instead of handing the asset manager thousands of rows.
  • Install plugins your product uses; every extra one costs bundle size and panel space.
Security

Security considerations

A page builder accepts arbitrary content from users and turns it into pages other people see. Treat every input as untrusted and every client-side rule as decorative.

  • Authorise every project load, store and publish on the server.
  • Enforce tenant isolation in the query, not in the component that issued it.
  • Validate uploads by type and size before they reach your storage.
  • Sanitise published HTML before serving it to anyone.
  • Authenticate the API the editor talks to like any other endpoint.
  • Protect publish endpoints separately — publishing is a privileged action.
  • Re-check permissions on the server even when the UI already hid the button.

Never rely only on client-side permissions.

Who does this

Who builds Vue page builders?

Different products, one architecture. If you recognise your team here, the rest of this page is written for you.

SaaS companies

Adding visual editing to an existing product so customers stop filing tickets for content changes.

Agencies

Building a custom editing experience per client, on one codebase they maintain.

CMS platforms

Giving customers visual editing over content the platform already models.

Marketing platforms

Letting campaign teams launch pages without a developer in the loop.

Enterprise teams

Creating controlled internal editing workflows with roles, review and approval.

Questions

Vue page builder FAQ

What is a Vue page builder?

A visual editor inside a Vue application that lets someone assemble and style a page by dragging sections onto a canvas, instead of writing markup. The Vue app supplies the routes, users and data; the editor supplies the canvas.

Can I use GrapesJS with Vue 3?

Yes. GrapesJS renders into a plain DOM element, so you create it inside `onMounted` and destroy it in `onBeforeUnmount`. No wrapper library is involved.

Can I use GrapesJS with Nuxt?

Yes. The editor is created on the client; `onMounted` already guarantees that, and `<ClientOnly>` gives you a server-rendered fallback around it.

Does GrapesJS work with Nuxt SSR?

Importing the module is safe on the server — only `init()` requires a DOM. So the surrounding page server-renders normally and the editor appears once the component mounts in the browser.

Is GrapesJS a Vue page builder?

It is a framework-agnostic editing engine, not a Vue library. It becomes a Vue page builder when you mount it in a Vue component and connect it to your own storage and publishing.

How do I integrate GrapesJS with Vue?

Install the package, add a component with a container element, call `grapesjs.init()` in `onMounted` with your plugins and blocks, and call `destroy()` on unmount. The complete guide covers events, composables and wrappers.

Can I use the Composition API?

Yes, and it is the natural fit — the lifecycle hooks are exactly where creation and teardown belong. Hold the instance in `shallowRef` rather than `ref`.

Is there an official Vue wrapper for GrapesJS?

No. There is an official React wrapper, but nothing for Vue; the package on npm targets Vue 2 and has not been updated since 2022. Calling `init()` yourself is about five lines and avoids depending on unmaintained code.

Can I create custom blocks?

Yes. Blocks are registered on the editor's Block Manager with your own markup, label and category, and you can group them however your product's vocabulary works.

Can I create custom components?

Yes. Define your own component types with their own settings, constraints and behaviour, then expose them as blocks. This is how a builder stops looking generic.

Do Vue components render inside the canvas?

No. The canvas is an isolated document rendering plain DOM, so it edits HTML and CSS rather than mounting Vue components. Your application is Vue; the edited page is markup your app can render however it likes.

Can I create reusable templates?

Yes. Save whole layouts as starting points, either through your own storage or with a template management plugin from the catalogue.

Can I save projects to my own backend?

Yes, and that is the intended design. You register a storage adapter with `load` and `store` methods that call your API — the editor never talks to your database directly.

Should I store project JSON or HTML?

Store the project JSON: it is the editable source of truth the editor reloads. Generate HTML and CSS when you publish. Storing only HTML makes the page permanently uneditable.

Can I build a SaaS page builder with Vue?

Yes. Your Vue app handles accounts, plans and routing; the editor handles authoring; your API handles projects. That combination is the common shape for a builder sold as a product.

Can I build a multi-tenant page builder?

Yes, but the tenancy lives in your application and your database, not in the editor. Scope every project, asset and template by tenant and enforce it server-side.

Can I create a white-label page builder?

Yes. Logo, colours, panels, terminology and available blocks are all configuration, so each customer can be given an environment that looks like your product.

Can I build a landing page builder with Vue?

Yes — it is the most common first version. Curate a small set of marketing sections, add templates, and let the marketing team publish through your existing pipeline.

Can I build a CMS editor with Vue?

Yes. Register component types that mirror your content model, so editors work with your entities visually rather than with free-form markup.

Can I extend the editor with plugins?

Yes. A plugin is a function that receives the editor instance, so the whole GJS.Market catalogue works in a Vue app unchanged — there is no Vue-specific edition to look for.

Can I use GrapesJS commercially?

Yes. The core is BSD-3-Clause licensed, which permits commercial use, including inside a product you sell. Check the individual licence of any plugin you install.

Need help building your Vue page builder?

Need help integrating GrapesJS with Vue or Nuxt, creating custom blocks and components, connecting your backend or building a production-ready editing workflow? We do that work.

For teams that would rather ship the product than the editor infrastructure.

Start here

Build your Vue page builder without starting from scratch

Use Vue for your application and GrapesJS for the visual editing experience. Add your own components, blocks, templates, storage and publishing workflow — then extend the builder with GJS.Market plugins when you need more.

Developers

Get started

Five steps and one component. Install the package and have an editor running in your Vue app this afternoon.

Get Started
Product teams

Browse plugins

Blocks, templates, storage, assets and export — install the capabilities you would otherwise put on the roadmap.

Browse Plugins
Companies

Get implementation help

Integration, custom components, backend wiring and a production editing workflow, built with your team.

Talk to us

Your Vue app. Your editor. Your product.