Weave 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

Content Sections Laravel Package

capell-app/content-sections

A Laravel package from Capell for creating and managing reusable content sections across your application. Define structured content blocks once, then render them anywhere to keep layouts consistent and content easily editable through the CMS.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install into an existing Capell app, not standalone. composer require capell-app/content-sections only makes sense after capell-app/capell is installed and booted — this package is a section-type library layered on Capell's blueprint/content model, not a CMS in itself. If you don't have Capell running, stop here and evaluate the core package first.
  • Publish, migrate, then read the config. Run the vendor publishes for config, migrations, and views, then php artisan migrate. Open config/content-sections.php before writing a line of code: the list of registered section types (hero, FAQ, pricing, team, comparison, …) is the map of what you get and the template for what you'll add.
  • Look at a shipped section class and its Blade view first. Pick the simplest one (hero), read the class (fields + view), then the view (markup + data access). That pair teaches you the package's whole contract faster than any README: fields in the blueprint, data out of the model, markup in a namespaced view.
  • First use case — override, don't build. Add a hero section to a page in the Capell admin, save it, and confirm it renders on the front end. Then immediately publish/override the hero view in your theme and change one visible thing. That proves the render path, the view namespace, and your override strategy in about ten minutes — which is the actual install validation.
  • Second use case — clone a shipped type. Copy the FAQ section class into your app namespace, rename it, register it in config, and confirm it appears in the editor. This is the day-to-day extension motion for the whole package; do it once deliberately before you need it under deadline.

Implementation Patterns

  • Treat the config registry as the source of truth for "what editors can pick." Every section type is a class with fields and a view, mapped in config. Adding a type = write the class, write the view, add a config entry. Never branch on section type in a page template or hardcode markup elsewhere; the registry should be the only place the set of types is enumerated.
  • Render pages with a single dumb loop. The page template should do nothing but iterate ordered sections and delegate:
@foreach ($page->sections as $section)
    @include('content-sections::sections.' . $section->type, ['data' => $section->data])
@endforeach

Keeping the loop trivial means a new section type never requires touching page templates — which is the entire value proposition.

  • Override views per type, not globally. Point your custom section class at your own view (resources/views/sections/hero.blade.php) rather than editing or re-publishing vendor Blade. If you must override a shipped type, do it via published views in your theme and record which ones you've overridden — see the gotchas.
  • Model repeated content as typed item arrays, and validate the shape on save. FAQ items, team members, pricing tiers, and comparison rows are all "array of small structs inside the section's JSON." Cast the data column to array, validate the item shape in the form/save path, and give the Blade view a defensive default ($data['items'] ?? []). Malformed JSON that reaches a view produces a confusing Blade error instead of a validation message.
  • Prefer shipped types over custom ones until they don't fit. Hero, FAQ, pricing, team, and comparison cover most marketing/editorial pages. Every custom type is a permanent template you owe the content team; the shipped set is the cheap 80%.
  • Filament wiring: expose page sections through a relation manager with a reorderable table (type, summary, order) and the type's own field schema in the form. Because the picker is config-driven, new types surface automatically — resist adding bespoke admin UI per type.
  • Separate global/reusable sections from page-scoped ones. Global CTA bands, headers, and footers should live in their own grouping or a dedicated singleton page so an editor editing a landing page can't silently rewrite a sitewide block.
  • Test by rendering every registered type with fixture data. One Pest test that loops the config registry, instantiates each type with minimal valid data, and asserts a 200 + a known string is the cheapest possible guard against a broken view registration reaching production — and doubles as your upgrade canary.
it('renders every registered section type', function (string $type) {
    $section = Section::factory()->ofType($type)->create();
    $this->get($section->page->url)->assertOk();
})->with(fn () => array_keys(config('content-sections.types')));

Gotchas and Tips

  • Config cache is the #1 "my new section doesn't appear" cause. After adding a type to content-sections.php, php artisan config:clear locally and make sure deploys run config:cache. Verify the type is in the cached config, not just the file.
  • Published views go stale after upgrades. Republishing views overwrites your overrides; not republishing means you miss upstream markup fixes. Keep an explicit list of overridden views, diff the vendor views on each bump, and re-publish selectively. This is the main long-term maintenance tax of the package.
  • Schema changes have no migration. Changing a section's fields doesn't rewrite existing JSON rows. Old sections will render with missing keys. Plan a backfill command (or a render-time default) for any field you add or rename, and never assume $data['x'] exists.
  • Ordering must be atomic. Reorder writes touching multiple rows should go through the package's ordering helper or a transaction; a partially applied reorder produces duplicate or skipped positions that are annoying to diagnose from the editor UI.
  • Eager-load what sections touch. Sections commonly reference media or related models; rendering a page of ten sections can quietly become dozens of queries. Add the relations to the page load, not inside the section views.
  • Don't delete a type from config while content references it. Rows become orphans and either disappear or throw on render. Deprecate by hiding the type from the picker first, migrate the content, then remove the class.
  • Markup and theme CSS are coupled. Overriding a section view means inheriting responsibility for the theme's classes and spacing. Changing the wrapper markup of a shipped section is a design change, not a template tweak — check it visually, not just in tests.
  • Validate on save, render defensively. Any editor-supplied value can be absent, empty, or the wrong shape. Rich-text fields in particular should be sanitized at save time; don't trust the JSON because it came through Filament.
  • Dependency hygiene. Zero stars, single maintainer, frequent patch releases with empty changelog bodies — pin ^1.0 (or ~1.0), read the commit diff rather than the release notes before bumping, and keep your custom types in your own namespace so a fork-and-replace stays a few hundred lines of work. Your per-type render test suite is the thing that makes those upgrades safe; build it before you have twenty section types in production.
  • Check names against source. Class names, the config key shape, and the view namespace are not well documented upstream — confirm them from the service provider and an existing section class rather than assuming from these patterns.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console