harmony-betta/harmony
Harmony is a Laravel package that pulls common application concerns into one cohesive toolkit, keeping configuration, conventions, and everyday utilities consistent across your project. Drop-in install, sensible defaults, and a small API that stays out of your way.
Since 0.7 is the first release with Illuminate support, the package can now be installed and bootstrapped directly inside a Laravel app rather than as a standalone frontend toolkit. The fastest path from zero to a working build:
Install the package as a dev dependency (asset tooling is normally not needed in production):
composer require --dev <vendor>/<package>
The "Add Illuminate Support" fix means the Composer constraints now resolve against your Laravel version; if you previously saw conflicts around illuminate/support, this release is what unblocks you.
Publish the package's config/asset stubs:
php artisan vendor:publish --provider="<Vendor>\<Package>\<Package>ServiceProvider"
Look for a config file (typically config/<package>.php) and a published gulpfile.js / task directory.
Install the Node side:
npm install
Gulp has been upgraded to 4, so ensure your local Node is a version Gulp 4 supports (Node 12+ is the safe modern floor; Node 16/18 is typical on Laravel apps today).
Run the new command:
npm run gulp
This is the headline feature of 0.7 — you no longer have to know the internal task names.
Where to look first: the package service provider (to see what config/assets are merged or published), the published gulpfile.js (to see which tasks the npm run gulp script maps to), and package.json scripts (to confirm the command wiring). First use case: replacing hand-rolled asset compilation tasks with the package's Gulp pipeline inside an existing Laravel app — compile Sass/JS, write to public/, and reference the output from a Blade layout.
Baseline build workflow. Treat npm run gulp as the canonical entry point and wire it into your scripts rather than calling gulp directly:
{
"scripts": {
"dev": "npm run gulp",
"watch": "npm run gulp -- --watch",
"build": "npm run gulp -- --production"
}
}
Keeping your own aliases means the underlying Gulp 4 task names can change without touching CI config.
Environment-aware output. Gulp 4 discourages the old gulp.task('x', ['dep'], fn) syntax in favour of series/parallel. If the published gulpfile exposes composable tasks, prefer branching on an env flag inside the task rather than maintaining separate gulpfile copies per environment:
const isProd = process.env.NODE_ENV === 'production';
// minify / sourcemaps / hashing gated on isProd
Coexistence with Laravel Mix. If the host app already uses Mix/Vite, do not let both pipelines write to the same public/ paths. Namespace the package's output (e.g. public/vendor/<package>/) or scope the Gulp tasks to only the assets the package owns. This is the single most common integration failure when dropping a Gulp-based package into a Vite-era Laravel app.
Artisan-driven convenience. With Illuminate support in place, wrap the npm invocation in a small Artisan command or a Composer script so backend developers never need to remember the Node incantation:
// app/Console/Commands/BuildAssets.php
return $this->process ?: Process::forever()->run('npm run build', fn ($type, $out) => $this->output->write($out));
Or simply add it to composer.json:
"scripts": {
"post-install-cmd": ["@php artisan vendor:publish --tag=<package>-assets --force"],
"assets": ["npm run build"]
}
CI integration. Install Node before the Composer step, cache ~/.npm and node_modules, and run npm ci && npm run build as a discrete stage. Because the package now depends on Illuminate, the PHP and Node toolchains must both be present in the build image — previously a pure-Node build may have sufficed.
Config-driven task selection. Read the package config from a task runner wrapper or a small PHP command that emits env vars, so per-environment task selection lives in PHP config (which Laravel developers already understand) rather than duplicated JS.
Gulp 4 is a breaking change, not just a security bump. The release note frames it as fixing the Gulp 3 vulnerability, but Gulp 4 changes the task API:
gulp.task('name', ['dep'], fn) no longer works — migrate to gulp.series(...) / gulp.parallel(...).gulp-util was removed from the ecosystem — audit any custom tasks copied from Gulp 3 tutorials.If you had a locally customised gulpfile from a pre-0.7 install, do not blindly re-publish — diff the new gulpfile against yours and port your customisations onto the Gulp 4 structure.
Don't overwrite your gulpfile on upgrade. vendor:publish --force will clobber local task customisations. Check what the publish tag covers before forcing, and keep app-specific tasks in a separate gulpfile.local.js or a tasks/ directory that the package's gulpfile requires.
Node/npm version pinning. Gulp 4 plus a fresh npm install can surface peer-dependency errors (ERESOLVE). Pin Node with .nvmrc and use npm ci in CI. If you hit resolution conflicts from legacy plugins, --legacy-peer-deps is a stopgap, not a fix — note it in the repo so the next developer understands why it's there.
Composer constraint resolution. The Illuminate support fix may still produce conflicts if the package pins a narrow illuminate/support range. After upgrading, run composer why-not <vendor>/<package> <version> if the install refuses to resolve, and check whether your Laravel version is inside the newly added constraint.
npm run gulp is a thin alias. The new command is convenience, not a new API — it will fail if node_modules isn't installed. Guard scripts that assume it works (e.g. deploy hooks) with an npm ci step first.
Debugging the pipeline.
npx gulp --tasks lists the resolved task tree — the quickest way to confirm the package registered its tasks after an upgrade.npx gulp --tasks-simple gives a flat list for scripting.dest paths in the gulpfile against where Blade actually references them; stale output usually means the package writes to a different directory than the app expects.Extension points to prefer. Rather than editing published files, look for: (a) a config array of source/destination globs, (b) a tasks/ directory the gulpfile globs over, or (c) an env-var hook for NODE_ENV. Any of these survive a package upgrade; a forked gulpfile does not. If the package offers none of these, that's the first thing to request upstream — and the reason to keep your customisations in a separate file until it does.
Upgrade checklist for 0.7: confirm Node version → reinstall node_modules cleanly → diff published gulpfile → run npx gulp --tasks → verify asset paths → run npm run gulp and a production build in CI.
How can I help you explore Laravel packages today?