liberusoftware/boilerplate-laravel
A Laravel boilerplate package from Liberu Software that provides a reusable application foundation, conventions, and starter structure to help you scaffold and launch new Laravel projects faster.
The boilerplate is a full application, not a library — there is no composer require step to evaluate. Day one is: clone, get it running, then make one feature end-to-end so you learn the conventions you'll be living inside.
Clone and register the site. This project ships with a lerd (Podman-based) environment definition, so use the MCP site tool rather than hand-rolling Docker:
site → action: "list" first to see what's already registered.site → action: "link" for the checkout. Read the reply verbatim; lerd will not auto-start a proxy.command dev server for you (command not approved). If it asks, run lerd link --yes in a terminal.Pick the database before touching .env. A fresh Laravel clone defaults to SQLite. Use db → action: "set" with database: "postgres" (or mysql/mariadb). This persists to .lerd.yaml, rewrites the DB_ keys, starts the service, and creates both the app DB and a _testing sibling.
Configure env, then bootstrap the framework. Order matters:
env → action: "setup" (services, DBs, APP_KEY, APP_URL)framework → action: "setup" — storage link, migrate, seedSkipping the second step is the single most common "why is my DB empty" failure.
Look at the code in this order: routes/, app/Models + policies (Jetstream teams/roles), app/Filament (panels, resources, tenancy wiring), app/Livewire (or app/Http/Livewire), config/fortify.php / config/jetstream.php, config/services.php + Sociallite config.
First real use case: log in, create a Jetstream team, and confirm that team scopes the Filament panel. That single loop exercises auth, tenancy, policies, and Filament's getTenants()/tenant() contract in one go — and tells you whether the boilerplate's tenancy opinion matches yours before you've written 40 resources against it.
Check diag → action: "status" early to learn whether you're in managed DNS mode (*.test + mkcert, TLS available) or disabled mode (*.localhost, no TLS toggling). Every URL and OAuth redirect you write depends on it.
Split the two UIs deliberately. Filament 5 is for CRUD-heavy back-office work (tenant admin, billing admin, support tooling); Livewire 4 components are for bespoke, high-interaction screens inside the Jetstream shell. The failure mode is building everything as a Filament resource "because it's fast" and then fighting panel layouts for a consumer-facing flow.
Tenancy flows through Filament, not around it. Register the Jetstream team as the Filament tenant, then let policies do the scoping. Reach for ->tenant(Team::class) on the panel and per-resource getEloquentQuery() overrides only when the default relationship scoping genuinely doesn't fit — otherwise you get two sources of truth for authorization and an audit nightmare.
Social login is config-plus-provider, not custom middleware. Sociallite wraps Socialite; adding a provider is a services.php entry, credentials, a redirect URI matching your actual host (https://acme.test/auth/{provider}/callback in managed DNS mode), and a provider callback route already registered. Keep credentials in .env.lerd_override (gitignored, wins over lerd defaults) or the real .env for staging, never in committed config.
Workers mirror production concerns. Use the worker tool for queue, horizon (auto-detected when laravel/horizon is installed and it replaces the queue toggle), schedule, and reverb. The vite host worker runs your dev script on the host for HMR — it follows the project's package manager (a packageManager pin wins, then the lockfile), so don't assume npm run dev.
Branch previews come free. Create a git worktree and lerd gives you <branch>.<site>.test with a wildcard cert, seeding vendor/, node_modules/, .env from the main checkout. Combined with .lerd.yaml env_overrides ({{domain}}, {{scheme}}, {{site}}), this is the right way to test multi-tenant routing or per-branch cookies without touching the main site.
Feature work loop I'd actually use:
worktree worker per branch for queue/Horizon so jobs don't cross-contaminate._testing DB that db set created; keep phpunit.xml pointed there.db → snapshot before any destructive migration on shared data; restore is destructive, so snapshot first.service → preset_install for redis, meilisearch, phpmyadmin, stripe-mock rather than writing custom container definitions.Extend via Filament's extension points, not forks. Custom fields → Filament\Forms\Components; repeated admin screens → a shared base resource class in your own namespace. Anything you can keep outside app/Filament and app/Providers/Filament is upstream-mergeable later.
composer.json and treat composer update as a scheduled task, not a habit.runtime → ext_add/ext_remove change one declared set applied to every PHP version. Adding an extension rebuilds one FPM container immediately and the others lazily — so the first request after adding one can be slow enough to look like a hang. Check ext_list before assuming an extension loaded; mongodb needs 8.1+.node -v differs from the container's is nearly always this. Check runtime → node_manager before debugging a build failure.group_assign secondaries inherit TLS from the main. If the main site has TLS, the secondary does too, and tls_disable on the secondary is refused while the main is secured — the main's *.<main> wildcard would answer the subdomain and serve the wrong app. Disable the main first, or don't group at all..test. In disabled DNS mode the TLD is .localhost and TLS toggling doesn't exist. Read diag → action: "status" and drive URLs from APP_URL.link output is the source of truth. It returns lerd link's stdout verbatim and may partially succeed. Re-read it rather than assuming success.Containerfile.lerd, inotify doesn't fire across Podman Machine's virtiofs mount: Vite needs server.watch.usePolling: true, nodemon --legacy-watch, webpack watchOptions.poll. Don't add WORKDIR/COPY to the Containerfile — lerd mounts and sets workdir itself.env → check after pulling upstream. Boilerplates add env keys constantly; env check diffs against .env.example and catches the new STRIPE_*/SOCIALITE_* var before a confusing runtime null..env.lerd_override for personal secrets, and LERD_EXTERNAL_SERVICES=<svc> if you point at a hosted DB you don't want lerd to start. It's gitignored, which is exactly where per-developer credentials belong.app/Providers/Filament, the Jetstream config, and the Sociallite service provider. Keep a local notes file mapping "which package owns which concern" (Jetstream = teams/profile/2FA/API tokens, Sociallite = social auth, Filament = admin, Livewire = custom UI); the overlap is where you'll waste hours.How can I help you explore Laravel packages today?