paddle-pricing-pages
Display localized pricing in Next.js
When to use this skill
Use this skill when building a public pricing page (or in-app upgrade screen) that needs to show prices in the user's local currency, with the right tax behavior. Covers the Paddle.PricePreview() API, country detection, a billing frequency toggle (monthly/yearly), the zero-decimal currency formatting gotcha (JPY/KRW/CLP), and how to keep the displayed price in sync with what checkout will charge.
This is a client-side concern. For checkout itself, see checkout-web — the price IDs you display here are the same ones you pass to Paddle.Checkout.open().
Why use PricePreview at all?
You could hardcode "$10/month" in your UI, but comes with very strong regional pricing built-in — the same plan might be $10 in the US, €9 in the EU (with VAT), £8 in the UK, and ¥1,200 in Japan. Across countries that share a currency you can set different prices for each country to account for purchasing power parity. Hardcoding works only for one market.
PricePreview() returns the correct price for a given country, with currency, formatting, and applicable tax already calculated. The string it gives you is what the user will be charged — no client-side math.
If a Paddle MCP server is available to you, call client.pricingPreview.preview({ items: [{ price_id: "pri_...", quantity: 1 }], address: { country_code: "US" }, currency_code: "USD" }) inside an execute to get the same data server-side — useful for verifying what users will see in different countries before wiring up the client-side hook. Note pricingPreview is camelCase, but country_code and currency_code are snake_case.
The Paddle MCP exposes three tools per server (
search,execute,report_missing_tool). Workflow: callsearchto confirm the exact method name and parameter shapes, then callexecutewith an async function that callsclient.<resource>.<operation>(...). Method paths are camelCase (client.clientTokens.create,client.pricingPreview.preview). Body params and response fields are snake_case (tax_category,product_id,unit_price,currency_code). Pagination is{ pagination: { hasMore }, data: [...] }with{ after: "<last_id>" }— not.next()/.hasMore. Chain multi-step workflows inside oneexecute; variables don't persist between calls. Hard caps: 50 API calls per execute, 30s timeout, 32KB code.