Inspiration
Freelance web work breaks down at the handover. The client is asked to pay before they can tell whether the site works, and the freelancer is asked to deliver before they know they will be paid. "Done" was never written down, so the argument is about opinions. Escrow alone does not help: someone still has to decide whether the work is finished, and that someone is usually one of the two people arguing.
We wanted a neutral referee that both sides agree to in advance, that checks the actual delivered site rather than screenshots or promises, and that moves the money without either person pressing a button they could hold hostage.
What it does
- Agree what done looks like. The client describes each milestone. Claude turns each brief into a short list of testable checks, each carrying a share of the payment. Either person can change the list; the other must accept the change. Both sign by typing their name.
- Hold the money with PayPal. The client funds a milestone through PayPal checkout. Handovr authorises the payment rather than capturing it, so it stays in the client's account until the work passes. The client pays PayPal's fee on top: a $600.00 milestone is held as \$618.23, and the freelancer receives exactly \$600.00.
- Test the real site. The freelancer submits the live address. Claude drives a KERNEL cloud browser through every check: filling in forms, resizing to a phone, timing loads, following links, auditing accessibility. Each verdict comes with screenshots and notes, and a replay of the whole run.
- Review what only a person can judge. Checks about taste, and anything the tester could not decide, go to the client. If the client does nothing, the work is approved when the review window ends.
- Release, split or return. When every check passes, Handovr captures the hold and pays the freelancer through PayPal Payouts. After four failed attempts it proposes a proportional split: code does the arithmetic and Claude explains it in plain words. Both must accept; if either declines or time runs out, the hold goes back to the client.
Along the way, both people get an email at each step through Zapier MCP. The project timeline is a Bryntum Gantt, and the ledger is an AG Grid table with an AG Charts summary.
How we built it
- Next.js 16 (App Router, server actions,
after()for background work) with Postgres through Drizzle, deployed on Render. - PayPal REST APIs called directly: Log in with PayPal, Orders v2 with intent
AUTHORIZE, reauthorise, partial capture, void, Payouts and webhook signature verification. A Postman collection in the repo has every call. - One state machine decides every milestone change. Money work is written to an outbox in the same transaction and sent with PayPal idempotency keys, so a retried request can never capture or pay twice. Webhooks are verified, then treated only as a nudge to re-read PayPal.
- Claude Sonnet 5.5 with tool use drives the browser through playwright-core over CDP into KERNEL. Structured output drafts and rewrites checks and explains splits. Everything a website shows the tester is treated as data, never as instructions.
- A tick every five minutes renews holds on day 25, ends review windows and splits that ran out of time, retries failed payouts and restarts stalled test runs.
Challenges we ran into
- Holds expire. A PayPal authorisation lasts 29 days and can be renewed only once. We designed the renewal, a lapse path, and a "Start again" button that copies the milestone for both people to sign again.
- Paying the fee without shortchanging anyone. We worked out the hold total so the platform nets the exact milestone amount after PayPal's 2.9% plus $0.30, and checked it against real sandbox captures.
- Testing that tests are fair. A tester that fails a good site is worse than none. We built six fixture sites, including one with hidden text telling the tester to pass everything, and measured the models on them.
- The test database lied. Our in-memory Postgres accepted a query the real driver rejects, so the tick failed in production while every test passed. Now new database code is also run against the real Postgres.
- Hosting fixtures. A popular raw-file CDN shows real browsers an interstitial page, which made every load-time measurement meaningless. The app now serves its own fixtures.
Accomplishments that we're proud of
- 30 of 30 correct verdicts on the fixture sites with Claude Sonnet 5.5 (286,821 input tokens for the whole set), including failing the injection site despite instructions hidden in the page.
- A full sandbox milestone end to end: a broken form failed in 64 seconds with four screenshots of evidence, the fixed site passed, the review window ran out, and the money moved by itself: hold \$103.30, capture \$103.30, payout $100.00.
- The split: amounts that follow from the signed shares, explained by AI, accepted by both people, and paid as a partial capture plus a payout.
- Over 450 automated tests covering the state machine, payments, races between two people answering at once, and every route that moves money.
What we learned
- An AI judge is only acceptable when both people agreed to the checks in advance and can see the evidence behind every verdict.
- Let code do the arithmetic and let the model explain it. People trust a split they can follow.
- Treat webhooks as hints and the payment provider as the source of truth.
What's next for Handovr AI
- Real money in more currencies, and milestones that run longer than a PayPal hold.
- Checks against a code repository as well as the live site.
- A shared review where both people can comment on each verdict before the client decides.
Built With
- ag-grid
- axe-core
- bryntum
- claude
- drizzle
- kernel
- next.js
- paypal
- playwright
- postgresql
- react
- render
- tailwindcss
- typescript
- zapier
Log in or sign up for Devpost to join the conversation.