stolz/assets
stolz/assets is a lightweight Laravel asset manager for defining CSS and JavaScript collections, managing dependencies, and rendering them with Blade directives. It supports asset versioning/cache busting and optional minification, simplifying frontend asset organization without a heavy build pipeli...
Install
composer require stolz/assets
Laravel wiring
On Laravel 5.5+ the service provider is auto-discovered. On older versions add it manually in config/app.php:
'providers' => [
Stolz\Assets\Laravel\ServiceProvider::class,
],
'aliases' => [
'Assets' => Stolz\Assets\Laravel\Facade::class,
],
Publish the config and trim it to what you actually use:
php artisan vendor:publish --provider="Stolz\Assets\Laravel\ServiceProvider"
// config/assets.php (essentials)
return [
'public_dir' => public_path(),
'css_dir' => 'css',
'js_dir' => 'js',
'engine' => 'Laravel',
'minify' => env('ASSETS_MINIFY', false),
];
First use case — replace a pile of hand-written <link>/<script> tags in layouts/app.blade.php:
<head>
{!! Assets::add('vendor.css')->add('app.css')->css() !!}
</head>
<body>
...
{!! Assets::add('app.js')->js() !!}
</body>
That single change gives you ordered output, optional concatenation/minification, and one place to add per-page assets.
Where to look first
README.md — the API is small; the examples are the real documentation.config/assets.php — directory mapping, collections, minify/pipeline switches.src/Manager.php — the fluent add()/css()/js()/render() surface and how groups are stored.src/Laravel/ServiceProvider.php + facade — what is bound as a singleton (this matters later).tests/ — the fastest way to see edge-case behavior for missing files and groups.Layout renders, views register. Because Blade executes the child view before the layout, a page view can call Assets::add('js/charts.js') and the layout’s Assets::js() will still pick it up. Use this instead of @push/@stack if you want a single asset pipeline for the whole app.
{{-- resources/views/reports/show.blade.php --}}
@php Assets::add('vendor/chart.js')->add('js/reports.js'); @endphp
Groups for <head> vs. end-of-body. Keep CSS and JS in separate buckets so you don’t have to split the layout manually:
Assets::group('head')->add('app.css');
Assets::group('body')->add('app.js');
{!! Assets::render('head') !!}
...
{!! Assets::render('body') !!}
Collections for vendor bundles. Define repeatable bundles once in config, then add them by name in views. This is the cleanest way to bump jQuery/Bootstrap versions in one place.
'collections' => [
'vendor' => ['jquery.min.js', 'bootstrap.min.js'],
'vendor-css' => ['bootstrap.min.css'],
],
Environment-aware minification. Enable minify only in production; keep it off locally so you can debug unminified output. Prefer a dedicated env var so you can toggle it without a deploy:
'minify' => env('ASSETS_MINIFY', app()->environment('production')),
Version your URLs. This package predates content-hashed filenames. Append a cache-buster yourself (from filemtime() or a deploy tag) when generating tags, otherwise browsers will happily cache CSS/JS across releases.
Keep it isolated from Vite/Mix. Don’t let two asset systems write into the same layout. If the project uses Vite, use this package only for legacy pages served outside the Vite entry points, and keep the two code paths clearly separated in the layout.
Testing. In feature tests, assert against rendered HTML (assertSee('css/app.css')). Because the manager is typically a container singleton, remember to reset it between requests.
css()/js()/render() return HTML, so they must be echoed with {!! !!}. Using {{ }} produces visible escaped tags — the most common first-day mistake.css_dir/js_dir or a filename typo usually yields a perfectly valid <link> to a 404, not an exception. Add a smoke test that asserts every registered asset exists under public_dir.app.js needs jQuery, add jQuery first explicitly (or bundle both in a collection) — the package will not infer it.add() calls. In PHPUnit this can bleed between tests; under Laravel Octane it can bleed between requests. Flush/reset the instance in tearDown() or on each request boundary.APP_URL, the links will be wrong even though the files exist. Verify with curl against the generated URL, not just the filesystem path.import, .mjs, TypeScript, or PostCSS. For any modern frontend, keep Vite/Mix; use this only for plain assets.render() output, confirm the exact <link>/<script> attributes, check the file exists at public_dir/css_dir/..., then check the served URL returns 200. That sequence isolates almost every failure quickly.How can I help you explore Laravel packages today?