tomatophp/tomato-breeze
Laravel Breeze integration for TomatoPHP that adds ready-made authentication scaffolding—login, registration, password reset, email verification, and profile management—styled for the Tomato admin panel. Skip hand-written auth views and controllers and ship secure, session-based login in minutes.
Treat it as a scaffold you adopt once, not a dependency you upgrade. The install generates auth controllers, routes, views, and Tailwind config into your app. From the moment it's generated, that code is yours. There is no composer update path to upstream fixes — the package's last release was April 2023, so plan to own the fork.
Minimal steps on a throwaway app first:
composer create-project laravel/laravel:^10.0 breeze-spike
cd breeze-spike
composer require tomatophp/tomato-breeze
php artisan list | grep -i breeze # find the installer command name
# run the installer
npm install && npm run dev
Confirm the stack before you commit to anything real: it predates Laravel 11's slimmed skeleton, so assume Laravel 9/10 + PHP 8.1/8.2 + Splade 1.x + Tailwind 3 until a spike proves otherwise.
Where to look first, in order:
routes/auth.php — the entire auth surface you now own. Read it end-to-end before editing.app/Http/Controllers/Auth/* — login, register, password reset, email verification, password confirmation. Verify each matches the current Breeze baseline.dir="rtl" and the dark-mode class strategy actually live. Find the <html> tag and body classes.tailwind.config.js — check darkMode, any RTL plugin, and the content globs (the single most common silent breakage).resources/views/auth/* — the actual screens.First use case: a working authenticated admin shell — register → verify email → log in → edit profile → reset password — rendering correctly in both LTR and RTL under an ar locale, with dark mode toggling cleanly. If all five flows work in both directions and both themes, the scaffold has paid for itself. If any fail, stop and reassess before building product on top.
Day-one vendoring (do not skip):
git add -A
git commit -m "vendor tomato-breeze scaffold (upstream: <sha>)"
composer remove tomatophp/tomato-breeze
Keep the generated code, drop the runtime dependency, tag the upstream commit, and register the fork as self-maintained. An unowned auth fork is how password-reset flows rot.
Publish everything, edit only the copies. Every Breeze-style kit exposes publishable routes, views, and controllers. Publish them into the app namespace first, then make all edits against those copies. If you find yourself patching vendor/tomatophp/..., you've broken the vendoring model and your changes vanish on the next composer install.
Rebrand via tokens, not markup. The value of the scaffold is that the screens already exist. Swap logo, primary color scale, and font through tailwind.config.js and layout components. Half a day of token changes gets you 90% of the perceived customization without forking a single Blade file.
Extend registration without rewriting the flow. Add fields by extending the published RegisteredUserController plus its FormRequest and Blade form. Keep validation in the FormRequest so it stays testable. Do the same for ProfileUpdateRequest when adding avatar/name fields. Leave password-reset and verification controllers alone unless you have no choice — those are the flows most likely to break silently.
RTL is a Tailwind discipline, not a locale flag. Set dir on <html> from a layout variable or middleware, then use logical utilities (ms-*, me-*, ps-*, pe-*) or rtl: / ltr: variants. When you touch a view that has hard-coded ml-*/mr-* or absolute icon positioning, fix that view. Don't schedule a big-bang sweep. Test with real Arabic strings — dir="rtl" on English copy hides the truncation bugs.
Dark mode: tokenize early. If the scaffold sprinkles dark:bg-gray-800 classes, that's fine for v1 but painful at scale. Consolidate into CSS custom properties or a semantic palette (bg-surface, text-muted) so future theme changes are one file, not four hundred class strings. Persist the user's choice in localStorage and apply it with a blocking inline script in <head> — see Gotchas for the FOUC.
Route ownership in one place. Keep the published routes in their own file and require it from bootstrap/app.php (Laravel 11+) or RouteServiceProvider (10 and below). Wrap the authenticated group with your middleware stack and rate limiting there. Apply throttle to the login and password-reset POST routes if the scaffold doesn't already.
Test the four flows — this is non-negotiable. Feature tests for registration, login, email verification (Mail::fake() + assert on the signed URL), and password reset. These are precisely the flows that regress invisibly: RTL and mail-delivery bugs pass CI and fail in a customer's inbox. Add a manual RTL/dark visual pass to your PR template.
Cherry-picking onto an existing Breeze app. If you already ship stock Breeze and only want the RTL/dark value, don't re-scaffold. Lift three things: the Tailwind config changes, the CSS-variable/theme layer, and the layout wrapper's dir/class handling. One to two days captures most of the package's actual differentiation without dragging in Splade.
Post-install hardening pass. Before building product surface, diff the auth controllers against current upstream Laravel Breeze and re-apply security fixes issued since April 2023. Confirm password reset uses hashed tokens with expiry, verification links are signed, and session regeneration happens on login. Treat as a checklist, not a vibe.
Tailwind content globs are the #1 silent breakage. Splade renders vendor Blade views. If those paths aren't in tailwind.config.js content, classes used only in vendor-rendered components get purged and the UI looks almost right — subtly unstyled buttons, wrong spacing. Add ./vendor/prologuephp/**/*.php and ./vendor/tomatophp/**/*.php (plus ./vendor/laravel/framework/... if you use pagination views) and rebuild before debugging anything else.
Don't run alongside tomato-admin (Filament). Two auth front ends, two theming systems, two upgrade tracks, and a confused web.php. Decide which paradigm owns authentication before introducing the second. This is an architectural collision, not an integration task.
Don't co-install with first-party laravel/breeze. Namespace and route-name collisions, duplicated routes/auth.php, and a Tailwind config that fights itself. Pick one, uninstall the other, clear bootstrap/cache.
Laravel 11/12 is a port, not an install. No app/Http/Kernel.php, middleware in bootstrap/app.php, slimmer skeleton, changed signed-URL conventions. If the spike throws missing-class or route-signature errors, that's the porting cost surfacing (~3–5 engineer-days). Decision gate: if porting exceeds ~5 days, lift only the RTL/dark CSS layer onto stock Breeze and hand-build the rest.
Dark mode flashes white on load. If the theme class is applied by Vue or on DOMContentLoaded, users see a flash of light theme. Put a tiny inline <script> in <head> — before the CSS — that reads localStorage and sets the class on <html>. Two lines, eliminates the complaint.
Verification and reset links break on APP_URL mismatch. Behind a proxy, in Docker, or with a different host in APP_URL vs the request host, signed URLs fail validation with a generic 403 that looks like a code bug. Set APP_URL correctly in every environment. When debugging, log the generated URL rather than guessing. Test against your real transport (Mailpit locally, real provider in staging) — flows that work on the log driver sometimes don't on a real one.
RTL regressions don't fail CI. Manual visual pass per release, or wire up a Playwright screenshot diff. Everything else is caught by tests; this isn't.
Auth bugs are quiet. Password reset and verification failures typically surface as a generic redirect or 403, not an exception. Debug order: php artisan route:list --path=auth, then storage/logs/laravel.log, then a throwaway Mail::fake() test to inspect the generated URL, then php artisan config:clear && php artisan view:clear. Stale config after publishing views explains a surprising share of "the change didn't apply."
Pin everything and commit the lock. Splade, Tailwind, Vue, and the Prologue PHP packages move independently. Record a tested version matrix in the repo. An unpinned composer update on an auth scaffold you don't control is how a Friday goes bad.
Zero stars means zero Stack Overflow answers. Every edge case is yours to discover by reading source. Budget for it — the codebase is small and reading the published controllers is faster than searching for a fix that doesn't exist. This is also why the fork-and-own posture matters: there's no community to lean on.
Extension points worth knowing: published views (full control), layout components (theme + direction live here), FormRequests (validation), and the routes file (middleware + rate limiting). Those four cover nearly every customization you'll need. If a change requires reaching outside them, question whether you're using the scaffold as intended.
How can I help you explore Laravel packages today?