-
-
Penny's café has two big bills on Thu 12 Nov. tmrw spots that she'll be $120 short, a week before it happens.
-
Overview: rent and the bean order land on the same day. $1,900 due, $1,780 free above her cushion, $120 short.
-
Every fix goes to the Margin Guard. The $240 reminder is over $100, so it waits for the owner's OK.
-
The reminder carries a real PayPal sandbox checkout link. The customer pays and the signed webhook confirms it.
-
GIF
The Margin Guard: 9 rules in plain code. A second reminder after payment is blocked, because PayPal shows it paid.
-
Every decision prints a receipt: all 9 rules, what passed, what failed and why, with the PayPal IDs checked.
-
The 30-day forecast in AG Charts. Each day is covered, tight or short, with the minimum balance dashed.
-
AG Grid lists every payment due in the next 30 days and how much of it is ready on the day.
-
Ask in plain words: "Can I afford a $200 order on Monday?" No, Thursday would be $320 short. Numbers come from code.
-
Built phone-first. The owner sees the short day and the one next step each morning.
Inspiration
A small shop's money month lives in five places: the PayPal app where sales trickle in, auto-debits set up once and forgotten, WhatsApp messages from suppliers and staff, a paper calendar with rent on it, and the owner's head. None of them talk to each other. So two big payments land on the same Thursday and nobody notices until that Thursday.
The data to see it coming is already sitting in PayPal: every sale, every regular payment, every fee. We wanted to build what a good shop manager does on a Sunday night with a pen. Look at the month ahead, spot the bad day, and fix it while there's still time.
What it does
tmrw is a planner that lives inside PayPal. Our demo shop is Dunder Mifflin & Co., a small café-bakery run by Penny. Today is Thu 5 Nov, and tmrw has already found the problem:
Thu 12 Nov Rent $1,500
Bean There (coffee beans) $400
Due that day $1,900
Free above her $200 cushion $1,780
Short $120
It works in three steps:
- Spot. It reads the shop's PayPal history, finds every regular payment (supplier orders, bills, auto-debits) and works out the next 30 days, day by day. Each day is Covered, Tight or Short, always in words as well as colour.
- Plan. The month on one page: what must be paid, what's coming in, and what's left for the owner's own plans, like a second oven before Christmas.
- Steer. It offers fixes. Ivory & Vow, a wedding planner, still owes $240 for a cake. tmrw drafts a reminder with a fresh PayPal checkout link. When she pays, tmrw counts the money that actually arrives, not the price on the order:
$$ 240.00 - (0.0349 \times 240.00 + 0.49) = 231.13 $$
Thursday goes from $120 short to $311, covered. The other fixes are moving the bean order to Saturday or a small short-term loan.
Every action passes through the Margin Guard first: 9 fixed rules in plain code. Has PayPal already captured this order? Did the customer agree to be contacted? Were two reminders already sent in 48 hours? Would this push any day below the owner's minimum? Is it over $100, so the owner should say yes first? Every decision prints a receipt that shows which rules passed, which failed and why. If tmrw tries to remind Ivory & Vow again after she's paid, the Guard blocks it, because PayPal shows the order as paid.
You can also just ask: "Can I afford a $200 order on Monday?" The answer is no, because Thursday would then be $320 short. Every number in that answer comes from the forecast, not from the model.
How we built it
- Next.js 16, React 19 and TypeScript (strict), Tailwind, hosted on Render, with PostgreSQL on Supabase through Prisma.
- PayPal sandbox: Orders v2 for checkout and the reminder links, Webhooks with signature verification, Payments for refunds and Payouts for paying suppliers. Every PayPal call lives in one file, and every write sends a
PayPal-Request-Idbuilt from the action's idempotency key. - Gemini through the AI SDK for words only: reminder drafts, one-line explanations of why a day is short, and the Ask chat, which can only answer through four read-only tools that return numbers calculated by code.
- AG Charts draws the 30-day balance chart, each day coloured covered, tight or short, with the minimum balance as a dashed line. AG Grid shows upcoming payments and recent orders.
- The forecast is plain code. Money in is the average net sales for each weekday over the last 8 weeks. A payment counts as regular once there are 3 of them within 15% of the median, at a steady interval.
- 244 unit tests, Playwright end-to-end tests, and lint rules that stop any AI code from importing PayPal.
We used AI coding agents (Claude Code and Gemini) as tools, under one written rulebook (AGENTS.md) that every agent had to follow.
Challenges we ran into
- Deciding what the AI must not do. It's tempting to let a model answer "can I afford this?" directly. But a money tool that's right most of the time is a money tool you can't trust. So we split it: AI suggests, code decides, the owner taps. Drafts are checked for exclamation marks, banned words and any amount that wasn't in the input, and a failing draft falls back to a template. An Ask answer is thrown away if its numbers didn't come from a tool.
- The fee. A $240 order isn't $240 in the bank. Forecasting the order price instead of what arrives quietly overstates every week, so the forecast only ever uses the net amount PayPal reports.
- Two messages, one payment. The buyer coming back from PayPal and PayPal's webhook can arrive in either order, or twice. Every handler is idempotent, so whichever arrives second changes nothing.
- Many judges, one demo. Each visitor gets a private copy of the shop. Reset starts a new demo run id, so PayPal never replays a response from an earlier run.
- Free AI quota. We pooled keys, limited each visitor, and remembered each AI text by the facts it was written from. If the AI fails completely, the app still works from code.
Accomplishments that we're proud of
- A real PayPal sandbox payment runs end to end: reminder approved, checkout link created, buyer pays, webhook verified, $231.13 lands, Thursday turns green, and the follow-up reminder is blocked because the order is already paid.
- The Guard fails closed. If a rule can't be checked, for example because PayPal is unreachable, nothing runs.
- It reads like a planner, not a dashboard. No KPI tiles, no acronyms, one clear next step.
What we learned
- The most useful thing AI did for us was write the words around the numbers, not the numbers.
- Writing "Simulated" on screen made the demo easier to trust, not harder.
- Small shops don't need more charts. They need one sentence: "Thu 12 Nov, $120 short, here's why, here's the fix."
What's next for tmrw
- Pip, the assistant, edits the plan directly: snap a bill or type an instruction, see the change dashed on the page, tap Keep or Discard.
- A requests inbox, so staff and suppliers stop asking on WhatsApp.
- Learning from edits: move the bean order to Monday once, and next month it's already there.
- A real PayPal loan offer as a last resort, with the fee shown up front.
What's real and what's simulated
Real: the forecast, the Margin Guard, receipts, the AI features and PayPal sandbox payments, webhooks, refunds and payouts. Simulated, and labelled so on screen: the shop's 90 days of history, the reminder outbox, moved payment dates and loans. PayPal sandbox only, never live.
Try it at https://tmrw-y5bg.onrender.com/demo (the sandbox buyer login is on that page).
Built With
- ag-charts
- ag-grid
- gemini
- next.js
- node.js
- paypal
- paypal-orders-api
- paypal-payouts
- paypal-webhooks
- playwright
- postgresql
- prisma
- react
- render
- supabase
- tailwindcss
- typescript
- vercel-ai-sdk
- vitest
- zod