get paid for what you made.
Your project page already tells people what you made. This step lets them buy it without leaving the page. You set the price and what the customer gets in Polar, a payments service for people who sell software and digital products. Your site shows the price at the bottom of the project page, opens Polar's checkout on top of it, and remembers who paid.
| Polar does | Your site does |
|---|---|
| Holds your products and prices | Shows the price on the project's page |
| Takes the card, sends the receipt | Opens the checkout without leaving your page |
| Delivers what the customer bought: a file, a license key, access to a GitHub repository, a Discord invite | Remembers the purchase, so the button says YOURS. the next time they visit |
| Pays you out | Nothing. The money never touches your code |

✓ Success: someone can buy your project from its page.
this is a work in progress
- A project page — from Your first project page. Its name, like soap-shop, is how Polar's product finds its page
- Sign-in working — from Add sign-in. Customers sign in before they buy, so your site knows who paid
- Your site deployed — from Deploy, for the last part
1️⃣ Make a Product in the Sandbox
Polar has two separate worlds. The sandbox takes test cards and moves no money. Production is the real one. They have separate accounts, separate keys and separate product IDs, so you set everything up twice: once to practice, once to sell. Start in the sandbox.
- Go to sandbox.polar.sh/start, create an account, and create an organization for your business
- Open Products, click New product, give it a name and a price
- Under Benefits, attach what the customer gets: a file to download, a license key, access to a private GitHub repository, or a Discord invite. Polar delivers it the moment they pay
- Open Settings → Preferences → Embedding and add localhost:3000. Without it, the checkout cannot open on top of your page
- Open Settings → Developers and click New Token. Name it "my site sandbox", set an expiry, and tick only products:read and checkouts:write
- Copy the token. It starts with polar_oat_ and is only shown once
| Permission | Why your site needs it |
|---|---|
| products:read | To read the price it shows on your page |
| checkouts:write | To open a checkout when someone clicks the price |
| Everything else | Leave it off. A token that can do less can leak less |
Last, copy your product's ID. Open the product in Products; the ID is the long code with dashes in its address and on its page, like 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d.
2️⃣ Connect It to Your Project Page
Add the sandbox token to .env, and tell your site which Polar it belongs to:
# .env
POLAR_SERVER="sandbox"
POLAR_ACCESS_TOKEN="polar_oat_…"Then open src/data/FoundersConfig.json, the file from Make it yours. At the bottom is projects, an empty list. Add one entry for your project page:
"brandColors": ["#C8553D", "#F2D0A4", "", "", ""],
"projects": [
{
"id": "soap-shop",
"name": "Soap Shop",
"polarProductId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
}
]
}- Inside the list, not next to it — the entry goes between the square brackets of projects. A polarProductId anywhere else is ignored
- id matches the page — lowercase, words joined by dashes, the same as the folder in src/app
- One entry per project — sell more projects by adding more entries, with a comma between them
# Check the file, then start your site
npm run check:identity
npm run devOpen localhost:3000/soap-shop and scroll to the bottom. Above the footer is your price, in a pill:
| Who is looking | What they see |
|---|---|
| Signed out | The price, outlined. It shows what it costs |
| Signed in | The price, filled, with an arrow. Clicking it opens the checkout |
| Signed in, already bought it | ✓ YOURS. |
🔔 Let Polar Tell Your Site About the Sale
When someone pays, Polar sends your site a message called a webhook. That is how your site learns who bought what. On your live site, Polar sends it straight there. On your computer, Polar cannot reach localhost, so its command-line tool passes the messages along. On a Mac or Linux:
# Install the Polar CLI (not with npm: that package is only a placeholder)
curl -fsSL https://polar.sh/install.sh | bash
# Sign in, and choose Sandbox when it asks
polar login
# Pass sales along to your site. Leave this running in its own window
polar listen http://localhost:3000/api/webhook/polarpolar listen prints a line starting with Secret. It proves to your site that a message really came from Polar. Copy it into .env, then stop npm run dev and start it again, because your site reads it only when it starts:
# .env
POLAR_WEBHOOK_SECRET="the-secret-polar-listen-printed"On Windows, Polar's installer does not run. Skip the listening part here: your test purchase still works, and the button still says YOURS. until you reload. You will see the full round trip on your live site in the last part.
🧪 Buy It Yourself
- Sign in on localhost:3000 and open your project page
- Click the price. Polar's checkout opens on top of your page
- Pay with the test card 4242 4242 4242 4242, any future date, any three digits
- The checkout confirms, and the pill turns into ✓ YOURS.
- Reload the page. It still says YOURS. That is your site remembering the sale
- The polar listen window shows order.paid passed along with a 200
- Your dev server prints recorded purchase with your product's ID
- Clerk shows it too: open your Clerk dashboard, Users, your user, Metadata, and under Public you will see purchasedProductIds
- Polar's sandbox lists the order, with your benefit granted
“Test money first. The same steps with real money are only a key away.”
— unparty-app
3️⃣ Go Live
Now repeat the setup in the real Polar, at polar.sh. Nothing from the sandbox carries over, so the product, the token and the IDs are all new.
- Create your organization on polar.sh, and finish Polar's payout setup so it can pay you
- Create the same product with the same benefits, and copy its new ID
- In Settings → Preferences → Embedding, add your address, like www.soapshop.com
- Create a token with products:read and checkouts:write again
- Open Settings → Webhooks, click Add Endpoint, and enter https://www.soapshop.com/api/webhook/polar. Keep the format on Raw, generate a secret and copy it, and choose the event order.paid
Give the real keys to your live site. In Vercel, open your project, then Settings → Environment Variables, and add these for the Production environment:
| Key | Value |
|---|---|
| POLAR_SERVER | production |
| POLAR_ACCESS_TOKEN | The token from polar.sh |
| POLAR_WEBHOOK_SECRET | The secret from the webhook endpoint you just added, not the one polar listen printed |
Last, put the real product's ID into FoundersConfig.json in place of the sandbox one. In GitHub Desktop, the Changes list should hold FoundersConfig.json. Write a summary like "Start selling", click Commit to main, then Push origin. Pushing redeploys your site with the new keys too.
- Open your project page on your live address and scroll down: the real price is there
- Sign in and click it: the checkout opens on top of your page
- If you want to see a real sale, buy it yourself, then refund the order in Polar's dashboard
⚠️ Good to Know
- Customers sign in to buy — that is how your site knows who paid. Visitors who are signed out see the price, not the button
- Your computer now shows the real product — once FoundersConfig.json has the production ID, your local site needs production keys to show its price. To practice again, swap the sandbox ID and keys back in, then swap them out before you push
- Sandbox emails only reach you — the sandbox sends receipts only to members of your Polar organization
- Previews use real keys unless you say otherwise — Vercel preview sites count as production. Add sandbox keys for the Preview environment if you want previews to take test cards
- Prices live in Polar — change a price in Polar's dashboard and your page shows the new one within the hour. There is nothing to redeploy
🧯 If Something Is Off
- No price at the bottom of the page — check that the entry is inside projects, that its id matches the page's address, and that POLAR_SERVER matches where the product lives. A sandbox product with production keys, or the other way round, shows nothing
- Clicking the price takes you to a Polar page instead — your address is missing from Embedding in Polar's settings. The purchase still works; add it to keep people on your page
- YOURS. disappears when you reload — the webhook did not reach your site. Check that polar listen is running, that POLAR_WEBHOOK_SECRET matches what it printed, and that you restarted npm run dev
- polar listen shows 403 — the secret in .env is not the one it printed. Copy it again and restart
- polar listen shows 503 — POLAR_WEBHOOK_SECRET is missing from .env
- command not found: polar — it was installed with npm. Run npm uninstall -g @polar-sh/cli, then the curl line above
🤖 Ask Your LLM
I am selling [describe what you made] to [who buys it]. Suggest
a price, what the customer should get when they pay (a download,
a license key, repository access), and a one-line description for
the product in Polar.
(In Claude Code, inside your copy)
Add my project page soap-shop to the projects list in
src/data/FoundersConfig.json with Polar product ID [paste it],
then run npm run check:identity and fix anything it reports.
My polar listen window shows [paste the line]. What does it mean,
and what should I check first?✅ You Are Done When
- A test purchase in the sandbox turned your price into ✓ YOURS., and it stayed after a reload
- Your live site shows the real price on your project page
- Vercel has POLAR_SERVER, POLAR_ACCESS_TOKEN and POLAR_WEBHOOK_SECRET for Production
- Polar's webhook endpoint points at your live address with order.paid turned on
Your project page now does more than describe what you made. It sells it, delivers it, and knows who owns it. To sell another project, make its page, create its product, and add one more entry to projects.
“You made it. Now it can pay you back.”
— unparty-app