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 Core Laravel Package

joy/voyager-core

Core foundation for Joy Voyager, a Laravel admin panel toolkit. Provides shared service providers, configuration, and building blocks for creating and extending Voyager-style admin interfaces in PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

joy/voyager-core is a thin Voyager extension rather than a standalone admin panel — it assumes you already have TCG/Voyager installed and running. Treat it as a "foundation" package that other joy/* modules depend on, so install order matters.

Minimal steps:

  1. Confirm prerequisites. You need a working Voyager install on a Laravel version inside Voyager's supported window (realistically Laravel 8/9). Verify with composer show tcg/voyager before touching anything else.
  2. Install the package:
    composer require joy/voyager-core
    
  3. Publish its assets/config. Because this is a small package with no explicit docs, check the service provider first:
    composer show joy/voyager-core
    grep -R "publishes\|loadViewsFrom\|loadMigrationsFrom" vendor/joy/voyager-core/src
    php artisan vendor:publish --provider="Joy\\VoyagerCore\\VoyagerCoreServiceProvider"
    
  4. Run php artisan migrate if the provider registers migrations, then php artisan vendor:publish --tag=voyager_assets --force and php artisan storage:link if you're rebuilding the admin UI from scratch.
  5. Log into /admin as a Voyager admin user and look for new menu entries or widgets.

Where to look first: the src/VoyagerCoreServiceProvider.php file. In these Voyager add-on packages almost all behavior is registered there — Voyager menu hooks, widget registration, view namespaces, and BREAD-related bindings. Reading that file will tell you exactly what the package actually does within 30 seconds; the README is unlikely to.

First use case: the intended pattern is to install this alongside the rest of the joy/voyager-* family and let it bootstrap shared admin scaffolding (menu registration, common widgets, or base BREAD configuration) so you don't repeat that in every project. If you're using it standalone, verify it isn't a no-op — with 3 stars and zero dependents, it's entirely possible the "module" is mostly a placeholder that other packages in the family actually extend.

Implementation Patterns

Service-provider-first integration. All customization flows through the provider. If you need to add a menu item, register a widget, or override a view, do it in a follow-up provider (AppServiceProvider::boot()) after Voyager has booted, not by editing the vendor package:

// app/Providers/AppServiceProvider.php
public function boot(): void
{
    if (class_exists(\TCG\Voyager\Facades\Voyager::class)) {
        Voyager::addMenuItem('main', [
            'title' => 'Core Settings',
            'route' => 'voyager.core.index',
            // ...
        ]);
    }
}

Compose with sibling modules. The package name implies a family (joy/voyager-core, plus likely joy/voyager-* satellites). Keep this one unmodified and layer your own providers on top, so upgrading becomes composer update joy/* rather than a merge conflict exercise.

BREAD integration. If it exposes BREAD types or custom formfields, register them in config/voyager.php under additional_formfields / additional_media_picker_handlers and then re-run php artisan voyager:admin for the affected table. BREAD definitions are cached; changes to config/voyager.php won't reflect until the admin is regenerated.

Widget/asset registration pattern. For dashboards, register widgets rather than editing Voyager blade views:

Voyager::addWidget(new \Joy\VoyagerCore\Widgets\SomethingWidget());

Keep custom views in resources/views/vendor/voyager-core/ — Voyager's view namespace resolves from the app first, so this is the safe override path.

Testing in isolation. Given the low release cadence, pin the version in composer.json ("joy/voyager-core": "1.0.*" once you know which tag corresponds to 2024-02-24) and add a smoke test that hits /admin after php artisan route:list to catch provider boot failures before deploying.

Gotchas and Tips

Voyager compatibility is the real risk. Voyager itself has been effectively unmaintained for years and struggles past Laravel 9. This package depends on it, so you inherit that ceiling. Before adopting, run composer why-not laravel/framework ^10.0 in the project — if it refuses, expect to pin Laravel 9.

Provider boot order. joy/voyager-core must load after TCG\Voyager\VoyagerServiceProvider if it calls Voyager:: facade methods at boot. Composer auto-discovery usually handles this alphabetically, but if you see Target class [voyager] does not exist or menu items silently missing, manually register the provider in config/app.php with correct ordering rather than relying on discovery.

Asset publishing is destructive. --force on vendor:publish --tag=voyager_assets overwrites any manual edits to /public/vendor/tcg/voyager. If you've customized the admin UI, publish once during setup and never again — prefer view overrides in resources/views/vendor/voyager/.

BREAD cache staleness. After any config or formfield change, clear both Voyager's own caches and Laravel's:

php artisan config:clear
php artisan cache:clear
php artisan view:clear
php artisan voyager:admin <table> --force

Forgetting the voyager:admin step is the #1 source of "my new field doesn't appear."

Near-zero dependents means near-zero tested paths. With 3 stars, 0 dependents, and a single 2024 release, assume the package is untested outside the author's own stack. Read the source end-to-end before trusting it in production — particularly anything that registers routes or touches middleware. If a required feature is missing, fork it into a local packages/ directory via a Composer path repository rather than submitting a PR upstream; you'll likely never get a response.

Extension points are minimal, so add your own. The clean pattern for anything non-trivial is a wrapper trait or your own menu/provider class that uses this package's primitives but doesn't modify them. That way, if the package turns out to be a dead end (which, at this level of activity, is the default assumption), swapping it out is a one-file change.

Debugging tip. If /admin returns a 500 with no stack trace, check storage/logs/laravel.log for a BindingResolutionException on a Voyager class — this is almost always a missing or misordered service provider, not a problem with this package specifically.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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
cgv/localized-resource