Can AI build a free app to split expenses with friends?
Yes. An AI coding tool can build a simple page where you enter who paid what and it shows who owes whom, with no account or subscription.
01Why bot
- The math is simple and easy to test.
- A single-page app works on any phone.
- Syncing across everyone's phones needs a backend.
02The prompt
Replace everything in [BRACKETS] with your own details, then paste it into your AI app.
You are a web developer. Build an expense splitter. Features: add people, add expenses (who paid, amount, who shares), show balances and the fewest payments to settle. Requirements: - MUST be a single index.html file, mobile-first, saving data only in the browser. - MUST round to cents and make balances add to zero. - MUST include a 'copy summary' button. - Don't add features I didn't list. Then give me steps to publish it free and 3 test cases to check the math.
03Steps
- Run the prompt in an AI coding tool.
- Test it with the 3 cases.
- Share the link with your group.
04What can go wrong
- Browser-only data can be lost if you clear storage.
- Double-check totals on big trips.
05What to use
06Our test runs
2 runs, each with a different made-up sample. 2 of 2 passed every check.
The made-up sample:
This prompt has nothing to fill in.
- Single index.html file
- Mobile‑first design
- Data saved only in browser
- Include copy summary button
- Didn't make up details we never gave it
What came back (excerpt):
Here are three test cases to check the math: 1. Add two people, Alice and Bob. Add an expense where Alice pays $10 and the sharers are Alice and Bob.
Read the full answer
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Expense Splitter</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
label {
display: block;
margin-bottom: 10px;
}
input, select {
width: 100%;
height: 30px;
margin-bottom: 20px;
padding: 10px;
box-sizing: border-box;
}
button {
width: 100%;
height: 30px;
background-color: #4CAF50;
color: #fff;
padding: 10px;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #3e8e41;
}
#balances {
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Expense Splitter</h1>
<label for="name">Add Person:</label>
<input type="text" id="name" placeholder="Name">
<button onclick="addPerson()">Add</button>
<label for="payer">Add Expense:</label>
<select id="payer"></select>
<label for="amount">Amount:</label>
<input type="number" id="amount" step="0.01" placeholder="Amount">
<label for="sharers">Sharers:</label>
<select id="sharers" multiple></select>
<button onclick="addExpense()">Add</button>
<button onclick="showBalances()">Show Balances</button>
<button onclick="copySummary()">Copy Summary</button>
<div id="balances"></div>
<script>
let people = [];
let expenses = [];
function addPerson() {
let name = document.getElementById('name').value;
people.push(name);
let payerSelect = document.getElementById('payer');
let sharersSelect = document.getElementById('sharers');
payerSelect.innerHTML += `<option>${name}</option>`;
sharersSelect.innerHTML += `<option>${name}</option>`;
document.getElementById('name').value = '';
}
function addExpense() {
let payer = document.getElementById('payer').value;
let amount = parseFloat(document.getElementById('amount').value);
let sharers = Array.from(document.getElementById('sharers').selectedOptions).map(option => option.value);
expenses.push({payer, amount, sharers});
document.getElementById('amount').value = '';
document.getElementById('sharers').selectedIndex = -1;
}
function showBalances() {
let balances = {};
people.forEach(person => balances[person] = 0);
expenses.forEach(expense => {
let splitAmount = expense.amount / expense.sharers.length;
balances[expense.payer] += expense.amount - splitAmount * expense.sharers.length;
expense.sharers.forEach(sharer => {
if (sharer !== expense.payer) {
balances[sharer] -= splitAmount;
}
});
});
let summary = '';
people.forEach(person => {
summary += `${person}: $${balances[person].toFixed(2)}\n`;
});
document.getElementById('balances').innerText = summary;
let payments = [];
let debtors = people.filter(person => balances[person] < 0);
let creditors = people.filter(person => balances[person] > 0);
debtors.sort((a, b) => balances[a] - balances[b]);
creditors.sort((a, b) => balances[b] - balances[a]);
while (debtors.length > 0 && creditors.length > 0) {
let debtor = debtors[0];
let creditor = creditors[0];
let amount = Math.min(-balances[debtor], balances[creditor]);
payments.push(`${debtor} pays $${amount.toFixed(2)} to ${creditor}`);
balances[debtor] += amount;
balances[creditor] -= amount;
if (balances[debtor] === 0) {
debtors.shift();
}
if (balances[creditor] === 0) {
creditors.shift();
}
}
document.getElementById('balances').innerText += '\nPayments:\n' + payments.join('\n');
}
function copySummary() {
let summary = document.getElementById('balances').innerText;
navigator.clipboard.writeText(summary);
}
</script>
</body>
</html>
```
To publish this code for free, you can follow these steps:
1. Create a GitHub account if you don't already have one.
2. Create a new repository and upload your `index.html` file to it.
3. Go to GitHub Pages and select your repository.
4. Choose the branch you want to use (e.g., `main`) and click "Save".
5. Your website will be live at `https://your-username.github.io/your-repo-name`.
Here are three test cases to check the math:
1. Add two people, Alice and Bob. Add an expense where Alice pays $10 and the sharers are Alice and Bob. Show balances and verify that Alice has a balance of $5 and Bob has a balance of -$5.
2. Add three people, Alice, Bob, and Charlie. Add an expense where Alice pays $15 and the sharers are Alice, Bob, and Charlie. Show balances and verify that Alice has a balance of $10 and Bob and Charlie each have a balance of -$5.
3. Add two people, Alice and Bob. Add two expenses: one where Alice pays $10 and the sharers are Alice and Bob, and another where Bob pays $8 and the sharers are Alice and Bob. Show balances and verify that Alice has a balance of $1 and Bob has a balance of -$1.Check for floating‑point rounding issues in the balance calculations.
The made-up sample (a messier one):
This prompt has nothing to fill in.
- Provide a single index.html file
- Round balances to cents and sum to zero
- Include a copy summary button
- Do not add unlisted features
- Didn't make up details we never gave it
What came back (excerpt):
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.
Read the full answer
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Expense Splitter</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
label {
display: block;
margin-bottom: 10px;
}
input, select {
width: 100%;
height: 30px;
margin-bottom: 20px;
padding: 10px;
box-sizing: border-box;
}
button {
width: 100%;
height: 30px;
background-color: #4CAF50;
color: #fff;
padding: 10px;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #3e8e41;
}
#summary {
white-space: pre;
}
</style>
</head>
<body>
<h1>Expense Splitter</h1>
<button id="add-person-btn">Add Person</button>
<div id="people"></div>
<button id="add-expense-btn">Add Expense</button>
<div id="expenses"></div>
<button id="calculate-btn">Calculate Balances</button>
<div id="balances"></div>
<button id="copy-summary-btn">Copy Summary</button>
<div id="summary"></div>
<script>
let people = [];
let expenses = [];
document.getElementById('add-person-btn').addEventListener('click', () => {
const name = prompt('Enter person\'s name:');
people.push(name);
renderPeople();
});
document.getElementById('add-expense-btn').addEventListener('click', () => {
const payer = prompt('Who paid?', people.join(', '));
const amount = parseFloat(prompt('Enter amount:'));
const sharers = prompt('Who shares? (comma separated)', people.join(', ')).split(',').map(s => s.trim());
expenses.push({ payer, amount, sharers });
renderExpenses();
});
document.getElementById('calculate-btn').addEventListener('click', () => {
const balances = calculateBalances();
renderBalances(balances);
});
document.getElementById('copy-summary-btn').addEventListener('click', () => {
const summary = document.getElementById('summary').textContent;
navigator.clipboard.writeText(summary);
alert('Summary copied to clipboard!');
});
function renderPeople() {
const peopleHtml = people.map(person => `<p>${person}</p>`).join('');
document.getElementById('people').innerHTML = peopleHtml;
}
function renderExpenses() {
const expensesHtml = expenses.map((expense, index) => `<p>Expense ${index + 1}: ${expense.payer} paid $${expense.amount.toFixed(2)} for ${expense.sharers.join(', ')}</p>`).join('');
document.getElementById('expenses').innerHTML = expensesHtml;
}
function calculateBalances() {
const balances = {};
people.forEach(person => balances[person] = 0);
expenses.forEach(expense => {
const share = expense.amount / (expense.sharers.length + 1);
balances[expense.payer] += expense.amount - share * expense.sharers.length;
expense.sharers.forEach(sharer => {
balances[sharer] -= share;
});
});
// Round to cents and make balances add to zero
const total = Object.values(balances).reduce((a, b) => a + b, 0);
const adjustment = total / people.length;
people.forEach(person => balances[person] -= adjustment);
return balances;
}
function renderBalances(balances) {
const balancesHtml = people.map(person => `<p>${person}: $${balances[person].toFixed(2)}</p>`).join('');
document.getElementById('balances').innerHTML = balancesHtml;
const summary = Object.keys(balances).map(person => `${person}: $${balances[person].toFixed(2)}`).join('\n');
document.getElementById('summary').innerHTML = summary;
}
</script>
</body>
</html>
```
Steps to publish it for free:
1. Create a GitHub account if you don't have one.
2. Create a new repository and upload your `index.html` file.
3. Go to GitHub Pages settings and select the branch that contains your `index.html` file.
4. Click on the "Save" button to publish your website.
5. Share the link to your GitHub Pages website with others.
Test cases:
1. Add two people, Alice and Bob. Add an expense where Alice pays $10 for both of them. Calculate balances and verify that Alice has a balance of $5 and Bob has a balance of -$5.
2. Add three people, Alice, Bob, and Charlie. Add two expenses: one where Alice pays $15 for all three, and another where Bob pays $8 for Alice and Charlie. Calculate balances and verify that the balances add up to zero.
3. Add four people, Alice, Bob, Charlie, and David. Add three expenses: one where Alice pays $20 for all four, another where Bob pays $12 for Alice and Charlie, and a third where Charlie pays $8 for Bob and David. Calculate balances and verify that the balances add up to zero and are rounded to cents correctly.Check that the balance calculation truly balances to zero after rounding.
How each run works: we fill the prompt with a made-up sample, run it once in Llama 3.3 70B, and GPT-OSS 120B grades the answer against the prompt's own rules. Word limits are counted by code, and every quote flagged as made up is checked against the full answer. Your results can differ. How we test.