Case / shared expense app

Kvitt

Laravel / Vue 3 / PostgreSQL

Kvitt lets a group split expenses, see who owes whom, and settle up with as few payments as possible — instead of everyone having to keep track themselves.

Problem

Splitting expenses in a group often turns into a tangle of small debts crossing between everyone. Without a way to simplify the debts, each person would need to settle with every other person, even when the net result could be handled with a handful of payments.

Solution

I built a Laravel + Inertia + Vue app with groups, expenses with even or custom splits, and a greedy debt-simplification algorithm that repeatedly matches the largest credit against the largest debt until the whole group is settled.

Technical decisions
The debt-simplification algorithm works in integer cents, not floats, to avoid rounding errors that would otherwise creep in across repeated splits.Reminder cooldowns are checked with an atomic conditional UPDATE (WHERE last_reminded_at IS NULL OR < cutoff) instead of read-then-write, to avoid duplicate notifications under concurrent requests.Inertia.js for an SPA feel without building and maintaining a separate API layer.Laravel Wayfinder for typed routes shared between backend and frontend.Pest, Larastan, and Pint in CI via GitHub Actions, pinned to commit SHAs rather than movable tags.
What it shows

The project shows I can solve a real algorithmic problem (debt simplification) and handle race conditions correctly, not just build forms and tables.

Tech
Laravel 13PHP 8.3Inertia.jsVue 3PostgreSQLPestLarastanTailwind v4Render