Solo SaaS with Laravel and Nuxt: Five Decisions That Paid Off
Published · Marten Ackermann
Short answer: A solo SaaS lives or dies by decisions that avoid work: separate auth domains instead of role spaghetti, Stripe Cashier instead of homegrown billing, WebSockets for long-running jobs, tests as a default rather than an afterthought — and a static marketing site that never touches the app bundle.
I built PEX — invoicing and time-tracking software for freelancers and agencies: Laravel 11 API, Nuxt 3 app, customer portal, iOS app, marketing site. Alone. These five decisions paid off most clearly.
1. Two auth domains instead of a role matrix
PEX has two fundamentally different user groups: the team writing invoices, and their clients who view and pay invoices in a portal. Instead of squeezing both into one user model with roles, there are two separate guards: Laravel Sanctum for team users, and a dedicated customer guard with bearer tokens for portal clients.
The win: no endpoint can accidentally be reachable by the wrong group — the separation lives in the infrastructure, not in if statements.
2. Stripe Cashier instead of homegrown subscription logic
Building billing yourself is the classic solo trap: proration, failed payments, taxes, dunning. Laravel Cashier covers subscriptions and portal payments; what remains is webhook processing — with retry logic, because webhooks arrive twice, late, or not at all.
Rule of thumb: billing is never the differentiator of a solo product. Buy, don’t build.
3. Make long jobs visible: Horizon + WebSockets
CSV bulk imports in PEX run as background jobs via Laravel Horizon. Progress is streamed live to the frontend over WebSockets (Pusher). That costs one evening of setup and permanently avoids the worst UX there is: a spinner that lies.
4. Tests and CI from day one
53 Pest tests in the backend, Playwright end-to-end tests in the frontend, four GitHub Actions workflows. As a solo developer there is no second pair of eyes — the test suite is the colleague who objects during refactoring. Without it, I could not have rolled out the shadcn/ui migration or larger feature branches calmly.
5. Marketing static, app dynamic
The marketing site is its own Astro 5 site — static HTML, no app framework, perfect Core Web Vitals. The Nuxt app stays a pure client-side application behind the login. The two worlds have opposite requirements (SEO vs. interactivity); forcing them into one framework makes both worse.
Conclusion
None of these decisions is spectacular. That is exactly the point: a solo SaaS rarely fails from a lack of sophistication — it fails from self-inflicted complexity. Each of these five decisions removed complexity before it could exist.
The PEX case study shows what the full system looks like.