xgenious / xgpagebuilder
A powerful and flexible page builder package for Laravel applications
Package info
github.com/XgeniousLLC/xgpagebuilder
Language:JavaScript
pkg:composer/xgenious/xgpagebuilder
Requires
- php: ^8.2
- illuminate/database: ^11.0|^12.0
- illuminate/http: ^11.0|^12.0
- illuminate/routing: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
- illuminate/view: ^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^9.0
- phpunit/phpunit: ^11.0
README
A powerful, self-contained page builder package for Laravel with a modern React frontend. Build beautiful pages with drag-and-drop widgets, extensible architecture, and zero conflicts with your existing application.
Features
- Visual Page Builder — Modern React drag-and-drop interface
- Extensible Widget System — 9+ built-in widgets with easy custom widget creation
- Advanced Styling — Comprehensive style controls with live CSS preview
- Responsive Design — Desktop / Tablet / Mobile preview modes
- Highly Configurable — Works seamlessly with existing Laravel apps
- Performance Optimized — Efficient CSS generation and caching
- Secure — XSS protection and input sanitization
- Self-Contained Assets — Pre-built React assets, no Node.js needed in your host app
Requirements
- PHP: 8.2 or higher
- Laravel: 11.0 or 12.0
- Database: MySQL 5.7+ or PostgreSQL 10+
Installation
Step 1 — Install via Composer
composer require xgenious/xgpagebuilder
Step 2 — Publish config and assets, run migrations
php artisan vendor:publish --tag=page-builder-config php artisan vendor:publish --tag=page-builder-assets php artisan migrate php artisan config:clear
Step 3 — Add columns to your pages table
Create a new migration:
Schema::table('pages', function (Blueprint $table) { $table->boolean('use_page_builder')->default(false); $table->string('page_builder_status')->default('off'); // 'on' or 'off' });
Two flags are needed:
use_page_builder— triggersrenderPage()in the controllerpage_builder_status— gates display in the blade view ('on'= show builder content)
Step 4 — Register the widget view namespace
In app/Providers/AppServiceProvider.php:
public function boot(): void { $this->loadViewsFrom(base_path('plugins/PageBuilder/views'), 'pagebuilder'); }
Adjust the path to wherever your widget blade views live. This is required for view('pagebuilder::...') to work inside widget render() methods.
Step 5 — Add model relationship
// app/Models/Backend/Page.php public function pageBuilderContent() { return $this->hasOne(\Xgenious\PageBuilder\Models\PageBuilderContent::class, 'page_id'); }
Step 6 — Point config to your models
// config/xgpagebuilder.php 'models' => [ 'page' => \App\Models\Backend\Page::class, 'admin' => \App\Models\Backend\Admin::class, ],
Usage
Controller
use Xgenious\PageBuilder\Services\PageBuilderRenderService; public function show($slug) { $page = Page::where('slug', $slug)->firstOrFail(); if ($page->use_page_builder) { $result = app(PageBuilderRenderService::class)->renderPage($page, true); $page->rendered_content = $result['html'] ?? ''; $page->pagebuilder_generated_styles = $result['css'] ?? ''; } return view('frontend.pages.show', compact('page')); }
Always pass
trueas the second argument torenderPage(). Without it, CSS from style fields is silently dropped.
Blade view
@if($page->page_builder_status === 'on') @if(isset($page->rendered_content)) <style>{!! $page->pagebuilder_generated_styles !!}</style> {!! $page->rendered_content !!} @endif @else {!! $page->content !!} @endif
Editor link in admin
@if($page->use_page_builder) <a href="{{ route('admin.page-builder.edit', $page->id) }}" target="_blank"> Open Page Builder </a> @endif
Creating Custom Widgets
namespace Plugins\PageBuilder\Widgets; use Xgenious\PageBuilder\Core\BaseWidget; use Xgenious\PageBuilder\Core\ControlManager; use Xgenious\PageBuilder\Core\FieldManager; use Xgenious\PageBuilder\Core\WidgetCategory; class CallToActionWidget extends BaseWidget { protected function getWidgetType(): string { return 'call_to_action'; } protected function getWidgetName(): string { return 'Call to Action'; } protected function getWidgetIcon(): string|array { return 'las la-bullhorn'; } protected function getCategory(): string { return WidgetCategory::MARKETING; } public function getGeneralFields(): array { $control = new ControlManager(); $control->addGroup('content', 'Content') ->registerField('title', FieldManager::TEXT()->setLabel('Title')->setDefault('Get Started Today')) ->registerField('button_text', FieldManager::TEXT()->setLabel('Button Text')->setDefault('Sign Up')) ->registerField('button_url', FieldManager::URL()->setLabel('Button URL')->setDefault('#')) ->endGroup(); return $control->getFields(); } public function getStyleFields(): array { return []; } public function render(array $settings = []): string { $content = $settings['general']['content'] ?? []; return view('pagebuilder::widgets.cta', [ 'title' => $content['title'] ?? '', 'buttonText' => $content['button_text'] ?? '', 'buttonUrl' => $content['button_url'] ?? '#', ])->render(); } }
Icon format: always use Line Awesome format
'las la-ICONNAME'(e.g.'las la-bullhorn','las la-star').
IMAGE and VIDEO fields return an array
['url' => '...', 'id' => ...], not a plain string. Always extract the URL:$value['url'] ?? ''.
Register in config and clear cache:
// config/xgpagebuilder.php 'custom_widgets' => [ \Plugins\PageBuilder\Widgets\CallToActionWidget::class, ],
php artisan config:clear
See Widget Development Guide for all field types and real-world examples.
Built-in Widgets
- Header Widget — Hero sections with titles, subtitles, and CTAs
- Features Widget — Feature grids with icons and descriptions
- Testimonial Widget — Customer testimonials and reviews
- Image Widget — Responsive images with captions
- Image Gallery Widget — Photo galleries with lightbox
- Video Widget — Embedded videos (YouTube, Vimeo, self-hosted)
- Icon Widget — Icon displays with customization
- Tabs Widget — Tabbed content sections
- Code Widget — Syntax-highlighted code blocks
Documentation
- Setup & Integration Guide — Full installation, configuration, and host-app integration
- Widget Development Guide — Create custom widgets and migrate legacy addons
- Frontend Integration — CSS pipeline, JS, responsive, media library
- Field Reference — All available PHP fields with examples
- Online Documentation — Full documentation website
Quick Links
- Editor URL:
/{route_prefix}/edit/{pageId}(default:/page-builder/edit/{pageId}) - API Endpoints:
/api/page-builder/* - Config file:
config/xgpagebuilder.php
Publishing Options
# Configuration php artisan vendor:publish --tag=page-builder-config # Pre-built frontend assets (required) php artisan vendor:publish --tag=page-builder-assets # Views (for customization) php artisan vendor:publish --tag=page-builder-views # Migrations php artisan vendor:publish --tag=page-builder-migrations
Troubleshooting
Assets 404 (page-builder.js / page-builder.css)
cd vendor/xgenious/xgpagebuilder npm install && npm run build cd ../../.. php artisan vendor:publish --tag=page-builder-assets --force
Assets are published to
public/assets/vendor/page-builder/— not/vendor/page-builder/. nginx commonly blocks/vendor/URL paths as a security rule.
Editor shows blank page
php artisan vendor:publish --tag=page-builder-views --force
php artisan view:clear && php artisan config:clear
Widgets not appearing in sidebar
php artisan config:clear
Verify the widget class is listed in custom_widgets in config and extends BaseWidget.
Content not showing on frontend
- Check
page_builder_statusis'on'for the page - Check
use_page_builderistrue - Verify blade outputs
$page->pagebuilder_generated_stylesin a<style>tag before$page->rendered_content
Route conflicts
// config/xgpagebuilder.php 'route_prefix' => 'admin/page-builder',
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes
- Push to the branch
- Open a Pull Request
License
This package is open-sourced software licensed under the MIT license.
Support
- Email: support@xgenious.com
- Issues: GitHub Issues
Made with ❤️ by Xgenious