SplitBillBuddy: The Small PHP App That Treats Shared Money Like a Trust Problem

A plain LAMP-stack expense splitter with transactions, hashed passwords, receipt uploads, and a surprisingly careful model for who owes whom.

7 to 9 min read • View on GitHub • More from Alroy10

A dinner table seen from above. Receipts, a calculator, a phone, and ledger cards are connected by ink lines into a shared accounting system, while one side stays neatly locked and the other side is cluttered with overlapping IOUs. The image explains that the real problem in bill splitting is not arithmetic, but keeping shared money legible and trusted.
SplitBillBuddy is less about splitting a bill than about keeping a group’s money state coherent.
Key Takeaways

Shared money apps fail in boring ways. A receipt disappears, a group gets half-created, a balance does not reconcile, and nobody is sure which number is current. SplitBillBuddy is interesting because it treats those failure modes as the real product problem.

Why bill splitting is really a trust problem

At first glance, this is a utility app for roommates, trips, and small teams. Under the hood, though, it is closer to a trust ledger than a calculator. If a group expense app cannot keep membership, balances, and receipts aligned, the arithmetic is irrelevant.

That is where this repo earns attention. It is a classic PHP and MySQL application, but it makes grown-up choices in the places that matter: authentication, group creation, relational integrity, and file handling. The stack is old school. The discipline is not.

What SplitBillBuddy actually is

SplitBillBuddy is a straightforward web app for tracking shared expenses. Users can register, log in, create or join groups, add expenses, upload receipt images, and see balances rendered on a dashboard with Chart.js. It also includes PDF export for reports, which tells you the project is aiming to be a complete utility, not a demo.

The architecture is intentionally plain. PHP handles request flow, MySQL stores state, vanilla JavaScript covers interaction, and a small set of libraries adds charts and PDF output. There is no framework layer to hide mistakes, which makes the care in the code easier to spot.

The app’s most important feature is consistency

The strongest signal in the repo is the transaction logic in create_group.php. When a group and its member rows must be created together, the code wraps the operation in a database transaction and commits only if every step succeeds. That is the difference between a toy app and software that understands state can break.

The core idea is not division. It is turning one expense into a balanced set of obligations without losing consistency.

$conn->begin_transaction();

try {
    // insert group
    // insert group members
    // verify each step succeeded
    $conn->commit();
} catch (Exception $e) {
    $conn->rollback();
    throw $e;
}

That pattern matters because shared money is a multi-write problem. If one insert lands and the next does not, the app has already lied to the user. The repo avoids that in the one place where it really counts.

The security choices are similarly pragmatic. Passwords are hashed with password_hash(). Sessions gate access. Prepared statements appear in important write paths. There are still inconsistencies in the codebase, but the direction is clearly toward safety rather than convenience.

How the split engine works

The app supports three split types: equal, percentage, and fixed. Equal splits are the simplest, but percentage and fixed splits introduce accounting edge cases. Once you let users define custom weights, the system has to convert those weights into amounts that still reconcile to the original total.

Split typeWhat the app doesWhy it is tricky
EqualDivides the expense across all participantsRounding can leave small residual amounts that still need a rule
PercentageTurns percentages into concrete amountsPercentages must sum cleanly to the bill total
FixedAccepts explicit per-person amountsThe inputs must match the total or the ledger breaks

That is the subtlety most casual expense splitters ignore. A split is not finished when you have numbers on the page. It is finished when the sum of obligations matches the original expense and the ledger still balances.

In other words, the math serves the state model, not the other way around. SplitBillBuddy seems to understand that, which is why it feels more like accounting software than a simple form wizard.

Why the database is both tidy and messy

The schema tells the same story. On the tidy side, the repo uses a normalized group_members table to represent the many-to-many relationship between users and groups. That is the right relational move, and it keeps queries honest.

A split composition shows two database worlds. On the left, tidy nodes labeled users, groups, and group_members are connected by clean lines. On the right, a clipboard-like display stores a comma-separated members field as a shorthand list. The image explains a pragmatic compromise between relational integrity and fast display.
The repo keeps normalized joins for correctness, but also stores a redundant text list for convenience.

On the messy side, the groups table also stores a comma-separated members text field for display. In a stricter design, that redundancy would look suspicious. Here it reads as a pragmatic shortcut: use the join table for truth, and the text field for quick rendering when a simple list is enough.

That compromise is worth calling out because it makes the app feel real. It is not pretending to be pristine. It is trying to be useful while staying readable, which is often how working software actually evolves.

Receipts, uploads, and the dashboard

The expense flow is rounded out by receipt uploads, a dashboard summary, and export tools. Receipt files are stored in an Uploads/ directory with unique names generated by uniqid(), which reduces collisions when multiple users add files at the same time.

The dashboard aggregates spending by member and feeds it into Chart.js. That matters because it turns raw entries into a shared picture of the group. The app is not just collecting data. It is trying to make the group’s state legible at a glance.

PDF export pushes the project one step further. This is not only about recording what happened. It is also about producing something you can save, share, and review later. That is a real utility feature, not decoration.

How it compares to more mature tools

Compared with Splitwise, Venmo-style quick splits, or a typical beginner PHP CRUD app, SplitBillBuddy is smaller, rougher, and far less polished. That is obvious. What matters is what it proves anyway: you can build a credible shared-expenses tool with a classic stack if you respect state, not just screens.

DimensionSplitBillBuddySplitwise / similar products
OwnershipSelf-contained PHP app, easy to understand and adaptPolished product with platform-level maturity
Transaction safetyShows careful transactional thinking in key pathsUsually mature by default, but opaque to the reader
Receipt handlingBasic but functional upload pipelineMore advanced scanning and workflow support
Split logicEqual, percentage, and fixed splitsBroader feature depth and edge-case handling
UX polishSimple and directHighly refined
Educational valueHigh, because the code is visible and readableLower, because the internals are hidden

That comparison is not about winning. It is about category. SplitBillBuddy belongs to the class of open-source utility software that teaches by doing. It does not need a large surface area to be valuable.

What this repo teaches

The lesson here is simple. Use transactions when multiple writes must succeed together. Hash passwords. Prefer prepared statements on the paths that matter. Normalize relationships when the database needs to tell the truth, but do not be afraid of a pragmatic redundancy if it makes the app easier to use.

Most of all, do not confuse a small codebase with a careless one. SplitBillBuddy is small, but it is trying to behave like software that understands money. That is the part worth noticing.