Skip to content

This guide will walk you through creating custom components that can be injected into the Vue Website Page Builder.

Custom Layout Builder

Quick Setup

Begin by creating a ComponentsPageBuilder folder in your project to organize your customizable components:

your-project/
├── src/
│   └── ComponentsPageBuilder/
│       ├── YourCustomBuilderComponents.vue

If you want to use your own components—whether custom-designed or tailored to your application's needs—you can inject them directly into the builder.

  • Create a ComponentsPageBuilder folder in your project for your custom components.
  • (Optional) Use a modal to let users browse and select custom components.
  • Pass your custom component to the builder using the :CustomBuilderComponents prop.
  • When a user selects or drops a component from your custom component picker, inject it into the builder using a function like injectComponentToBuilder. See the example below for implementation details.
vue
<script setup>
import { getPageBuilder, usePageBuilderModal } from '@myissue/vue-website-page-builder'
import YourCustomBuilderComponents from './ComponentsPageBuilder/YourCustomBuilderComponents.vue'

// Retrieve Page Builder service instance
const pageBuilderService = getPageBuilder()
const { closeAddComponentModal } = usePageBuilderModal()

const injectComponentToBuilder = async function (componentObject) {
  const component = {
    // ID will be auto-generated by the Page Builder
    id: null,
    html_code: componentObject.html_code,
    title: componentObject.title,
  }

  await pageBuilderService.addComponent(component)
  closeAddComponentModal()
}
</script>

<template>
  <div>
    <PageBuilder :CustomBuilderComponents="YourCustomBuilderComponents" />
  </div>
</template>

How Should the Components Array Look?

Each custom component you inject must be represented as an object with the following structure.
The Page Builder relies on a <section></section> wrapper to correctly render each component and attach event listeners.

  • Required: The HTML for each component must be wrapped inside a <section>...</section>. The builder uses this tag to identify and manage components.
  • Tip: For optimal responsive layouts, wrap your component content inside:
html
<section>
  <div class="relative py-4">
    <div class="mx-auto max-w-7xl lg:px-4 px-2">
      <!-- Your content here -->
    </div>
  </div>
</section>

TypeScript interface for reference:

typescript
interface Component {
  html_code: string
  id: string | null
  title: string
}

const components: Component[] = [
  {
    html_code: `<section><div class="relative py-4"><div class="mx-auto max-w-7xl lg:px-4 px-2"><div class="break-words"><h2>This is a component</h2></div></div></div></section>`,
    id: null,
    title: 'Header Example One',
  },
  {
    html_code: `<section><div class="relative py-4"><div class="mx-auto max-w-7xl lg:px-4 px-2"><div class="break-words"><h2>This is another component</h2></div></div></div></section>`,
    id: null,
    title: 'Header Example Two',
  },
]

Benefits of this Approach

Full Control: Decide exactly where and when to create components within your application.
Flexible: Easily adapt to any project structure or workflow.
Secure: No postinstall scripts or hidden dependencies—just clean, safe code.
Simple: Lightweight package with straightforward, well-documented setup.
Optional: Only create and use the components you actually need—nothing extra.

Released under the MIT License.