DEV Community

Thirumaran
Thirumaran

Posted on

Haggle: rehearse your freelance rate against a lowballing client who lives in your browser tab

Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle Submission 💸

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle

Built by @mrmaran and @vettri_vel_f6a5c117c95b00.

What I Built

A client reads your quote and writes back: "$4,000 is a bit steep for me right now. Could we try a trial project for $1,800?"

Most freelancers answer a message like that for the first time when the money is real. In a 2018 survey of 267 freelance science writers by The Open Notebook, 14% said they never ask for more, and 45% of those who did ask said they often got it.

Haggle lets you practise that conversation first. You quote a price and get up to eight turns against one of three difficult clients:

  • Marcus, the lowballer, offers less than half and asks for a free trial.
  • Dana, the scope creeper, keeps slipping in "just one more page".
  • Viktor, the late payer, wants to pay in 90 days.

At the end you get a receipt with your score, the client's real limit, and the exact line where you gave money away. In our own play-test that line was "Okay, I could do $3,800." It dropped the price by $200 and asked for nothing back. Marcus didn't budge, and his real limit turned out to be $3,400.

The client is played by Gemma 2 2B, running inside your browser tab. There's no server, no API key and no account, and nothing you type leaves your computer.

The people who'd pay for this are freelancers who know they undercharge. A two-day negotiation seminar costs $1,489, and practice apps charge $10 to $19 a month. Our plan is one free client and a $9 pack for the rest. We have exactly one paying user so far, and he's family (more on him below), so treat the $9 as a plan, not a proven price.

Demo

Play it here: https://haggle.mrmaran.workers.dev/

Start negotiating downloads the model once, about 1.4 GB, and your browser caches it after that. You need a WebGPU browser such as a current Chrome or Edge, and a computer with a graphics card.

Play without the AI skips the download and works in any modern browser. Simple rules read your moves and the client answers with fixed lines.

If you're curious how the model reads you, add ?debug to the address. After every turn it shows the model's label for your line and whether code overruled it.

Haggle receipt: the line
A receipt from a round against Marcus. One $200 concession for nothing, quoted back in red.

Code

GitHub logo Mramaran / haggle

Rehearse your freelance rate against a difficult client played by an open model (Gemma 2 2B) running in your browser. No key, no server.

Haggle

Rehearse your freelance rate against a client who won't make it easy. The client is played by an open-weight model (Gemma 2 2B) running in your own browser tab, so there is no server, no API key, and nothing you type leaves your computer.

You quote a price. The client lowballs you, asks for a free trial, slips in extras or wants to pay in 90 days. You negotiate for up to eight turns. At the end you get a receipt: your score, the client's real limit, and the exact line where you gave money away for nothing.

Built for the DEV Hacktoberfest 2026 Open-Source AI Challenge, Week 2: Side Hustle.

Play

Play it at https://haggle.mrmaran.workers.dev/

To run it locally:

npm install
npm run dev
Enter fullscreen mode Exit fullscreen mode

Open the address Vite prints (usually http://localhost:5173).

  • Start negotiating downloads the model the first time (about 1.4 GB, then cached by your browser)…

It's MIT licensed, written in TypeScript with Vite, and has 38 unit tests and 6 Playwright end-to-end tests.

How I Built It

Code decides every number

Give a 2B model a negotiation about money and sooner or later it will invent a price. So we split the work:

Part Done by
Opening offer, each concession step, the real limit, when the game ends Code
The client's lines, in character Gemma 2 2B, checked by code
Reading your move: holding firm, discounting, trading, walking away, accepting Gemma 2 2B, with code rules for its known blind spots
The score Code only

On each turn, code picks the client's move: raise, hold, press, or give a final number. Gemma is told the move and the one dollar amount it may say, and it writes the line. Code checks the reply. If Gemma invents a number, breaks character or agrees when it shouldn't, it gets one retry, and if that fails too the player gets a plain fixed line instead.

Scoring is code as well. You get up to 60 points for how close you land to the client's real limit and up to 40 for never giving ground without getting something back, minus 12 for every concession you gave away for nothing.

Picking the model

We tested models on day one, before writing any of the game. Gemma 3 1B looped, invented amounts and read 0 of 12 player moves correctly. Qwen 2.5 1.5B kept losing track of who was speaking and read 11 of 16. Gemma 2 2B held the role across 15 scripted games and wrote 126 replies without a single invented amount or character break, so we went with it.

Running in the browser

WebLLM runs Gemma 2 2B on WebGPU. The half-precision build needs about 1.9 GB of GPU memory, and there's a fallback build for GPUs that can't do half precision. The model library only loads when you start the AI client, so the page itself is about 9 KB compressed. On a laptop with an RTX 40-series GPU, a turn takes 2.3 to 3.3 seconds.

The share link on the scorecard carries the score and the quoted line in the URL, so a shared receipt opens on any device without loading the model.

What testing caught

A four-round play-test on the real model got the money right. Offers matched the rules on 19 of 19 turns. Gemma wrote 21 of 23 replies on its first try. Its reading of the player's move held on 15 of 19 turns, and code corrected the other four.

It also turned up three bugs that unit tests would never have found.

The first: asking "What's your real budget?" got read as a trade, so the client raised his offer for a question. Questions are now settled before trades.

The second was funnier. Mashing the keyboard got labelled "holding firm", and random letters walked Marcus all the way up to his limit. A line with no price and no ordinary English word now counts as off-topic, and the client steers you back to the project.

The third only showed up after deploying. The AI worked on localhost and failed with "Failed to fetch" on the live site. Hugging Face, which hosts the model files, rejected downloads whose Referer was a workers.dev page. Adding <meta name="referrer" content="no-referrer"> fixed it.

Two faults are still there. The model sometimes uses the wrong direction word ("bump it down" while raising his offer), and now and then it repeats the player's figure as if it were its own.

Why Does Open Innovation Matter?

For Haggle, open weights are what make the business work.

The player's own GPU runs the model, so our running cost per game is zero and the hosting bill stays flat however many people play. A $9 practice pack only works as a side hustle if each game costs us nothing.

People type real rates and real client situations into a tool like this. Here none of it leaves the device, because there's no server to send it to.

Nobody has to sign up or paste a key. The closest thing we found, an AI negotiation simulator on itch.io, asks players for their own Gemini or Mistral API key, and I think most freelancers would close the tab at that point.

No vendor can change the price, retire the model or cut off access. Anyone can fork the repo and add a client of their own, say a landlord or a recruiter.

A hosted closed model would write better lines, faster, for about half a cent a session, so we don't claim Haggle is cheaper per game. What open weights buy us is free hosting and privacy, and for a game about getting braver with money, we think that's the right trade.

My First User

Our first paying customer is my brother. He's a freelancer, so he quotes clients for a living. He played Haggle and paid me ₹1,500 (about $17), which is more than the $9 we planned to charge.

One sale to family proves very little about the market. Still, he's the kind of person Haggle is for and he chose to pay, and it told us what to do next: put it in front of freelancers who aren't related to us.

Prize Categories

  • Best Use of Gemma: Gemma 2 2B plays every client, running locally in the player's browser through WebLLM and WebGPU.

Top comments (0)