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

Voyager Pages Laravel Package

pvtl/voyager-pages

A Pages module for Laravel Voyager that adds admin CRUD for managing CMS pages, including titles, slugs, content, and templates, so you can build editable site sections without custom code.

View on GitHub
Deep Wiki
Context7

Getting Started

This is an archived module from January 2020 that adds a CMS-style "Pages" entity to a Voyager admin. Treat it as legacy: verify compatibility before installing rather than after.

  1. Confirm the stack. It targets the Voyager 1.x era (Laravel ~5.6–7, PHP 7.x). On Laravel 8+/PHP 8 you will likely hit Composer constraint conflicts and type-hint errors. Decide up front whether you are pinning an old app or forking the package.
  2. Install alongside an already-working Voyager.
    composer require pvtl/voyager-pages
    
    If resolution fails, pin the last tagged release or a commit, and expect to fork.
  3. Publish and migrate.
    php artisan vendor:publish --provider="Pvtl\VoyagerPages\VoyagerPagesServiceProvider"
    php artisan migrate
    
  4. Register the BREAD so a "Pages" entry appears in the Voyager sidebar — either through Admin → Tools → BREAD, or by seeding the package's BREAD seeder (check database/seeds in the package for the exact class name).
  5. Create your first page in the admin (title, slug, body, optional image/status) and visit the slug in the browser.

Where to look first, in order: the service provider in src/ (it tells you what routes, config, and views are registered), the migration (the column list is the model's contract), the package's routes file (how slugs resolve), then config/voyager-pages.php if present.

First use case: static, editor-owned content — About, Terms, Privacy, landing pages — so marketing can edit copy without a deploy.

Implementation Patterns

Admin-driven content. The normal workflow is: create/edit pages in the Voyager BREAD, publish via a status/active flag, and let the package's slug route resolve them. Keep non-developers in the admin and reserve code changes for templates and new fields.

Programmatic seeding for reproducible environments. Don't hand-create pages in production-only. Seed them with updateOrCreate keyed on slug so staging/prod match and re-runs stay idempotent:

Page::updateOrCreate(
    ['slug' => 'privacy-policy'],
    ['title' => 'Privacy Policy', 'body' => '...', 'status' => 1]
);

Linking. Reference pages by slug in Voyager's menu builder and in Blade via route()/url() against the slug rather than hardcoding paths, so a slug change is a one-line edit.

Template selection. If the package doesn't already support it, add a template column and resolve the view dynamically — this is the cheapest way to get "landing page" vs "legal page" layouts from one BREAD:

return view($page->template ?: 'pages.default', compact('page'));

Rendering overrides. Publish the package views and shadow them under resources/views/vendor/..., or point the slug route at your own controller if you need middleware (auth-gated pages) or shared view data (menus, SEO meta).

Caching. Page lookups are a natural cache target. Cache Page::where('slug', $slug)->first() and bust it from the model's saved/deleted events; tag the cache by slug so invalidation is surgical.

Headless/API use. If you have a SPA, expose the Page model through a small JSON controller rather than rendering Blade — the model is the reusable part; the view layer is the throwaway part.

Gotchas and Tips

  • Archived means frozen. No security patches, no Laravel 8+ support, no PHP 8 fixes. Pin exact versions in composer.json, commit the lock file, and budget for a fork if you need to upgrade the host app.
  • Catch-all route shadowing. A {slug} route will swallow any route registered after it. Ensure the package's route is registered last, or constrain it (->where('slug', '[A-Za-z0-9\-\/]+')) and keep admin, login, api out of the slug space.
  • Nested slugs. Check whether parent/child paths are supported before designing URLs that assume it; a plain {slug} segment won't match slashes without a custom pattern.
  • 404s. Make sure a miss aborts with a real 404 rather than a ModelNotFoundException stack trace, and that unpublished pages are excluded from the query — not just hidden in the view.
  • Route caching. If the package registers closure-based routes, php artisan route:cache will fail in production. Convert to controller actions in your fork if you need it.
  • Images. Voyager media relies on the storage symlink; run php artisan storage:link or page images silently 404.
  • BREAD seeding is not inherently idempotent. Re-running the seeder can duplicate BREAD rows and menu items. Wrap in updateOrCreate before putting it in a deploy pipeline.
  • Config caching. After publishing config, php artisan config:cache in deploys will mask later config edits — clear it during debugging before assuming the package ignores your settings.
  • Translation columns. If you enable Voyager's translatable trait, the stored value may be JSON; querying where('slug', ...) across locales needs care, or you'll get false negatives.
  • Debugging loop: php artisan route:list --path=<slug> to confirm the route exists and its order, php artisan tinker to test the model query directly, then check the published views are actually the ones being rendered.
  • Extension points to prefer over editing vendor code: the service provider's bindings, config-driven model swapping (if present), view overrides, and model events. Never patch vendor/ — fork and use a VCS path repository instead.
  • Strategic call: for a new project, a simple Page model plus a Voyager BREAD takes an afternoon and removes a dead dependency. Adopt this package only where it's already embedded in a legacy app you're maintaining, not modernizing.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route