limenet/laravel-baseline
A Laravel package that provides a reusable baseline for new projects, bundling sensible defaults, common configuration, and setup conventions so you can start from a consistent foundation. It reduces repetitive setup work and keeps applications aligned with limenet's conventions.
limenet/laravel-baseline is a dev-only package that codifies the baseline of quality tooling a Laravel project is expected to have — PHPStan, Rector, Pint, strict types, CI wiring — and lets you assert that baseline programmatically. Day-to-day, you install it, run its check command, and let it tell you which pieces of your tooling setup are missing or misconfigured.
Minimal setup:
composer require --dev limenet/laravel-baseline
php artisan vendor:publish --tag="baseline-config" # verify the exact tag with `php artisan vendor:publish`
Then look at, in this order:
config/baseline.php or similar) — it lists the enabled checks and any per-check options. This is where you will spend 90% of your time.php artisan list — confirm the actual command name (baseline:check, baseline, etc.) rather than assuming; the package's command surface is the primary API.src/Checks/ directory in vendor/limenet/laravel-baseline — each check is a small class with a name and a predicate. Reading three of them tells you the whole contract and how to write your own.First use case: run the command on an existing project and treat the output as a punch list. Most teams' first pass ends with adding a phpstan.neon, a rector.php, a Pint config, and a few lines of CI.
CI gate (the main workflow). Add the check as a step before your test suite so config drift fails fast and cheaply:
- run: composer install --no-interaction --prefer-dist
- run: php artisan baseline:check
- run: vendor/bin/phpstan analyse
- run: vendor/bin/pest
Because the package only inspects files and config, this step costs a second or two — there is no reason to skip it in a matrix build.
Local pre-flight via Composer scripts. Mirror the CI step so developers hit the same wall before pushing:
"scripts": {
"baseline": ["@php artisan baseline:check"],
"check": ["@baseline", "vendor/bin/pint --test", "vendor/bin/phpstan analyse"]
}
Baseline-as-documentation for new projects. When scaffolding a new Laravel app or an internal package skeleton, run the check immediately after laravel new. It doubles as a checklist of "what a finished project looks like here," which is more reliable than a wiki page nobody updates.
Custom checks for house rules. The valuable pattern is extending the package with your organisation's own invariants — "every app has a phpstan.neon that includes the shared config," "no project ships without a .editorconfig." Implement the package's check contract, register the class in the config's check list, and you get consistent output formatting and exit codes for free.
Per-environment / per-path config. Keep the check list identical across environments but vary options (paths to ignore, which tool versions count as acceptable) via env vars read in the config file. Avoid branching the set of checks between local and CI or you will only discover failures on push.
New in 2.18.0 — cache-location checks. The release adds hasRectorConfigWithCache and phpstanHasTmpDir. Both encode a CI-caching concern: if Rector's cache and PHPStan's tmpDir live in the OS temp directory, they are invisible to your CI cache action and get thrown away on every run. The pattern these checks reward is:
// rector.php
return RectorConfig::configure()
->withCache(directory: __DIR__ . '/.rector/cache')
->withPaths([__DIR__ . '/app', __DIR__ . '/src']);
# phpstan.neon
parameters:
tmpDir: .phpstan-cache
…paired with a CI cache step keyed on composer.lock and those directories, and both directories in .gitignore. If you already do this, 2.18.0 is a no-op; if you do not, expect two new failures to appear on upgrade.
2.17.* and migrate deliberately..gitignore and in your CI cache path. Getting one without the other is the classic half-fix: either you commit megabytes of Rector cache, or you configure the directory and still pay full analysis time on every job.tmpDir. If you matrix PHPStan across PHP versions in the same workspace, give each job a distinct tmpDir (e.g. suffix with ${{ matrix.php }}) or the runs will clobber each other and produce confusing partial-result errors.php artisan config:cache in CI will freeze your config. If a check option is env-driven and you cache config before the check runs, the value is whatever was set at cache time. Run the check before caching config, or hard-code CI values.phpunit.xml-driven working directory change, a monorepo subdirectory, or a symlinked path will defeat relative-path assumptions.-v and/or naming a single check to run. Isolate a failing check and read its class source; these predicates are deliberately short and you can usually spot the exact path or key it expects in under a minute.--dry-run-style local workflows.composer.json constraints and upgrade rather than fighting the check.How can I help you explore Laravel packages today?