Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Graper Laravel Package

cybertroniankelvin/graper

Filament plugin that brings a GrapesJS v3 drag‑and‑drop page builder to your admin panel. Create pages with blocks (hero, CTA, testimonials, etc.), edit on-canvas, save to the database, publish by slug, and register your own custom blocks.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation:
    composer require cybertroniankelvin/graper
    php artisan graper:install
    
  2. Register Plugin in app/Providers/Filament/AdminPanelProvider.php:
    public function panel(Panel $panel): Panel {
        return $panel->plugins([
            GraperPlugin::make(),
        ]);
    }
    
  3. Access Editor:
    • Navigate to Pages in Filament sidebar.
    • Create a new page and start dragging blocks (e.g., Hero, CTA) from the left panel.

First Use Case: Marketing Landing Page

  1. Create Page:
    • Title: "Summer Sale 2024"
    • Slug: summer-sale-2024
    • Publish: ✅
  2. Add Blocks:
    • Drag HeroBlock → Add headline, subtext, and CTA button.
    • Drag FeaturesGridBlock → Populate with 3–4 feature cards.
    • Drag Cta50_50Block → Split-screen CTA for "Shop Now" and "Learn More."
  3. Publish:
    • Save → Visit /pages/summer-sale-2024 to preview.

Implementation Patterns

Core Workflows

1. Admin-Driven Page Creation

  • Pattern: Use Filament’s resource interface to manage pages.
  • Steps:
    1. Admins create/edit pages via the Pages resource.
    2. Each page stores html, css, and project_data in the graper_pages table.
    3. Publish/unpublish toggles visibility via is_published.
  • Example:
    // Programmatically create a page
    $page = GraperPage::create([
        'title' => 'Product Launch',
        'slug' => 'product-launch-2024',
        'is_published' => true,
        'html' => '<section class="hero">...</section>',
        'css' => '.hero { background: #ff0000; }',
        'project_data' => json_encode(['blocks' => [...]]),
    ]);
    

2. Custom Block Development

  • Pattern: Extend functionality by registering custom blocks.
  • Steps:
    1. Create a block class (e.g., App\Blocks\ProductCarouselBlock).
    2. Implement required methods (getId(), getTemplate(), etc.).
    3. Register the block in a service provider:
      BlockRegistry::make()->register(ProductCarouselBlock::class);
      
  • Example Block:
    class ProductCarouselBlock extends Block {
        public static function getId(): string => 'product-carousel';
        public static function getName(): string => 'Product Carousel';
        public static function getTemplate(): string {
            return <<<'HTML'
            <div class="carousel">
                @foreach($products as $product)
                    <div class="carousel-item">
                        <img src="{{ $product->image }}" alt="{{ $product->name }}">
                        <h3>{{ $product->name }}</h3>
                    </div>
                @endforeach
            </div>
            HTML;
        }
    }
    

3. Frontend Display

  • Pattern: Render pages via Blade or API endpoints.
  • Options:
    • Blade View:
      @php
          $page = \CybertronianKelvin\Graper\Models\GraperPage::where('slug', 'about')->first();
      @endphp
      <div class="page-content">
          {!! $page->html !!}
          <style>{!! $page->css !!}</style>
      </div>
      
    • API Route:
      Route::get('/landing/{slug}', [GraperPageController::class, 'display']);
      

4. Dynamic Content Injection

  • Pattern: Use project_data to pass dynamic variables to blocks.
  • Steps:
    1. Store data in project_data (JSON field):
      $page->project_data = json_encode([
          'products' => Product::all()->toArray(),
          'promo_code' => 'SUMMER20'
      ]);
      
    2. Reference in block templates:
      public function getTemplate(): string {
          return <<<'HTML'
          <div class="promo-banner">
              Use code: <strong>{{ $promo_code }}</strong>
          </div>
          HTML;
      }
      
    3. Note: Requires custom block logic to parse project_data.

5. A/B Testing

  • Pattern: Duplicate pages with unique slugs and route traffic via:
    • Laravel Middleware:
      public function handle(Request $request, Closure $next) {
          if ($request->user()->is_testing_ab) {
              return redirect()->route('pages.show', 'variant-b');
          }
          return $next($request);
      }
      
    • Query Parameters:
      // Route: /pages/{slug}?variant={variant}
      $variant = $request->query('variant');
      $page = GraperPage::where('slug', $variant ?? $slug)->first();
      

Integration Tips

1. Filament Resource Customization

  • Override the default GraperPageResource by publishing and extending:
    php artisan vendor:publish --tag=graper-config --force
    
  • Modify app/Filament/Resources/GraperPageResource.php to add custom fields or actions.

2. Block-Specific Styling

  • Use Tailwind CSS classes in block templates for consistency:
    public function getTemplate(): string {
        return '<div class="bg-blue-500 text-white p-8">...</div>';
    }
    
  • Override global CSS via the css field in the page model.

3. Media Handling

  • Option 1: Use Filament’s built-in media manager to store images, then reference URLs in blocks:
    public function getTemplate(): string {
        return '<img src="' . $this->getImageUrl() . '" alt="Hero">';
    }
    private function getImageUrl(): string {
        return Storage::disk('public')->url('filament-media/hero.jpg');
    }
    
  • Option 2: Integrate with Spatie Media Library for advanced features.

4. Localization

  • Store translated content in project_data:
    {
        "translations": {
            "en": { "title": "Summer Sale", "cta": "Shop Now" },
            "es": { "title": "Oferta de Verano", "cta": "Comprar Ahora" }
        }
    }
    
  • Dynamically render based on app()->getLocale().

5. Caching

  • Cache published pages for performance:
    $page = Cache::remember("page:{$slug}", now()->addHours(1), function() use ($slug) {
        return GraperPage::where('slug', $slug)->first();
    });
    

Gotchas and Tips

Pitfalls

1. Block Template Escaping

  • Issue: Raw HTML in getTemplate() may expose XSS risks.
  • Fix: Sanitize output or use Blade directives:
    public function getTemplate(): string {
        return <<<'HTML'
        <div>{!! \Illuminate\Support\HtmlString::from($this->getSanitizedContent()) !!}</div>
        HTML;
    }
    

2. CSS Conflicts

  • Issue: Global styles in the css field may override Tailwind or block-specific styles.
  • Fix:
    • Scope CSS to block containers (e.g., .block-hero { ... }).
    • Use !important sparingly; prefer specificity.

3. Dynamic Data in Blocks

  • Issue: project_data is stored as JSON, requiring manual parsing in templates.
  • Fix: Create a helper method in your block class:
    public function getData(): array {
        return json_decode($this->page->project_data ?? '{}', true);
    }
    

4. Route Conflicts

  • Issue: Default /pages/{slug} route may conflict with existing routes.
  • Fix: Configure a custom prefix in config/graper.php:
    'page_route_prefix' => 'marketing', // Now accessible at /marketing/{slug}
    

5. GrapeJS Version Mismatches

6

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky