The account page turns catalog offers into billing actions.
Relevant files:
Browser action
The checkout button calls the browser API client with one thing: offerId.
const response = await client.checkout.start({ payload: { offerId: props.offerId } })Server-side workflow
Server code authenticates the user, validates the offer, and then delegates to Purchase:
const checkout =
yield *
sdk.checkout.start({
customerId: asCustomerId(input.user.id),
offerId: input.offerId as never,
successUrl: `${getAppBaseUrl()}/account?checkout=success&offer=${encodeURIComponent(input.offerId)}`,
cancelUrl: `${getAppBaseUrl()}/account?checkout=cancelled&offer=${encodeURIComponent(input.offerId)}`,
metadata: {
source: "nextjs-app",
workspaceSlug: input.user.workspaceSlug,
authUserId: input.user.id
}
})Why this boundary is right
The browser does not send:
- provider customer ids
- provider price ids
- provider-specific checkout payloads
It only selects a commercial offer. The server runtime fills in the rest.