Shared presets for Pint, PHPStan with Larastan, Rector, ESLint for Vue and Prettier, cut once and worn by every repo in the stack and every app it generates. Your app points at them and adds only its own exceptions.
On Packagist and npm now. The shop is open; walk-ins welcome.
Cut PERSize level 8Lining LarastanFit a11y
Scroll, and the tailor gets to work
The fitting
Walks in
Chalked
Pressed
One PHP class before and after the fitting. Before: the constructor assigns a property by hand, greet() has no return type and its brace on the same line, the array uses array(), and strlen() is given a value that might be null. After: the property is promoted into the constructor, greet() returns string with its brace on its own line, the array is short, and the null case is handled.
As it walked in
final class Greeter{private string $name;1public function __construct(string $name){$this->name = $name;}public function greet()2{3$parts = array('Hello', $this->name)4;return implode(', ', $parts);}public function length(?string $nick): int{return strlen($nick)5;}}
Pressed
final class Greeter{public function __construct(private string $name){}public function greet(): string{$parts = ['Hello', $this->name];return implode(', ', $parts);}public function length(?string $nick): int{return strlen($nick ?? '');}}
AlterationsNo. 0.1
1RectorPromote the property into the constructor.
2RectorAdd the return type, : string.
3PintThe method's brace goes on its own line (PER).
4Rectorarray() becomes [].
5PHPStan · level 8$nick might be null. PHPStan points; you sew the fix.
Pressed0 errors at level 8. Nothing changed but the fit.
Cut from Pinstripe's own test fixtures (raw-messy, rector-old, raw-nullbug), where the real tools run on every composer ci.
Every preset is a piece of the suit
The pieces
Seven measurements, one order card. Status comes straight from BEST_PRACTICES.md: a piece is Enforced when a test runs the real tool and checks both directions.
Seven pins, one cushion.
The cutPint
pint/per.jsonpint/laravel.json
PER for raw PHP, the Laravel preset for Laravel.
Enforced
The inseamPHPStan
phpstan/raw.neonphpstan/laravel.neon
Level 8 for new code. Every ignore needs a comment.
Enforced
The liningLarastan
phpstan/laravel.neon
Sews itself in through the extension installer. No include line to keep.
Enforced
The pressRector
rector/base.php
Reads your PHP floor from your own composer.json. Dead code, code quality, types, early returns.
Enforced
The buttonholesESLint
eslint/javascript.jseslint/typescript.js
Vue 3 recommended plus vuejs-accessibility. Every image gets its alt.
Enforced
The hemPrettier
prettier/index.json
Single quotes, semicolons, 100 columns, trailing commas.
Draft
The chalk lineBaseline
phpstan analyse --generate-baseline
For an existing app: mark the fabric as it is, then take it in every release. Never let it out.
Yours
The hem is still a draft: no test runs Prettier yet, so it is tacked, not sewn.
Every piece has a mirror
A preset without a test is a suit without a mirror: you can't tell when it has gone wrinkled. So each one is tried on twice.
It fits
raw-clean passes Pint and PHPStan
laravel-app passes the Laravel presets
rector-clean is left alone by Rector
clean-js and clean-ts lint clean
It catches
raw-messy fails Pint
raw-nullbug: PHPStan reports the null
rector-old gets altered
an <img> without alt, a v-for without :key
One bolt of cloth, three patterns
Made to measure
Raw PHP, Laravel and Vue each get their own pattern. These are the files your app keeps; each pattern starts with its install line.
Piece A · cut 1
Raw PHP
No framework. Pint with PER, PHPStan at level 8.
Install
composer require --dev waynestate/pinstripe:^0.1
Pinstripe 0.1.0 is on Packagist, so the line carries ^0.1; bump it when a newer version ships.
That's the whole file. Larastan registers itself through phpstan/extension-installer; allow the plugin when Composer asks. Scripts point at pint/laravel.json.
Proven on a minimal Laravel 13 app in the fixtures, every run.
grain
Piece C · cut 1
Vue
ESLint flat config with vuejs-accessibility, Prettier for the layout.
Rector modernises code for the PHP version your app already supports. It reads the floor from your own composer.json, so it can't drift out of step. The press smooths old code to the standard without changing the cut.
It's on the rack now; you can still try Pinstripe on in the shop: clone it and run its own checks. composer ci runs Pint, PHPStan, Larastan and Rector against the fixtures; npm test runs the ESLint presets.
The same commands on Windows, macOS and Linux. You need PHP 8.3 or newer, Composer, and Node 22.13 or newer.
On the cutting table next PREFLIGHT jobs, and reading the PHP floor from CREED. coming soon
Fitting roomany OS
$ git clone https://github.com/waynestate/pinstripe.git
$ cd pinstripe
$ composer install
$ composer ci
$ npm ci
$ npm test
Expect green on PHP 8.3, 8.4 and 8.5.
The whole wardrobe
Worn across the stack
Every repo on this rail, and every app WELD and Sourdough turn out, is cut to Pinstripe.