# How to embed a page builder in a React application

*Source: https://www.editorstack.cc/use-cases/embed-page-builder-in-react-app — last updated 2026-09-17. Licensed CC BY 4.0 with attribution to EditorStack.*

## Summary

- For a React application there are four realistic routes: Puck (90.4 kB gzip, editor included), Craft.js (29.2 kB, build the editor yourself), GrapesJS (294.6 kB, framework-agnostic HTML canvas), or a commercial SDK.
- Two questions eliminate most of the field: will your own customers use the editor, and must the output be portable HTML?
- Integration is roughly 8% of the work — asset storage, persistence, permissions and the editor UI are the rest, and they are the same regardless of which library you pick.

## Start with two questions

Most of the field eliminates itself before you compare features.

**Will people outside your organisation use this editor?** If yes, hosted platforms
([Builder.io](/libraries/builder-io), [Plasmic](/libraries/plasmic)) are structurally wrong: their
accounts and branding are the vendor's, and reselling the editing experience is not what they are for.

**Must the output be portable HTML?** If pages must render in an email, on a customer's own hosting,
or in a system you do not control, a React component tree is the wrong storage format and
[GrapesJS](/libraries/grapesjs) becomes the candidate despite being the heaviest.

## The four routes, with measured costs

| Route | Bundle (min+gzip) | Editor UI included | Output |
|---|---|---|---|
| [Puck](/libraries/puck) | 90.4 kB | Yes | Typed JSON of your components |
| [Craft.js](/libraries/craftjs) | 29.2 kB | No | JSON tree of your components |
| [GrapesJS](/libraries/grapesjs) | 294.6 kB | Basic, needs replacing | HTML and CSS |
| Commercial SDK | Vendor-hosted | Yes | Vendor format or HTML |

Bundle figures are from our own [benchmark](/research/bundle-size-benchmark-2026), with React
external for the React-only libraries.

## The recommended default: Puck

For a React product with a design system, Puck is the shortest route to something a customer can use.
You describe each component's editable fields once, and the editor is generated from that description.

```jsx
const config = {
  components: {
    Hero: {
      fields: { title: { type: 'text' }, cta: { type: 'text' } },
      defaultProps: { title: 'Welcome', cta: 'Get started' },
      render: ({ title, cta }) => <HeroSection title={title} cta={cta} />,
    },
  },
};
```

`render` is your production component. That single line is why there is no drift between what the
editor shows and what users see, and why there is no export step to maintain.

In Next.js App Router, the pattern is an editor route that is a client component, and a public route
that server-renders the same data through Puck's `Render`. Page data lives in your database.

## When to choose the others

**Craft.js** when the editor interface has to look like your product rather than like an editor. You
get the drag-and-drop node tree and write everything visible yourself — see
[Puck vs Craft.js](/compare/puck-vs-craftjs) for the honest cost of that choice.

**GrapesJS** when the editor must run outside React, when users need real style control, or when the
output must be HTML — a white-label builder resold to agencies is the classic case.
[GrapesJS vs Puck](/compare/grapesjs-vs-puck) covers the trade, and
[GrapesJS in React](/guides/grapesjs-react-integration) has a tested component for mounting it.

**A commercial SDK** when the timeline is the constraint and the editor is a feature rather than a
differentiator.

## The work nobody puts in the estimate

Integration is the small part. What follows it is the same regardless of library:

- **Asset management** — upload, storage, thumbnails, a picker, quotas. Around 80 hours.
- **Persistence and versioning** — autosave, drafts, publish state, recovery. Around 60 hours.
- **Multi-tenant permissions** — who may edit which page, sharing, roles. Around 60 hours.
- **A block library that matches your product** — around 100 hours, and the thing users judge you on.
- **The editor UI**, if you chose Craft.js or GrapesJS — around 120 hours.

Our [build-versus-buy calculator](/use-cases/build-vs-buy-visual-editor) totals these at roughly 520
hours and lets you uncheck what you already have.

> **Sponsored — GJS.Market:** Skip the block library — Ready-made blocks and templates for GrapesJS — the 100-hour line item, already built. Disclosure: GJS.Market funds this site.

## A realistic sequence

1. Write down who edits and what the output must be. Those two answers pick the library.
2. Build a spike with three real components from your design system, not a demo hero block.
3. Put it in front of one real user before building anything else. Editor projects fail on interaction
   assumptions far more often than on technology.
4. Then build persistence, then assets, then permissions — in that order, because each one is harder
   to retrofit than the last.


## Frequently asked questions

### What is the best page builder library for React?

Puck for most teams: it renders your own React components, ships an editor interface, and stores typed JSON. Craft.js if the editor UI must be entirely yours, and GrapesJS if the editor must also work outside React or emit standalone HTML.

### How do I add a visual editor to Next.js?

Load the editor in a client component with a dynamic import and SSR disabled, keep the public page server-rendered, and store the page data in your own database. Puck's renderer works in server components, which is why it is the smoothest Next.js path.

### How long does it take to embed a page builder?

A working editor takes hours. A customer-facing feature takes months: our estimate is around 520 engineering hours including the editor UI, block library, asset management, persistence, permissions and QA.

### Can I use my existing design system components in the editor?

With Puck and Craft.js, yes — that is their core model. With GrapesJS, not natively: it renders HTML in an iframe canvas, so your React components would need wrapping rather than rendering.

