My Side Project Stack in 2026

I’m currently working on two projects alongside my day job, each with a different stack. One is a fun experiment I built with AI, the other is a SaaS product. Here’s what I’m using and what I’ve learned so far.

The two projects

Cyprus Payroll 2026 is a Vue 3 web app for Cyprus tax compliance that I built as a fun experiment with AI-assisted development. Replaces my old Excel spreadsheet with a type-safe payroll calculator. Fully static, no backend.

ParkMyAWS is a SaaS that helps teams schedule and park unused AWS resources to cut costs. Full-stack Laravel and React, still in development. What matters for this article is the stack choices.

Two very different products, two different stacks, but some shared principles.

Backend: Laravel 12

ParkMyAWS runs on Laravel 12 with PHP 8.5. After 9+ years with Laravel, it’s still my go-to for anything that needs a backend. The ecosystem is mature, the conventions are solid, and I can move fast without fighting the framework.

What I’m using heavily:

  • Action classes for business logic, so no fat controllers and no fat models
  • Queues for all external API operations, because third-party API calls should never block an HTTP request
  • Laravel Cashier with Paddle for subscriptions
  • PHPStan level 9 with 100% type coverage, which catches bugs that tests miss

The Action pattern has been the single biggest improvement to how I write Laravel code. Every meaningful operation is a standalone class with a handle method. I wrote about this in detail here.

Frontend: Vue 3 vs React 19

Cyprus Payroll uses Vue 3 with the Composition API. ParkMyAWS uses React 19 with Inertia.js.

I went with Vue 3 for the payroll app because I wanted something lightweight: no backend, no SSR, just reactive UI on top of pure TypeScript functions. Vue’s Composition API with <script setup> is clean and productive. Pinia for state management is simple and type-safe.

React 19 powers ParkMyAWS via Inertia.js, which gives me server-driven navigation with a React frontend. Laravel and Inertia fit together naturally, so you get the benefits of an SPA without building a separate API.

If I’m honest, both work well. Vue feels lighter for standalone apps. React has a bigger ecosystem when you need specialized components (data tables, charts). I don’t think the framework matters as much as people argue. TypeScript strict mode on both is what actually prevents bugs.

TypeScript: strict mode everywhere

This is the one non-negotiable across both projects. TypeScript in strict mode with no implicit any.

On the PHP side, PHPStan level 9 serves the same purpose. Between the two, I have full type coverage across every line of code in both projects.

Is it slower to write? A bit, at first. But I’ve lost count of how many times the type checker caught something that would have been a runtime error.

Styling: Tailwind CSS 4

Both projects use Tailwind CSS 4 with the new Oxide engine, and shadcn components on both: shadcn-vue for Cyprus Payroll, shadcn/ui for ParkMyAWS.

Tailwind 4 simplified the config (just @import "tailwindcss" in your CSS). The @theme directive for custom values is cleaner than the old tailwind.config.js approach. Dark mode works out of the box.

shadcn sits at the right level of abstraction for me. They’re copy-paste components that I own and can modify, rather than a heavy library with opinions I’ll end up fighting.

Testing: Vitest + Pest

Vitest for the Vue and TypeScript side, Pest PHP for Laravel. Both are fast and expressive.

My coverage targets: 90% minimum overall, 100% for critical business logic. The tax calculator has caught real bugs at bracket boundaries that manual testing would’ve missed, so this isn’t just a vanity metric.

Build & deploy

  • Vite for both frontends, since it’s the default for Vue and Laravel now
  • Vercel for Cyprus Payroll, a static deploy on the free tier
  • A standard VPS for ParkMyAWS, which needs server-side execution
  • GitHub Actions for CI/CD on both

The common thread

Across both projects, the things that matter most are the same:

  • Strict types, meaning TypeScript strict mode and PHPStan level 9
  • Pure functions for core logic: tax calculations, cost calculations, anything that needs to be testable
  • Pre-commit quality gates, so formatting, linting, type-checking and tests all run before every commit
  • Boring technology, executed properly, with no bleeding-edge dependencies and no over-engineering

None of that is exciting, which is rather the point. I’d rather spend the evening building a feature than working out why my tooling stopped agreeing with itself.