hi-folks/fusion
Fusion is a Laravel package by hi-folks for merging multiple Laravel applications into one. It helps combine routes, views, migrations, and configs so you can build a modular monolith while keeping each application organized.
composer require hi-folks/fusion
php artisan fusion:start
php artisan fusion:check
fusion:start (new in v1.2.0, and still the intended entry point) creates the content directory if it doesn't exist, inspects it if it does, and prints the next setup steps. Run it before reading any docs — its output is the fastest path to a working install. Then run fusion:check to get a validation report over the content it just resolved; v1.2.1 added deep Markdown validation (opt-in) and JSON output, so this is now the cheapest way to confirm your content parses before you look at a browser.
Then look at, in this order:
config/fusion.php — content directory path, route registration, rendering options, and the cache settings introduced in v1.2.1.curl it or open it in the browser before touching any views, so you know whether a problem is content, config, caching, or presentation.First use case: drop one markdown file with front matter into the content directory, load the route, confirm the page renders and that a fenced code block is highlighted. That exercises the whole pipeline (discovery → parse → highlight → Blade) in about a minute and gives you a baseline for later debugging. Edit the file and reload once — since v1.2.1 parsed content is cached, this also tells you immediately whether your invalidation story is working.
To use a non-default directory:
php artisan fusion:start --dir=docs/content
Markdown is content, config is structure. Keep page copy in the content directory and keep routing/layout decisions in config/fusion.php. Resist the urge to edit Blade views for content changes, and resist hardcoding paths in views for structural changes.
Front matter drives metadata. Put title, order, and layout hints in each file's front matter rather than maintaining a separate index. Adding a page then means adding a file — no registration step, no array to update.
Point the content directory per project. Use --dir during scaffolding, but make the runtime value come from config so it survives deploys:
// config/fusion.php
'content_dir' => env('FUSION_CONTENT_DIR', base_path('content')),
Keeping the CLI flag and the config value aligned is what makes local, CI, and production agree.
Multiple content sets (docs + blog, or per-tenant docs). Use separate directories and resolve the dir at boot rather than mutating config at runtime — config caching will otherwise bite you:
// AppServiceProvider::boot()
config(['fusion.content_dir' => tenant_path('docs')]);
With v1.2.1 caching in play, verify that two tenants resolving different directories don't share cache entries before you ship this; if they do, namespace the cache store or prefix per tenant.
Set the cache lifetime deliberately. v1.2.1 caches parsed Markdown rows in Laravel's configured cache store, with FUSION_CACHE_TTL defaulting to one hour:
// config/fusion.php
'cache_ttl' => env('FUSION_CACHE_TTL', 3600),
Keep it short in local/dev (or clear the cache on content changes) and longer in production where content deploys are deliberate. Whatever you choose, read the README's invalidation section and confirm what actually busts the entry.
Wire setup and validation into onboarding and CI. A single non-interactive line in your setup script removes a whole class of "it doesn't work on my machine" reports:
php artisan fusion:start --dir=docs/content --no-interaction
Then make validation a gate rather than a habit. fusion:check now supports deep validation, JSON output, and --include-valid for full listings — JSON plus an exit-code check is the CI-friendly combination. Add fusion:check-model alongside it: in v1.2.1 it exits non-zero when a model is incompatible with Fusion, so a plain && chain now fails the build correctly. Run without --model it lists the classes it discovered under app/Models, which is a quick way to spot a model that was never picked up; pass --dir if your models live somewhere custom. Note that deep validation is opt-in — decide per project whether you want it gating merges or only producing a report.
Highlighting is a styling contract, not an implementation detail. Since v1.2.0 syntax highlighting comes from tempest/highlight. Ship its theme CSS (or vendor it) as part of your build step so code blocks don't render unstyled in production.
Test the route, not the parser. A feature test asserting 200 on a known docs URL plus one snapshot test of a fixture file with a code fence catches directory, config, caching, and highlighting regressions in a few lines. If you assert on cached output, clear the cache between cases so tests don't leak parsed rows into each other.
fusion:start is interactive. It will hang in Docker builds, CI, or composer create-project hooks. Always pass --no-interaction there.--dir is scaffolding, not a runtime override. It shapes setup and inspection; rendering still follows config. Set both, or set the env var, and expect confusion if you only do one. Same applies to fusion:check-model --dir — it widens the scan, it doesn't change runtime resolution.FUSION_CACHE_TTL low in development if you edit content constantly.0 — verify in the source whether that means "never cache" or "expire immediately" before relying on it.file locally and Redis in production; a shared store means multiple app servers share parsed rows (good), a per-container file store means they don't. Check CACHE_STORE before assuming cache behaviour is consistent across environments.php artisan config:cache (or config:clear locally). A stale cached path is the most common cause of "the directory is right but the pages are empty."fusion:check-model behaviour changed in v1.2.1. It now fails when a model is incompatible, and without --model it lists discovered classes instead of erroring. Any script that piped its output and ignored the exit code may now break your build — usually the desired outcome, but it's a deliberate change worth calling out in your upgrade notes.fusion:start creates it. In containers, create it during build rather than at runtime.spatie/commonmark-highlighter and tempest/highlight emit different markup and class names. If you upgraded from v1.1.x and code blocks look wrong, check your theme/selectors and any tests that assert on rendered HTML — this is the most likely post-upgrade breakage, not a PHP error.composer why spatie/commonmark-highlighter should come back empty.fusion:check flags, and the fusion:check-model changes don't remove configuration or drop older PHP/Laravel versions, so upgrading from v1.2.0 is low risk. Still run your suite on your actual target PHP version rather than assuming parity, and note that caching can surface latent test-order dependencies.php artisan fusion:start first: it reports the directory the package actually resolves. Working backwards from a confirmed path beats guessing at route or config issues. Follow with fusion:check --json to separate "file not found" from "file found but malformed".How can I help you explore Laravel packages today?