- Created detailed upgrade log for deversspecialist with phases including Composer updates, Filament upgrades, Tailwind migration, Pest updates, and final verification. - Added upgrade log for goos project, documenting version changes, encountered issues, and resolutions during the migration process. - Documented Composer dependency upgrades for qlshandling, highlighting significant changes and necessary code adjustments. - Introduced a template for future upgrade logs to standardize documentation for Laravel migrations.
34 KiB
Laravel 12 Migration: Problems & Solutions Reference
Compiled from 5 real project migrations (Contentmakers, QLS Handling, Deversspecialist, Cleanshopping, Goos). Intended audience: an AI assistant performing the next Laravel 12 upgrade, or a human developer doing it manually.
How to Use This Document
Read this before starting any Laravel 11 → 12 migration. Every item below is a real, observed problem — not hypothetical. The document is organized by upgrade area. Each entry follows the pattern:
- Problem: what went wrong
- Root Cause: why it happened
- Fix: what resolved it
- Projects affected: which projects hit this issue
Prompt for AI Assistants
Before starting, place these two files in the project root (or provide them in the conversation context):
- This reference document (
Laravel-12-Migration-Problems-and-Solutions.md) - The update log template (
Logs/TEMPLATE.md) — use it as the structure for the new project's update log
Copy-paste this prompt when starting a new project migration with an AI assistant:
Hi, we are going to update to the next version of Laravel and update everything that goes along with it. So please run
composer outdated. Gather all the resources you need to do the updates and then make a plan.There is a file "Laravel 12 Migration: Problems & Solutions Reference.md" — it contains all the errors and weirdness we have encountered in previous updates. Take these things into account if relevant for this project. And make an update log yourself (use the TEMPLATE.md as the structure) so we can later add that to the document for any other projects that need updating.
Then when the Composer work has been done, do
npm outdatedand do the same thing. Gather all the resources, make a plan, and keep track of all the exceptions and log anything out of the ordinary in the same markdown file.If anything is unclear, use the AskUserQuestion skill. When in doubt, ask. Ask about approach, preferences, naming, styling, scope — anything. Multiple questions per interaction are encouraged. Do not assume — confirm with the user first.
Table of Contents
- #Pre-Flight / Preparation
- #Composer & Package Resolution
- #Laravel 12 Breaking Changes
- #Filament v3 → v5
- #Livewire v3 → v4
- #Laravel Passport 12 → 13
- #Tailwind CSS v3 → v4
- #PHPUnit & Pest Upgrades
- #ESLint Migration
- #NPM / Frontend Build
- #Inertia v1 → v2
- #Browser Testing
- #Post-Upgrade Verification Checklist
- #Recommended Upgrade Order
Pre-Flight / Preparation
1. Always clear bootstrap cache after major package changes
Problem: After removing, replacing, or upgrading packages, php artisan commands fail with Class ... ServiceProvider not found errors. Examples: Barryvdh\Debugbar\ServiceProvider, CodeZero\Localizer\LocalizerServiceProvider, Filament\Upgrade\UpgradeServiceProvider.
Root Cause: Stale bootstrap/cache/packages.php and bootstrap/cache/services.php retain references to old/removed service providers.
Fix: Delete both files and re-run discovery:
rm -f bootstrap/cache/packages.php bootstrap/cache/services.php
composer dump-autoload
Rule: Do this after every major Composer operation (package removal, replacement, or major version upgrade).
Projects affected: All 5 projects.
2. Composer cache path issues in sandboxed environments
Problem: composer outdated fails with Cannot create cache directory.
Fix: Run with COMPOSER_CACHE_DIR=/tmp/composer-cache composer outdated.
Projects affected: Deversspecialist.
3. Record baseline test count before starting
Problem: After PHPUnit major upgrades, test counts can silently drop (e.g., 14 → 3) because test discovery rules changed. Without knowing the baseline, this goes unnoticed.
Rule: Before any upgrade work, record the exact test count and assertion count. After each upgrade phase, verify the count has not dropped.
Projects affected: Contentmakers, Goos.
Composer & Package Resolution
4. codezero packages block Laravel 12
Problem: codezero/laravel-localized-routes (^4), codezero/laravel-localizer (^3), and codezero/laravel-uri-translator (^2) all hard-require illuminate/support ^10.0|^11.0. No stable release supports Laravel 12.
Fix:
- Replace
codezero/laravel-localized-routeswithopgginc/codezero-laravel-localized-routes:^5.0(maintained fork, sameCodeZero\LocalizedRoutesnamespace, drop-in replacement). - Remove
codezero/laravel-localizerentirely (typically unused — verifyuse_localizerisfalsein config, or that no PHP code referencesCodeZero\Localizer). - Set
codezero/composer-preload-filestofalseinallow-plugins.
Projects affected: All 5 projects.
5. codezero/composer-preload-files blocks Composer after removal
Problem: After removing codezero packages, the composer-preload-files plugin still exists in vendor as a transitive dependency. Composer refuses to run any command.
Fix: composer config --no-plugins allow-plugins.codezero/composer-preload-files false
Projects affected: Goos, Deversspecialist.
6. Localized routes: /en/ prefix no longer generated after fork switch
Problem: After switching to opgginc/codezero-laravel-localized-routes ^5, English locale redirects lose their /en/ prefix (e.g., /ds instead of /en/ds), even when omitted_locale is set to nl.
Status: Open / needs investigation per project. May be a config difference in the v5 fork.
Projects affected: Goos.
7. resend/resend-laravel must move to ^1.0 for Laravel 12
Problem: resend/resend-laravel ^0.14 or ^0.23 only supports Illuminate 10/11.
Fix: Upgrade to resend/resend-laravel ^1.0. No API changes encountered in practice.
Projects affected: Contentmakers, Deversspecialist.
8. laravel-lang packages need major version bump
Problem: laravel-lang/lang:^12 and laravel-lang/common:^3 are anchored to a publisher line that only supports Illuminate <=11.
Fix: Move to newer major lines compatible with Laravel 12 (check latest available versions at upgrade time).
Projects affected: Contentmakers.
9. Composer post-update-cmd scripts can trigger Filament upgrade side effects
Problem: Running composer require or composer update triggers php artisan filament:upgrade via post-update-cmd, republishing Filament assets and creating large git diffs.
Fix: Treat as expected side effect. Group Filament public-asset changes and commit separately.
Rule: On upgrade branches, assume Composer package changes may create large Filament asset diffs.
Projects affected: Contentmakers.
Laravel 12 Breaking Changes
10. HasUuids generates UUID v7 instead of v4
Problem: HasUuids trait now generates UUID v7 by default. This can break tests or code that expects UUID v4 format.
Fix: Use use HasVersion4Uuids as HasUuids; in affected models (e.g., Attachment, JobApplication).
Projects affected: Deversspecialist.
11. image validation rule excludes SVGs
Problem: The image validation rule no longer accepts SVG files in Laravel 12.
Status: Not encountered in practice across any project, but worth monitoring during testing.
12. route:list can throw due to controller-constructor abort guards
Problem: php artisan route:list --path=admin fails with NotFoundHttpException because the command instantiates controllers during route metadata collection, and some controllers have abort_unless(...) in their constructor.
Fix: Use php artisan about + tests/build for smoke checks instead. Long-term: move hard feature gates out of constructors into middleware.
Rule: Avoid abort_* calls in controller constructors.
Projects affected: Contentmakers.
Filament v3 → v5
You cannot skip v4. Filament must be upgraded v3 → v4 → v5 in sequence. Each step has its own rector script (
vendor/bin/filament-v4,vendor/bin/filament-v5). Running the v5 rector on a v3 codebase will produce incorrect or incomplete results. The v4 rector must run first and the v4 packages must be installed before proceeding to v5.
13. Rector scripts require explicit directory input
Problem: vendor/bin/filament-v4 and vendor/bin/filament-v5 require interactive input (directory prompt). Running without input causes MissingInputException.
Fix: Pipe input: echo "app" | vendor/bin/filament-v4 and echo "modules" | vendor/bin/filament-v4. Run for EACH custom namespace directory separately: app/, cms/, commerce/, modules/, support/, etc.
Rule: Always enumerate all custom source roots before running Filament codemods.
Projects affected: All projects with Filament.
14. Rector scripts miss certain transformations
The rector/codemod tools do not catch everything. The following require manual fixes:
a. Filament\Pages\Actions\* → Filament\Actions\*
Problem: Old action imports remain after rector.
Fix: Grep for use Filament\Pages\Actions; and replace all matches with use Filament\Actions;.
Projects affected: Contentmakers, Deversspecialist, Goos.
b. Filament\Forms\Set|Get → Filament\Schemas\Components\Utilities\Set|Get
Fix: Search and replace across all Filament resource files. Projects affected: Contentmakers, Deversspecialist.
c. Form/Schema layout components moved to Filament\Schemas\...
Problem: Layout/utility classes moved namespaces but rector didn't update all imports. Fix: Migrate these imports:
| Old | New |
|---|---|
Filament\Forms\Components\Fieldset |
Filament\Schemas\Components\Fieldset |
Filament\Forms\Components\Grid |
Filament\Schemas\Components\Grid |
Filament\Forms\Components\Section |
Filament\Schemas\Components\Section |
Filament\Forms\Components\Tabs\Tab |
Filament\Schemas\Components\Tabs\Tab |
Filament\Forms\Components\Component |
Filament\Schemas\Components\Component |
Filament\Forms\Get |
Filament\Schemas\Components\Utilities\Get |
Filament\Forms\Set |
Filament\Schemas\Components\Utilities\Set |
Projects affected: Contentmakers.
d. form(Form $form): Form → form(Schema $schema): Schema
Problem: Partial codemod application leaves old signatures in some resources/relation managers.
Fix: Grep for use Filament\Forms\Form; and remove all remaining occurrences. Update method signatures.
Projects affected: Contentmakers.
e. $navigationGroup and $navigationIcon type changes (Filament v4)
Problem: protected static ?string $navigationGroup must be protected static string | \UnitEnum | null $navigationGroup. Same for $navigationIcon → string | \BackedEnum | null. Rector does NOT catch this.
Fix: Search for protected static ?string $navigationGroup and $navigationIcon and update types manually. Not needed if the project uses method overrides instead of static properties.
Projects affected: Deversspecialist.
15. TextInput\Mask builder class removed
Problem: Legacy closures typed as Forms\Components\TextInput\Mask are invalid in Filament v5.
Fix: Replace with v5-safe numeric/step/prefix configuration. Grep for TextInput\Mask and rewrite.
Projects affected: Contentmakers.
16. Filament v5 Component::$container uninitialized error
Problem: Typed property Filament\Schemas\Components\Component::$container must not be accessed before initialization — thrown when calling getChildComponents() on Filament form components outside a Livewire context (e.g., during frontend page rendering via CMS Block systems).
Root Cause: Filament v5's getChildComponents() creates a Schema wrapper that requires getLivewire(), which fails outside Filament admin panel context.
Fix: Replace getChildComponents() with getDefaultChildComponents() which returns raw component arrays without requiring a Schema/Livewire container. In hasSettings() methods, use the safe getSchemaChildComponents() resolver and treat closure schemas as non-resolvable (false).
Projects affected: Contentmakers, Goos.
17. Field::make() signature change
Problem: make(string $name) changed to make(?string $name = null). Any subclass overriding make() with string $name = '' must update.
Fix: Change to make(?string $name = null) and pass $name ?? '' to parent.
Projects affected: Goos.
18. ViewAction on ListRecords pages crashes in v5
Problem: ViewAction::make() in getHeaderActions() on a list page causes getViewAuthorizationResponse(): Argument #1 ($record) must be of type Model, null given.
Root Cause: In v5, ViewAction tries to authorize against a record, but list pages have no record.
Fix: Replace ViewAction::make() with Action::make('name') for navigation-only header actions.
Projects affected: Goos.
19. Filament v5 evaluates column labels during initialization
Problem: $livewire->tableFilters is null before filters are populated, causing "Trying to access array offset on null" errors when accessed in column labels/formatters.
Fix: Use null-safe access with ?? null or ?? 'default' defaults when accessing filter values in column labels.
Projects affected: Deversspecialist.
20. filament:upgrade creates large public asset diffs
Problem: php artisan filament:upgrade --no-interaction republishes many files under public/js/filament/*, public/css/filament/*, and public/fonts/filament/*.
Fix: Run once per upgrade pass, review/commit asset churn separately. Do not run repeatedly.
Projects affected: Contentmakers, Deversspecialist.
21. Filament v5 rector can print Rector cache deletion errors but still exit successfully
Problem: Commands report Unable to delete ... rector_cached_files ... No such file or directory but finish with success messaging.
Fix: Do not trust command success text alone. Run a post-codemod class-import existence scan and targeted runtime smoke checks.
Projects affected: Contentmakers.
22. Incompatible Filament plugins
Several third-party Filament plugins do not support v4 or v5:
| Plugin | Issue | Fix |
|---|---|---|
awcodes/filament-table-repeater |
No v4/v5 version | Replace with standard Filament\Forms\Components\Repeater |
johncarter/filament-focal-point-picker |
Only supports ^3.0|^4.0 |
Remove, replace with TextInput storing coordinates as string |
filament/spatie-laravel-translatable-plugin |
Deprecated in v4, no v5 | Replace with lara-zeus/spatie-translatable:^2.0 |
Note: lara-zeus/spatie-translatable requires Filament v5 (not v4). If upgrading v3→v4→v5, skip translatable during the v4 step and install with v5.
Projects affected: Deversspecialist, Goos.
23. Post-codemod verification scan
After running all rector/codemod scripts, run these verification commands:
# Check for old Filament namespace imports that rector missed
grep -r "use Filament\\Pages\\Actions;" app/ cms/ commerce/ modules/ support/
grep -r "use Filament\\Forms\\Form;" app/ cms/ commerce/ modules/ support/
grep -r "use Filament\\Forms\\Components\\Fieldset;" app/ cms/ commerce/ modules/ support/
grep -r "use Filament\\Forms\\Get;" app/ cms/ commerce/ modules/ support/
grep -r "use Filament\\Forms\\Set;" app/ cms/ commerce/ modules/ support/
grep -r "TextInput\\Mask" app/ cms/ commerce/ modules/ support/
grep -r "protected static ?string \$navigationGroup" app/ cms/ commerce/ modules/ support/
Livewire v3 → v4
24. Config key renames
| Old Key | New Key |
|---|---|
layout |
component_layout |
lazy_placeholder |
component_placeholder |
Projects affected: QLS Handling.
25. wire:model behavior unchanged (deferred by default)
wire:model without .live works the same in both v3 and v4 (deferred by default). No action needed.
26. Potential gotchas (not encountered but worth knowing)
wire:model.blur/.changebehavior changed: in v4, these modifiers now control client-side state sync timing too. Add.livebefore them for old behavior:wire:model.live.blur.- Component tags must be closed: unclosed
<livewire:component>tags are interpreted as slot content in v4. @livewireStyles/@livewireScripts: still work withinject_assets => true.
Laravel Passport 12 → 13
27. Passport::hashClientSecrets() removed
Secrets are always hashed in v13. Remove all calls to Passport::hashClientSecrets().
Projects affected: QLS Handling.
28. Middleware renamed
| Old | New |
|---|---|
CheckClientCredentials |
CheckToken |
CheckClientCredentialsForAnyScope |
CheckTokenForAnyScope |
CheckScopes |
CheckToken |
CheckForAnyScope |
CheckTokenForAnyScope |
CheckCredentials (abstract) |
ValidateToken |
Projects affected: QLS Handling.
29. ClientRepository::create() now protected
Use named factory methods instead:
| Old | New |
|---|---|
$repo->create(null, $name, '') |
$repo->createClientCredentialsGrantClient($name) |
$repo->createPersonalAccessClient(...) |
$repo->createPersonalAccessGrantClient($name) |
New methods return a Client with $client->plainSecret property containing the unhashed secret.
Projects affected: QLS Handling.
30. setSecretAttribute() removed
Passport 13 uses an Eloquent Attribute mutator that auto-hashes on assignment. Just set $client->secret = $value;.
Projects affected: QLS Handling.
31. No database migration required
Passport 13 is backward compatible with the old schema. ClientRepository::create() auto-detects columns via getColumnListing().
However, the Passport 13 factory writes to new column names, so you may need a custom ClientFactory that maps to the old schema until you migrate to the new schema.
Projects affected: QLS Handling.
32. Config cleanup
Remove deprecated config keys from config/passport.php:
client_uuids— UUIDs are now always usedpersonal_access_client— personal access clients table removed
Projects affected: QLS Handling.
Tailwind CSS v3 → v4
Important
: Tailwind v3 → v4 should be treated as a separate upgrade step, not bundled into a single pass with other changes. The migration touches CSS architecture (PostCSS config, utility directives, theme tokens, custom classes) and frequently produces visual regressions that are invisible to automated tests. A developer must manually check the frontend after migration — open key pages in a browser and compare against the pre-upgrade state. Do not consider this step complete based on
npm run buildsucceeding alone; a green build does not mean the layout is correct.
33. Automated upgrade tool (@tailwindcss/upgrade) often fails
Problem: The upgrade tool fails with:
Cannot destructure property 'negative'(callback-based theme extensions)variants is not a function(third-party plugins like@formkit/themes/tailwindcss)Cannot apply unknown utility class 'pl-container'(@applyreferencing custom classes)- Refuses dirty git state (run with
--force) - Scans backup directories (
node_modules.bak)
Recommended workflow:
- Always try the automated tool first
- If it errors, resolve blockers and re-run (do not immediately switch to manual migration)
- Comment out problematic custom classes temporarily if needed
- Run with
--forceon upgrade branches - Unpack custom-class-in-custom-class patterns to raw utilities before running
Projects affected: Contentmakers, Deversspecialist, Goos.
34. PostCSS plugin package split
Problem: Vite build fails with "trying to use tailwindcss directly as a PostCSS plugin".
Fix: Install @tailwindcss/postcss and update postcss.config.js:
// Old
module.exports = { plugins: { tailwindcss: {}, autoprefixer: {} } }
// New
module.exports = { plugins: { '@tailwindcss/postcss': {} } }
Remove autoprefixer package (no longer needed).
Projects affected: All projects.
35. @layer base → @utility for custom utility classes
Problem: Custom classes defined with @apply inside @layer base {} fail with Cannot apply unknown utility class.
Fix: Convert to @utility blocks instead of @layer base. Expand any custom-class-in-custom-class usage to raw utility classes.
Projects affected: Contentmakers, Deversspecialist, Goos.
36. @import must precede all other statements
Problem: Warning about @import appearing after @theme {}.
Fix: Move all @import statements to the very top of the CSS file, right after @import "tailwindcss".
Projects affected: Deversspecialist, Goos.
37. Tailwind v4 silently overrides custom .container class
Problem: Major frontend layout degradation after upgrade. Tailwind v4 no longer supports corePlugins.container = false from the JS config in CSS-first mode. The core .container utility is generated and overrides the project's custom .container.
Fix: In resources/css/app.css, add:
@source not inline('container');
@source not inline('container!');
Verification: Built CSS should contain only the custom .container rule.
Projects affected: Contentmakers.
38. Remove stale tailwind.config.js after migration
Problem: After migrating to CSS-first config, the old JS config file remains, creating ambiguity.
Fix: After verifying no @config references exist in the CSS, remove tailwind.config.js.
Projects affected: Contentmakers, Deversspecialist, Goos.
39. Blade-injected runtime colors require @theme inline
Problem: Color utilities tied to runtime CSS variables (e.g., from app.blade.php) behave inconsistently.
Fix: Use @theme inline instead of @theme for color tokens that reference runtime CSS variables:
@theme inline {
--color-primary: var(--primary-color);
--color-primary-medium: var(--primary-color);
}
Rule: After migration, grep for custom color utility names and verify each has a corresponding --color-* theme variable.
Projects affected: Contentmakers.
40. Removed TW v3 plugins (now built into v4)
These plugins no longer exist as separate packages in Tailwind v4:
@tailwindcss/forms@tailwindcss/typography@tailwindcss/aspect-ratioautoprefixer
Remove them from devDependencies. Use --force if npm uninstall fails with peer dependency conflicts.
Projects affected: All projects.
41. eslint-plugin-tailwindcss is not Tailwind v4 compatible
Problem: Linting fails with ERR_PACKAGE_PATH_NOT_EXPORTED for tailwindcss/resolveConfig. The plugin requires tailwindcss ^3.4.0.
Fix: Remove eslint-plugin-tailwindcss from devDependencies and ESLint config. TW v4 support is still WIP upstream.
Watch out: If using strixi/laravel-quality or similar packages, they may re-add eslint-plugin-tailwindcss config on composer update. Remove again after Composer operations.
Projects affected: All projects.
PHPUnit & Pest Upgrades
42. PHPUnit 12 drops /** @test */ annotation support
Problem: Tests using /** @test */ doc-comment annotations are silently not discovered. Test count drops without errors.
Fix: Replace all /** @test */ annotations with #[PHPUnit\Framework\Attributes\Test] attribute. Add use PHPUnit\Framework\Attributes\Test; import. Alternatively, prefix methods with test_.
Rule: After PHPUnit major upgrades, always compare test counts to the baseline.
Projects affected: Contentmakers, Goos.
43. Pest v4 requires protected setUp() in TestCase
Problem: Access level to Pest\Concerns\Testable::setUp() must be public (as in class Tests\TestCase) — fatal error on any test run.
Fix: Change public function setUp(): void to protected function setUp(): void in tests/TestCase.php.
Projects affected: Contentmakers, Goos.
44. Pint can break setUp() visibility
Problem: Running vendor/bin/pint can normalize setUp() method visibility in a way that conflicts with the TestCase chain, causing setUp() visibility conflict (must be public).
Fix: Remove no-op setUp() overrides from affected tests. Always re-run tests after Pint on upgrade branches.
Projects affected: Contentmakers.
45. PHPUnit XML config deprecation warning
Problem: Your XML configuration validates against a deprecated schema — non-blocking, cosmetic warning from PHPUnit 12.
Fix: Run --migrate-configuration if desired, or ignore (non-blocking).
Projects affected: Deversspecialist.
46. Hidden regressions surfaced after restoring test discovery
Problem: After fixing @test → #[Test], previously-hidden test failures appear (e.g., Call to undefined function get_classes_in_namespace()).
Fix: Treat newly exposed failures as real upgrade regressions and fix them. Example: add missing helper functions locally if dependencies no longer provide them.
Projects affected: Contentmakers.
ESLint Migration
47. eslint-plugin-vue v10 requires flat config migration
Problem: Linting fails with legacy config errors (plugin:vue/vue3-recommended not found).
Fix: Create eslint.config.cjs (or .mjs) and migrate rules/plugins from .eslintrc.json. Keep ESLint on v9 (v10 may have additional peer compatibility issues with @typescript-eslint v8).
Rule: Treat ESLint plugin major upgrades as config-schema migrations, not package-only updates.
Projects affected: Contentmakers.
48. npm dependency graph deadlock during ESLint upgrades
Problem: npm install fails repeatedly with ERESOLVE could not resolve when upgrading ESLint plugins.
Fix: Regenerate the npm install tree cleanly — remove node_modules and package-lock.json, then reinstall.
Projects affected: Contentmakers.
NPM / Frontend Build
49. Ziggy v2 requires qs-esm npm package
Problem: Vite build fails with Rollup failed to resolve import "qs-esm" from Ziggy v2 JS source.
Fix: npm install qs-esm
Rule: After Ziggy major upgrades, run a full build immediately.
Projects affected: Contentmakers.
50. laravel-vite-plugin v2 requires Vite 7
Problem: npm install fails — laravel-vite-plugin ^2 has peer vite@"^7.0.0".
Fix: Upgrade vite to ^7.0.0. May need --force flag.
Projects affected: Deversspecialist, Goos.
51. Clean npm install can expose missing direct dependencies
Problem: After lock regeneration, Vite build fails resolving packages (e.g., lodash) that were previously available transitively.
Fix: Add missing packages as explicit direct dependencies.
Rule: After lock regeneration, treat unresolved imports as missing direct dependency declarations.
Projects affected: Contentmakers.
52. Duplicate npm dependency entries
Problem: npm warns about removing packages from dependencies in favor of devDependencies (or vice versa).
Fix: Let npm normalize. Avoid duplicating build-only packages across both sections in package.json.
Projects affected: Contentmakers.
53. @vuepic/vue-datepicker v12 breaking changes
Problem: Default export removed; locale and format props changed.
Fix:
// Old
import VueDatePicker from '@vuepic/vue-datepicker'
// New
import { VueDatePicker } from '@vuepic/vue-datepicker'
Additionally:
localeprop now requires a date-fnsLocaleobject instead of a string:import {nl} from "date-fns/locale", change:locale="'nl'"to:locale="nl"formatprop renamed toformatswith sub-properties: changeformat="dd-MM-yyyy"to:formats="{ input: 'dd-MM-yyyy' }"
Projects affected: Deversspecialist.
Inertia v1 → v2
54. SSR config change in vite.config.js
Problem: @inertiajs/server no longer exists in Inertia v2.
Fix: Change ssr.noExternal from ['@inertiajs/server'] to ['@inertiajs/vue3'] in vite.config.js.
Projects affected: Goos.
Browser Testing
55. Pest browser tests need Playwright runtime
Problem: Browser tests fail on clean machines if Playwright browser binaries are not installed.
Fix: After npm install playwright, run npx playwright install (or npx playwright install chromium).
Rule: Include Playwright browser install in local + CI bootstrap.
Projects affected: Contentmakers, Goos.
56. Browser title assertions can be empty on Inertia pages
Problem: <title> can be empty at initial render timing on Inertia pages.
Fix: Use assertSourceHas(...) + smoke assertions instead of strict immediate title assertion.
Projects affected: Contentmakers.
57. assertSee() can fail on non-SSR Inertia pages
Problem: Text is present in response payload but not as immediate visible server-rendered DOM.
Fix: Use assertSourceHas(...) for payload-level assertions on client-rendered Inertia pages. Use assertNoSmoke() to catch JS errors and console logs.
Projects affected: Contentmakers, Goos.
Post-Upgrade Verification Checklist
Run these checks after completing all upgrade phases:
# 1. PHP tests (compare count to baseline!)
php artisan test --compact
# 2. Frontend build
npm run build
# 3. Code style
vendor/bin/pint --dirty
# 4. Filament assets
php artisan filament:upgrade --no-interaction
# 5. Application info
php artisan about
# 6. Remaining outdated packages
composer outdated --direct --format=json
npm outdated --json
# 7. ESLint (if configured)
npx eslint resources/js/app.js resources/js/ssr.js
# 8. Browser tests (if available)
./vendor/bin/pest tests/Browser/
# 9. Filament namespace scan (check for missed rector transforms)
grep -r "use Filament\\Pages\\Actions;" app/ cms/ commerce/ modules/ support/ 2>/dev/null
grep -r "use Filament\\Forms\\Form;" app/ cms/ commerce/ modules/ support/ 2>/dev/null
grep -r "use Filament\\Forms\\Get;" app/ cms/ commerce/ modules/ support/ 2>/dev/null
grep -r "use Filament\\Forms\\Set;" app/ cms/ commerce/ modules/ support/ 2>/dev/null
Note: php artisan route:list may fail if any controller constructor has abort_unless() calls. Use php artisan about instead for a quick framework verification.
Recommended Upgrade Order
Based on experience across all 5 projects, this order minimizes re-work:
- Pre-flight: Create branch, record baseline tests + build status
- Composer blockers: Replace/remove packages that block Laravel 12 (codezero, resend, laravel-lang)
- Laravel 12: Update
laravel/framework ^12+ Symfony packages + debugbar + other direct deps - Clear caches: Delete
bootstrap/cache/packages.phpandservices.php, runcomposer dump-autoload - Verify: Run tests + build
- Filament v3 → v4 → v5: Run rector for each step, for each custom directory. Fix missed transforms manually.
- Verify: Run tests + build
- Tailwind v3 → v4 (separate step, requires developer): Try automated tool first; fall back to manual. Update PostCSS config. Remove old plugins. A developer must visually verify the frontend after this step — open key pages in a browser and compare against the pre-upgrade state. A passing build does not guarantee correct layout.
- Verify: Run tests + build + manual visual check by developer
- Pest/PHPUnit upgrade: Update to Pest v4 / PHPUnit 12. Fix
setUp()visibility,@testannotations. - Verify: Run tests (count must match baseline!)
- NPM major updates: Upgrade remaining frontend packages. Fix breaking import changes.
- Verify: Run build + tests
- ESLint: Handle flat config migration if upgrading ESLint plugins
- Final verification: Full checklist above
- Browser smoke tests: Set up and run browser tests to catch runtime/rendering issues
Packages That Upgraded Cleanly
These packages upgraded without issues across multiple projects. No special handling needed — just update the version constraint and run composer update. Listed here so the AI does not waste time over-researching them.
| Package | Typical Upgrade | Notes |
|---|---|---|
darkaonline/l5-swagger |
9 → 10 | No code changes |
spatie/eloquent-sortable |
4 → 5 | No code changes |
spatie/laravel-data |
4.14 → 4.19 | Minor, constraint relaxation only |
spatie/laravel-medialibrary |
11.17 → 11.18 | Minor |
mollie/laravel-mollie |
3 → 4 | No code changes |
symfony/http-client |
7 → 8 | No code changes (PHP 8.4 already satisfied) |
symfony/mailgun-mailer |
7 → 8 | No code changes |
barryvdh/laravel-debugbar |
3 → 4 | Only issue is stale autoload cache (see #1) |
resend/resend-laravel |
0.x → 1.x | No API changes |
jeffgreco13/filament-breezy |
2 → 3 | Works with Filament v5 |
ariaieboy/filament-currency |
1 → 3 | Works with Filament v5 + Laravel 12 |
amidesfahani/filament-tinyeditor |
3 → 4 | No code changes |
ralphjsmit/laravel-filament-components |
2 → 3 | No code changes |
filament/spatie-laravel-media-library-plugin |
3 → 5 | No code changes |
filament/spatie-laravel-settings-plugin |
3 → 5 | No code changes |
filament/spatie-laravel-tags-plugin |
3 → 5 | No code changes |
nunomaduro/collision |
7 → 8 | No code changes |
laravel/sanctum |
3 → 4 | No code changes |
Projects Covered
| Project | Log File |
|---|---|
| Contentmakers | Logs/upgrade-log-contentmakers.md |
| QLS Handling | Logs/upgrade-log-qlshandling.md |
| Deversspecialist | Logs/upgrade-log-deversspecialist.md, Logs/upgrade-log-deversspecialist-composer.md |
| Cleanshopping | Logs/upgrade-log-cleanshopping.md |
| Goos | Logs/upgrade-log-goos.md |
Last updated: 2026-02-20