Skip to content

RoninForge/roninforge-laravel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

roninforge-laravel

License: MIT

Cursor plugin for Laravel 13.x on PHP 8.3+. Pinned to laravel/framework ^13.0. Teaches the Laravel 11 skeleton (bootstrap/app.php, bootstrap/providers.php, deleted Kernel.php files), the L12 + L13 deltas (Carbon 3 mandatory, casts() method, #[Scope] attribute, Cache::flexible(), automatic eager loading, UUIDv7, image:allow_svg, FrankenPHP-default Octane), and the modern frontend stack (Livewire 4 single-file components without Volt, Inertia 3.1 deferred props, Pest 4 browser testing). Catches 37 LLM regressions with BAD / CORRECT PHP pairs.

The Problem

LLMs trained on Laravel 9 / 10 (and tutorials older than the L11 skeleton flatten) emit code that does not match a fresh L13 install. They write:

  • app/Http/Kernel.php with $middleware / $middlewareGroups arrays (deleted in L11)
  • app/Console/Kernel.php with schedule() (deleted in L11)
  • app/Providers/RouteServiceProvider.php (deleted in L11)
  • app/Repositories/PostRepository.php wrapping Eloquent for no benefit (Otwell, Freek, Spatie all reject this)
  • protected $casts = [...] property instead of the casts() method (the documented shape since L11)
  • scopeActive($query) magic method instead of the #[Scope] attribute (the documented shape since L12)
  • protected $guarded = [] open mass-assignment combined with $request->all()
  • wire:model.defer / wire:model.lazy (Livewire 2 syntax; renamed in v3, default-deferred in v4)
  • class FooTest extends TestCase in a Pest 4 project
  • laravel new myapp --jet / --breeze (flags removed in L12)
  • Carbon 2 method calls (Carbon 3 mandatory in L12+)
  • 'image' validation rule expecting SVG (silently rejected since L12; opt in via image:allow_svg)
  • Cache::remember() on hot reads where Cache::flexible() (stale-while-revalidate) is the right answer
  • Manual with() chains everywhere when Model::automaticallyEagerLoadRelationships() (L12.8+) would cover them
  • octane:install --server=swoole when FrankenPHP is the recommended runtime since 2025
  • laravel/mix in new projects (Vite has been the default since 9.19)
  • Volt installation for fresh L13 + Livewire 4 (not required; SFC is built into v4)
  • Reverb / Pulse described as "beta" (both GA, both ship in starter kits)
  • Inertia v1 patterns with no Inertia::defer, no <WhenVisible>, no prefetch, no polling

Why this plugin (vs the existing community Laravel rule)

A short Laravel rule already lives on cursor.directory. It is shallow and has three structural problems this plugin fixes:

  1. It pins nothing. No PHP version, no Laravel major. Anything from L7 to L12 is "valid" per its rules. This plugin pins laravel/framework ^13.0 on php ^8.3 explicitly.

  2. It actively endorses the Repository pattern verbatim (it includes the recommendation as a positive item). Taylor Otwell on the Maintainable podcast (HN: https://news.ycombinator.com/item?id=45025685), Freek Van der Herten (https://freek.dev/2422-you-might-not-need-a-repository-in-laravel-3-alternatives), and Spatie's house style (https://github.com/spatie/boost-spatie-guidelines) all reject Repository-on-top-of-Eloquent as the most common Laravel over-abstraction. This plugin's laravel-anti-patterns rule entry #4 cites all three by name with URLs and offers Action classes as the idiomatic alternative.

  3. It ships flat .cursorrules text without globs, fixtures, skills, or an agent. This plugin ships:

    • 10 MDC rules with proper globs so the Repository check fires on app/Models/**, the Livewire check on resources/views/livewire/**, etc.
    • 37 documented anti-patterns with BAD / CORRECT PHP pairs (the existing rule has zero)
    • 5 skills: /laravel-new-action, /laravel-new-form-request, /laravel-migrate-v10-to-v13, /laravel-validate, /laravel-n+1-audit
    • 1 reviewer agent with severity grouping (CRITICAL / ERROR / WARN / NIT)
    • 2 fixture projects: correct-sample (gold-standard L13 + PHP 8.3 shape) and anti-pattern-sample (10+ tracked violations, pinned to L10 on purpose)

Install

Copy the rules, skills, and agent into your project's Cursor configuration. Back up your existing files first; cp -r will overwrite same-named rules.

git clone https://github.com/RoninForge/roninforge-laravel.git

# Use -n to avoid clobbering an existing customised rule of the same name.
cp -rn roninforge-laravel/rules/*  your-project/.cursor/rules/
cp -rn roninforge-laravel/skills/* your-project/.cursor/skills/
cp -rn roninforge-laravel/agents/* your-project/.cursor/agents/

Or vendor the whole repo as a git submodule under your-project/.cursor/plugins/. Refer to the Cursor plugin docs for the current global-install path on your Cursor version.

What's Included

Rules (10 files)

Rule Scope (globs) What it does
laravel-anti-patterns **/*.php 37 LLM regressions with BAD / CORRECT PHP pairs. Each entry annotates which Laravel version dropped or renamed the BAD form
laravel-core composer.json,bootstrap/app.php,bootstrap/providers.php,config/**/*.php L11 skeleton: bootstrap/app.php, bootstrap/providers.php, what is and is not in app/, removed config files, install:* commands
laravel-eloquent app/Models/**/*.php,database/migrations/**/*.php NO Repository, casts() method, #[Scope] attribute, strict mode, automatic eager loading, UUIDv7, Carbon 3 immutability, explicit $fillable
laravel-controllers-and-actions app/Http/Controllers/**/*.php,app/Http/Requests/**/*.php,app/Actions/**/*.php Single-action __invoke controllers, Action classes, FormRequest over inline validate, route model binding, JsonResource for APIs
laravel-livewire-volt app/Livewire/**/*.php,resources/views/livewire/**/*.blade.php,resources/views/components/**/*.blade.php Livewire 4 single-file components (no Volt required), default-deferred wire:model, .live opt-in, lifecycle hooks, computed properties, Flux UI
laravel-inertia resources/js/Pages/**/*.{tsx,jsx,vue},resources/js/Components/**/*.{tsx,jsx,vue},app/Http/Controllers/**/*.php Inertia 3.1 Inertia::defer, <Deferred> / <WhenVisible>, link prefetch, usePoll, useForm with processing state
laravel-queues-and-jobs app/Jobs/**/*.php,app/Mail/**/*.php,app/Notifications/**/*.php,routes/console.php ShouldBeUnique vs WithoutOverlapping inside batches, Bus::batch / Bus::chain, Horizon, encrypted payloads, Reverb GA
laravel-testing tests/**/*.php,phpunit.xml,Pest.php,pest.config.* Pest 4 it() / test() / expect(), browser testing replaces Dusk for most cases, fake() patterns, factories, arch tests
laravel-security app/Http/**/*.php,routes/**/*.php,app/Models/**/*.php Explicit $fillable, FormRequest validation, validateSignatures(except: [...]) for UTM safelist, image:allow_svg opt-in, Sanctum, throttle on login
laravel-performance app/**/*.php,routes/**/*.php,config/cache.php,config/octane.php Cache::flexible() SWR, Octane on FrankenPHP, automatic eager loading, strict mode in dev, Vite, Pulse, response cache headers, EXPLAIN

Skills (5 commands)

Skill Command What it does
New Action /laravel-new-action Scaffold an Action class under app/Actions/<Verb><Noun>.php. final readonly, single __invoke, DI constructor, optional DB::transaction wrapper, optional event dispatch. Refuses Repository
New FormRequest /laravel-new-form-request Scaffold a FormRequest with rules() (array form), authorize() (Policy-backed), messages(), prepareForValidation(). Refuses inline $request->validate() for non-trivial inputs
Migrate v10 -> v13 /laravel-migrate-v10-to-v13 Stage-by-stage migration: composer bumps, skeleton flatten (Kernel.php deletes), Eloquent shape updates (casts(), #[Scope]), Carbon 2 -> 3, Mix -> Vite, PHPUnit -> Pest 4, frontend stack
Validate /laravel-validate Run Pint + Larastan + Pest in parallel and grep-audit for tracked anti-patterns: Kernel.php presence, Repository classes, $casts array, scopeXxx(), $guarded = [], wire:model.defer, Mix, Carbon 2, missing strict mode
N+1 Audit /laravel-n+1-audit Enable strict mode, surface offenders via Pulse / Telescope / Debugbar, fix with with() / withCount() / automatic eager loading, confirm with EXPLAIN, add the matching index

Agent (1 subagent)

Agent What it does
laravel-reviewer Reviews Laravel 11/12/13 + PHP 8.3 code by severity. CRITICAL: Repository pattern, $request->all(), $guarded = [], ShouldBeUnique inside batches, regenerated Kernel.php files, PHP 8.1/8.2 pin on L13, webhook handler reading parsed JSON before HMAC. ERROR: $casts property, scopeXxx(), wire:model.defer, PHPUnit in Pest project, Carbon 2 calls, image rule expecting SVG, Mix, Filament 3 form shape. WARN: missing validateSignatures, Cache::remember where flexible fits, Octane defaulting Swoole, missing strict mode, removed config files regenerated. NIT: missing Pulse, missing $hidden, missing Carbon immutable default

Fixtures

tests/fixtures/correct-sample/ is a slim Laravel 13 + PHP 8.3 project demonstrating the gold-standard skeleton: bootstrap/app.php (no Kernel.php files), bootstrap/providers.php (no five-default-providers register), explicit $fillable, casts() method, #[Scope] attribute, single-action invokable controllers, FormRequest-driven validation, Action class instead of Repository, strict mode in dev, automatic eager loading, UUIDv7 primary keys, Carbon immutability, throttled login, signed-URL UTM safelist, Pest 4 feature tests using it() / test() / expect().

tests/fixtures/anti-pattern-sample/ is the inverse. Every file violates a numbered anti-pattern. composer.json pins laravel/framework ^10.0 on purpose so the v10 skeleton (Kernel.php, RouteServiceProvider) is technically valid for that version. Tracked violations: #1 (Http/Kernel.php), #2 (Console/Kernel.php), #3 (RouteServiceProvider), #4 (Repository pattern), #5 ($casts property), #6 (scopeXxx), #9 ($request->all()), #10 (inline validate), #12 (PHPUnit class in Pest project), #20 ($guarded = []), #36 (UUIDv4 PK), plus a #24-variant composer pin combination. The fixture's README maps every violation to file:line.

Versioning

Rules target laravel/framework ^13.0 on php ^8.3. Most patterns work back to L11 with the deltas called out inline (Removed in L11, Renamed in L12, Added in L12.8). Where the rule cites a version (Cache::flexible 11.23, automaticallyEagerLoadRelationships 12.8, casts() method 11.0, #[Scope] attribute 12.0, Reverb GA 1.0, Carbon 3 mandatory 12.0), verify against the changelog for the version you have installed before adopting.

License

MIT - see LICENSE

Links

About

Cursor plugin for Laravel 13.x on PHP 8.3+. Anti-Repository pattern stance. Catches 37 LLM regressions (Kernel.php, $casts array, scopeXxx, wire:model.lazy, Carbon 2 calls, Volt-for-Livewire-4, etc) with BAD/CORRECT pairs.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages