Build Mac AppDocsMenu

Reference

Troubleshooting

Find the message you see, in the words you see it. Each entry says what it means and what to do. When in doubt, run scripts/doctor.sh — it shows what is set up and the next step — or ask your agent:

Something's wrong: [paste the error]. Find out why and fix it.

If your problem isn't here, write to hello@buildmac.app. Every question that reaches us becomes an entry on this page.


Setting up

xcodegen: command not found, or bootstrap.sh says to install XcodeGen. Install it: brew install xcodegen, then run mac/scripts/bootstrap.sh again.

pnpm: command not found. Run corepack enable once. pnpm comes with Node; Corepack switches it on.

pnpm refuses to run, or complains about its version. Run site commands from inside site/ (cd site && pnpm dev), not from the repository's top folder. The version the site expects is written in site/package.json, and Corepack only reads it from there.

node --version shows 20 or older. Install a current Node: brew install node. Then open a new Terminal window.

scripts/doctor.sh shows a long list of "todo". That's normal on a fresh copy. Most lines are for later stages — signing, payments, a release. docs/start-here.md says which lines each stage turns green.


Running the app

The app always opens on the licence window. That's correct: it has no key yet. To see the licensed app while you build, add -AppDebugLicense YES in Product → Scheme → Edit Scheme… → Run → Arguments. It only works in Debug builds.

I added a Swift file but Xcode doesn't see it. The Xcode project is generated from mac/project.yml. Run mac/scripts/bootstrap.sh after adding (or removing) a file, and reopen the project if Xcode asks.

A check fails with "spelled outside its owners". Your app's name, domain or URL scheme is written out somewhere by hand. The message lists the file and line. Each of those facts lives in one file (the name and domain in site/lib/site.ts, for example), and everything else reads it from there — replace the literal with a reference to it, or ask your agent to.

scripts/verify.sh fails and I don't understand why. Run scripts/verify.sh --json and give the output to your agent: every failure comes with the file, the line and a suggested fix.


The website

The production build fails with NEXT_PUBLIC_SITE_URL is not set. Add it in Vercel → Settings → Environment Variables, for Production: https://your-domain.com — https, no www, nothing after the domain. This is the one variable a production build refuses to go without, so search engines never see the wrong address as your home.

The price or a button shows the waitlist instead of "Buy". Sales are off until you turn them on: onSale in site/lib/launch.ts. Leave it off until a real purchase and refund have worked (docs/go-live.md).

The buy button goes to the pricing section instead of the checkout. The checkout link isn't set: add the product's checkout link as NEXT_PUBLIC_CHECKOUT_URL_1 in Vercel, then redeploy (values starting with NEXT_PUBLIC_ take effect on the next deploy).

Emails don't arrive. Without RESEND_API_KEY emails are only written to the log, on purpose — the purchase still works. With it set, check that your sending domain is verified in Resend (docs/email.md), and look in spam.


Payments

The payment provider's webhook log shows 500. The webhook secret is missing in your site's environment. Set CREEM_WEBHOOK_SECRET (or POLAR_WEBHOOK_SECRET) and redeploy. The provider keeps retrying, so no payment is lost meanwhile.

The webhook log shows 400. The secret is wrong — usually the test endpoint's secret on the live site, or the other way round. Copy the secret of that endpoint.

A customer's key says it can't be activated. Check the key is from live mode on the live site (a test key never works on the live site, and the reverse), and that the product has licence keys turned on with enough activations (docs/go-live.md).


Releasing

A friend downloads the app and macOS says it is damaged and should be moved to the Bin. The app wasn't signed with a Developer ID certificate and notarized. It works on your Mac, and only on your Mac, because your Mac trusts your own development certificate. See "The signing blocker" in docs/releasing.md — it needs the Apple Developer Program.

The app crashes at launch with "Library not loaded … different Team IDs". It was signed without a Team ID. Set DEVELOPMENT_TEAM in mac/project.yml to your Team ID (security find-identity -v -p codesigning shows it in brackets) and build again.

Notarization was rejected. notarize.sh prints Apple's reason. In practice something re-signed the app after the release script did — build it again with mac/scripts/release.sh rather than signing by hand.

The release script stops before building. That's the preflight checking everything first, and the message names what is missing — usually the Developer ID certificate, the notarization profile or the update signing key. Each has a step in "One-time setup" in docs/releasing.md.

Customers' apps say "You're up to date" after I released a new version. Either the update feed wasn't published (commit the new entry in site/public/appcast.xml and deploy the site), or the build number didn't go up — updates compare the build number, not "1.1". Details in "When it goes wrong" in docs/releasing.md.

I shipped a broken version. Remove its entry from site/public/appcast.xml and deploy the site; that stops it being offered within minutes. Then ship a fixed version with a higher build number. There is no way to undo an update someone already installed, so the fix has to be a new version.

This page is docs/troubleshooting.md in the repository, copied 2026-09-25.