koala/content-bundle
Koala ContentBundle is a Symfony bundle for managing structured content in PHP applications. It provides reusable content types, backend administration, and flexible integration with existing Symfony projects, helping teams organize and reuse content without rebuilding core CMS functionality.
This is a Symfony 2 bundle, not a Laravel package — do not attempt composer require. Treat koala/content-bundle as a read-only reference for the inline-edit-over-entity pattern, then port the pattern into Laravel. There is no service provider, facade, Blade views, or Eloquent model here, and the Symfony/PHP constraints will not resolve against any supported Laravel version.
composer.json and read the Symfony, Doctrine, Twig, and PHP constraints. Symfony ^2.3 is incompatible with Laravel's symfony/* ^6/^7 requirements — Composer will fail before any code runs.composer.json — dependency floor and confirmed Symfony 2 targetKoalaContentBundle.php — bundle registration class (no equivalent in Laravel)DependencyInjection/ — configurable entity classes and service wiring; this is where "what's pluggable" is definedResources/config/routing.yml — the exposed save/load routes you'll be re-modelingEntity/ — the content/page persistence model; map these fields to Eloquent migrationsController/ — the editor↔persistence contract (save/load endpoints)Resources/views/ — Twig partials that emit editable region markupResources/public/ — the Mercury Editor JS/CSS payload (do not port this)app/AppKernel.php, import routing, configure Doctrine mapping, run a schema migration, publish assets, and firewall the editor routes.Page model, a ContentBlock model, a Blade partial per editable region, a JSON save endpoint with auth + CSRF + sanitization, and a maintained editor (TipTap, Trix, Editor.js, or ProseMirror). That is the entire first slice; the bundle tells you what the endpoints and region model looked like circa Symfony 2, nothing more.The reusable IP is the data model + interaction contract, not the code. Extract these patterns:
Page and ContentBlock models with explicit title, slug, body (HTML), status, published_at, and timestamps. If the original schema conflates page and block, split them — block reuse is the feature that justified a CMS layer in the first place.data-region="hero.body"). The editor writes to a keyed region, not the whole document; this keeps saves small and conflict-prone edits isolated.POST /pages/{page}/regions/{region} route with a FormRequest, a policy check, and JSON response. This is where the original's value lies — the shape of that contract, not the Symfony controller.{!! !!} — or, better, store structured field JSON and render via Blade components. Do not render raw stored HTML without server-side purification.ContentRevision (page_id, region, body, editor_id, created_at) on save. This gives you an audit trail and a migration story if content moves later.Resources/public/ (Mercury). Wire TipTap/ProseMirror as a Vite entrypoint, initialize it per editable region in a small JS module, and feature-flag inline editing so it can be disabled per environment.ContentRegionService and call it from both the controller and any queue/CLI import path. Keep the editor JS dumb — all validation and sanitization on the server.^2.3 pins are unresolvable against Laravel 9+ (^6.0), Laravel 10 (^6.3), and Laravel 11 (^7.0). This is the first and most likely failure mode.contenteditable, Rangy, and execCommand — deprecated APIs that fail silently or corrupt content on modern browsers. If you port it, you will lose data on save with no error visible to the user.mews/purifier). The original bundle likely lacks this; do not inherit the gap.Gate/policy and CSRF; validate that the editor owns the page before writing a region.opportunity: 0.71 here reflects supply scarcity, not market pull. Do not triage this as a hidden gem; the archived status, 10 stars, and 0 dependents are the real signals.How can I help you explore Laravel packages today?