docs
    commerce-kit: Changelog
    v1.0.1.md

    @sonordev/commerce-kit Changelog

    1.0.1

    • server-only is a dependency. @sonordev/commerce-kit/commerce/server and @sonordev/commerce-kit/memberships/server import the server-only marker, and 1.0.0 didn't list it. A Next build never noticed, because Next supplies its own copy, but a Node script or a test that imported either entry from a pnpm install failed with ERR_MODULE_NOT_FOUND. It's a dependency now, so the import resolves anywhere, and inside a build Next still uses its own copy. Outside Next, load these entries under the react-server condition (node --conditions=react-server), the way a server component loads them; without it, server-only stops the import on purpose. It's the package's only dependency: React, Next and site-kit stay peers of your site.
    • Moving from site-kit 7? Use sonor-setup 7.3.1 or later. Its codemod writes valid YAML when it adds this package to pnpm-workspace.yaml, and it adds the package only to a project whose code imports commerce.

    1.0.0

    The first release. commerce-kit is the commerce module that shipped inside site-kit through 7.4, now its own package, plus memberships. It needs site-kit 8 or newer. Moving a site is an import swap: see Moving from site-kit 7.

    Commerce

    Products, services, events and checkout, working the way they did in site-kit 7.4. See Commerce.

    • Pages and widgets. Product pages and grids, offering cards and lists, event tiles, calendars, agendas and an events widget with booking built in, and a size chart for clothing.
    • Checkout. Inline checkout on the product page, an event checkout with ticket tiers paid by card in the page with Square, registration for free events, shipping rates and address checks when the project ships, and discount codes.
    • Server helpers. @sonordev/commerce-kit/commerce/server fetches offerings, events, static paths and metadata on the server. Its *Result variants tell an empty answer from a failed request, so a page can avoid saying "nothing available" when Sonor was only briefly unreachable.
    • Helpers that run anywhere. @sonordev/commerce-kit/commerce/utils has the formatting helpers and the calendar ones (icsForEvent, googleCalendarUrl and icsResponse) with no React, so a server component or a route handler can call them. Through @sonordev/commerce-kit/commerce, a client module, they can't be called on the server.
    • Styling hooks. The components keep their site-kit- class names, and event and offering surfaces carry data-category and data-offering-type, so the stylesheets sites already have keep working.
    • Types. The root, @sonordev/commerce-kit, exports the main commerce types and nothing that runs.

    Memberships

    New with this release. Sell a membership on your site and keep members-only pages for the people who pay. See Memberships.

    • Sell it. MembershipCheckoutButton sends a visitor to Square's secure checkout for a membership offering. Square bills the card on the plan's schedule (weekly to yearly, with an optional free trial), and the member shows up in Sonor with their payments. getMembershipPlans() lists what the site sells.
    • Members sign in with an emailed link. MemberSignInForm asks for the address they joined with; there are no passwords. Sonor only sends links to the site's own domains, and the form answers the same way for members and strangers.
    • Members-only pages. createMembers() gives you requireMember() for a page, getMember() for headers and account pages, and the sign-in and sign-out routes. Access is checked with Sonor, so when a membership ends or a renewal fails, access stops within a minute, and the site keeps no secret of its own.
    • Members can cancel on the site. members.cancelMembership() ends a membership at the close of the period that's already paid for.
    • Redirects stay on your site. The sign-in and sign-out routes answer with paths, never full URLs, so a proxy can't send a member to the wrong host, and the one-time sign-in token never lands in the address bar (a landing page with no query of its own gets ?signed_in=1).
    • Keep your own sign-in if you have one. A site with its own accounts asks getMembershipByEmail(verifiedEmail) on the server whether someone has paid, and cancels with cancelMembershipByEmail.

    What's different from site-kit 7

    Apart from the fixes below, the code behaves the same. These are the differences:

    • The package and its paths. @sonordev/site-kit/commerce is now @sonordev/commerce-kit/commerce, and /commerce/server moved the same way. The commerce types the site-kit root used to re-export come from @sonordev/commerce-kit. Nothing is left behind at the old paths; the sonor-setup codemod rewrites the imports.
    • Server logs. Fetch errors from commerce/server start with [commerce-kit] instead of [site-kit/commerce].
    • Shopping events reach Sonor. The product and checkout components report product_view, add_to_cart, begin_checkout, checkout_start and purchase. site-kit 7 reported them through a hook that only answers inside the analytics provider, and under SiteKitLayout a page never is, so they were never sent. They go through site-kit's trackEvent now, which waits for analytics to load. See Analytics.
    • The server helpers return whole offerings. commerce/server re-mapped every offering through a copy of its shape that had fallen behind the API: it read the gallery from a field the API no longer sends, so a server-fetched product had no gallery, and it dropped the clothing flag, size chart, buy link, notes, options and an event's next date. It returns the offering exactly as the browser components load it now, so a page can hand ProductPage the product it fetched and the product is in the HTML.
    • Server requests are cached, tagged and time-limited. They go through site-kit's server data plane: each response is cached for 60 seconds under the commerce cache tag, which Sonor expires when you change an offering, so an edit shows within seconds on a site that serves the revalidation route. Each request gives up after 30 seconds and retries a busy API, where before one hung request could stall a build for minutes. Pass revalidate in the config to change the window (0 turns caching off). getUpcomingEvents makes one request now; it no longer falls back to a second, older one.
    • Server config is optional. The helpers read SONOR_API_KEY and SONOR_API_URL themselves, so {} is a complete config, and createServerConfig no longer asks for a project id (Sonor finds the project from the key). Existing calls keep working.
    • A sold-out offering keeps its page. One marked sold out in Sonor came back as "no such offering", so its page returned a 404 and could drop out of search while it was only sold out. It comes back with status: 'sold_out' now, and ProductDetail and EventTile show it as unavailable with buying turned off. If your own markup renders an offering, check status too. Drafts and archived offerings still have no page.
    • Checkout works when the browser blocks site storage. Reading the analytics session id threw in a browser set to block site data, which stopped checkout and event registration before they reached Sonor. The id now comes from site-kit's readAnalyticsIdentity, which never throws.
    • Agent tools. The opt-in list_offerings tool in sonorMcpServer takes its reader as an option: offerings: { path: '/shop', read: getOfferingsResult }, with getOfferingsResult from @sonordev/commerce-kit/commerce/server. It tells an agent the catalog is unavailable when a request fails; the plain getOfferings works too, but it reads an outage as an empty catalog. list_services is unchanged.
    • One reader for the Sonor address. Browser calls get the API address and the site credential from site-kit's @sonordev/site-kit/runtime, the same reader the rest of site-kit uses. During server rendering they follow SONOR_API_URL, so a staging site's server-rendered requests point at staging.

    Why it's a separate package

    Checkout is the busiest money path on a site, and most sites don't sell anything. As its own package, commerce versions and releases on its own: a checkout fix doesn't wait for a site-kit release, and a site-kit release doesn't touch checkout. site-kit also gets a smaller surface: its package is about 8% smaller to download than 7.4.0.

    It isn't about page weight. site-kit's root entry was already types only, and nothing in its core referenced commerce, so a visitor to a site without commerce never downloaded any of it. A page that does use commerce loads the same components as before.

    commerce-kit takes its transport, credential, analytics, visitor ids and server config from site-kit instead of carrying copies. It imports three site-kit entries, @sonordev/site-kit/runtime, @sonordev/site-kit/analytics and @sonordev/site-kit/server, and nothing else.

    Requirements

    • @sonordev/site-kit 8.0.0 or newer, installed and mounted with SiteKitLayout. It's a peer dependency, so commerce-kit uses your site's one copy.
    • React 19 and react-dom 19.
    • Node 20.19 or newer. The package is ESM only.
    • Next 16 is an optional peer. Only @sonordev/commerce-kit/memberships/server uses it.
    • SONOR_API_KEY, the one variable every Sonor site already has. commerce-kit adds none.