Moving a site to site-kit 8
site-kit 8 moves commerce into its own package, @sonordev/commerce-kit, which also carries the new memberships module, and removes the entries for two modules Sonor retired, Engage and the Sanity CMS. Most sites need no changes at all: if yours uses none of these, update site-kit and rebuild. A site's ^7 range never picks up 8, so nothing forces the move before you next touch the site.
Who's affected
Only sites that do one of these:
- Import from
@sonordev/site-kit/commerceor@sonordev/site-kit/commerce/server(products, services, events, checkout, calendars). - Import a commerce type from the root, such as
import type { CommerceOffering } from '@sonordev/site-kit'. - Turn on the opt-in
list_offeringsagent tool by passingofferingstosonorMcpServer. See The MCP change. - Import one of the entries that were removed:
@sonordev/site-kit/engage,/cms,/website/cms(or their/serverentries), orManagedContent,getManagedContentDataorgetContentBlockfrom/seo.
Not sure which you are? Search the site for the old paths, then for root imports:
grep -rnE "@sonordev/site-kit/(commerce|memberships|engage|cms|website/cms)" . \
--include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' \
--include='*.mjs' --include='*.cjs' --include='*.mts' --include='*.cts' --include='*.mdx' \
--exclude-dir=node_modules --exclude-dir=.next
grep -rnE "ManagedContent|getManagedContentData|getContentBlock" . \
--include='*.ts' --include='*.tsx' --include='*.js' --include='*.jsx' --exclude-dir=node_modules --exclude-dir=.next
grep -rnE "from ['\"]@sonordev/site-kit['\"]" . \
--include='*.ts' --include='*.tsx' --exclude-dir=node_modules --exclude-dir=.nextThe root entry is types-only (plus SITE_KIT_VERSION), so the last search turns up type imports. Look for the commerce types listed under What moved and the Engage type names under What was removed. If the first two searches find nothing, none of the root imports are those types, and you don't pass offerings to sonorMcpServer, you're done: raise site-kit to ^8 whenever you like.
Steps
1. Install both packages
pnpm add @sonordev/site-kit@^8 @sonordev/commerce-kitnpm install @sonordev/site-kit@^8 @sonordev/commerce-kit does the same. commerce-kit lists site-kit 8 or newer as a peer dependency, so it uses your site's one copy of site-kit. If your package manager reports that commerce-kit needs @sonordev/site-kit >=8.0.0 (npm stops with an ERESOLVE error, pnpm and Yarn warn), site-kit is still on 7. Like site-kit, commerce-kit needs React 19. Next 16 is an optional peer: only the memberships server helpers use it.
2. Run the codemod
Dry run first:
npx sonor-setup codemod --only site-kit-8It prints what it would change and writes nothing. When the diff looks right, apply it:
npx sonor-setup codemod --only site-kit-8 --writeThe codemod needs sonor-setup 7.3.1 or later, and npx fetches the latest. It reads source files anywhere in the project (pages/, hooks/ and scripts/ count, not just app/ and src/), but not node_modules, build output or public/. It rewrites your imports (the table below), and goes by imports only: a path that appears in a comment or inside a string, such as a code sample or a redirect table, is left as it is. When your code imports commerce, it also adds @sonordev/commerce-kit to package.json and raises site-kit's range to ^8.0.0, and if pnpm-workspace.yaml lists site-kit under minimumReleaseAgeExclude it adds commerce-kit there too. Anything it can't rewrite safely it flags, with the fix, so you can finish those by hand: a require() of an old path (commerce-kit is ESM only, so that call needs an import), an import of a removed entry, or a sonorMcpServer whose offerings has no reader (see The MCP change). Run it in the app's folder: in a monorepo, once per app that imports commerce, because it stops at a workspace root.
--check is the gate: it exits 1 while a file needs rewriting and while a manual follow-up remains, so exit 0 means there's nothing left for you to do.
If it changed package.json, install before you build:
pnpm installNo codemod handy? The swap is mechanical: replace the package name in each import and add commerce-kit to package.json. The subpath stays the same.
3. Build
pnpm buildA build is the real test. Nothing is left behind at the old paths, so an import you missed fails with "Module not found" instead of quietly running something stale. A bump you didn't build is a guess.
What moved
The subpath stays the same; only the package name changes.
| Was | Now |
|---|---|
@sonordev/site-kit/commerce | @sonordev/commerce-kit/commerce |
@sonordev/site-kit/commerce/server | @sonordev/commerce-kit/commerce/server |
@sonordev/site-kit/memberships | @sonordev/commerce-kit/memberships |
@sonordev/site-kit/memberships/server | @sonordev/commerce-kit/memberships/server |
Commerce types from the root, @sonordev/site-kit | @sonordev/commerce-kit |
Memberships never shipped in a site-kit release, so those two rows only matter if you tried an unreleased build. The root types are CommerceOffering, CommerceCategory, CommerceVariant, CommerceSchedule, OfferingType, Cart, CartItem, EventCheckoutProps and CheckoutLineItem.
// before
import { OfferingCard, ProductPage } from '@sonordev/site-kit/commerce'
import { getOfferingBySlug } from '@sonordev/site-kit/commerce/server'
import type { CommerceOffering } from '@sonordev/site-kit'
// after
import { OfferingCard, ProductPage } from '@sonordev/commerce-kit/commerce'
import { getOfferingBySlug } from '@sonordev/commerce-kit/commerce/server'
import type { CommerceOffering } from '@sonordev/commerce-kit'The new entries export what the old ones did, under the same names. /commerce is a client entry and /commerce/server is server code, the same split as before. commerce-kit's root is types-only, so import anything that runs from one of its module entries.
What stays where it was:
- Your CSS. The components keep their
site-kit-class names (site-kit-product-grid,site-kit-calendar-eventand the rest), so your styles still apply. Brand tokens still come from site-kit'sbrand.css, which your site imports as before. - Your credential. commerce-kit uses the credential
SiteKitLayoutalready publishes, so there's no new environment variable.
What's different besides the import path, all in commerce-kit's changelog:
- The shopping events (
product_view,add_to_cart,begin_checkout,checkout_startandpurchase) reach Sonor. site-kit 7 reported them through a hook that returns nothing underSiteKitLayout, so they were never sent. - The server helpers return whole offerings (gallery, size chart and options included), and they're server-only now. Each response is cached for 60 seconds under the
commercetag, which Sonor expires when you edit an offering, and a request gives up after 30 seconds. Pass{ revalidate: 0 }in the config if a page needs every request fresh. - A product marked sold out in Sonor keeps its page, shown as unavailable, instead of answering "no such product".
- Checkout works in a browser set to block site data.
- When a server fetch fails, the log line starts with
[commerce-kit]instead of[site-kit/commerce]. If you filter or alert on that prefix, update it.
What was removed
These modules were retired in Sonor, and their entries were kept through 7.x so old imports kept building. They're gone in 8, and nothing replaces them:
| Removed | Use instead |
|---|---|
@sonordev/site-kit/engage | @sonordev/site-kit/chat and @sonordev/site-kit/website/popups. The 7 codemod (npx sonor-setup codemod --write) moves the names that have a home there and flags EngageWidget, which SiteKitLayout already mounts |
@sonordev/site-kit/cms, /cms/server, /website/cms, /website/cms/server | Managed copy: ManagedSlot, ManagedRichText, ManagedLink and ManagedList from @sonordev/site-kit/website/slots. You can uninstall @portabletext/react and @sanity/image-url |
ManagedContent, getManagedContentData, getContentBlock and their types, from @sonordev/site-kit/seo | ManagedRichText from @sonordev/site-kit/website/slots |
EngageElement, WidgetConfig, EngageConfig and the other Engage type names, from the root | SitePopup, SitePopupConfig and the rest of @sonordev/site-kit/website/popups. (The engage prop on SiteKitLayout and its own EngageConfig type stay.) |
They rendered nothing in 7.x, so most sites never imported them and have nothing to do. npx sonor-setup manifest --json lists them under removed.
The MCP change
list_offerings is the opt-in agent tool that lists priced products, services and events. It used to read the commerce fetchers directly. It takes its reader as an option now, so site-kit doesn't depend on commerce-kit:
// before (site-kit 7)
sonorMcpServer({ businessName: 'Example Studio', offerings: { path: '/shop' } })
// after (site-kit 8)
import { getOfferingsResult } from '@sonordev/commerce-kit/commerce/server'
sonorMcpServer({ businessName: 'Example Studio', offerings: { path: '/shop', read: getOfferingsResult } })read is getOfferingsResult from @sonordev/commerce-kit/commerce/server. It reports a failed request as "the catalog is unavailable" instead of an empty catalog; the plain getOfferings from the same entry also works, but it reads an outage as empty. path is still optional and still defaults to /shop. The tool, how it ranks a query, and its rule that a price the business keeps private is never shown all stay in site-kit.
If read is missing, sonorMcpServer throws when the server is built, with a message that says what to pass. A TypeScript site sees the same reminder as a type error. A site that doesn't pass offerings changes nothing, and neither does list_services: it reads the site's core data, not commerce. See MCP and agent tools.
Check your work
- The first two searches from Who's affected come back empty, and none of the root imports the last one finds are commerce or Engage types.
pnpm buildpasses.pnpm ls @sonordev/site-kit @sonordev/commerce-kit(ornpm ls) shows site-kit 8.x and commerce-kit 1.x.- On a preview deploy or in dev, load a product or events page and start a checkout.
npx sonor-setup verifystill exits 0.
Staying on 7.x
Staying on 7 is fine while you plan the move. A ^7 range never picks up 8, and everything in 7.4 keeps working, commerce included. Two things to know: commerce-kit needs site-kit 8, so a site on 7 can't install it, and the memberships module ships only in commerce-kit. If a dependency update raised your range to 8 before you were ready, pin it back with pnpm add @sonordev/site-kit@^7.4.0.
Questions
Why is commerce a separate package?
It versions and releases on its own. Checkout is the busiest money path on a site, and most sites don't sell anything, so a fix there shouldn't wait for a site-kit release (or the other way round). commerce-kit builds on site-kit and takes its transport, credential, analytics and server data from it instead of carrying copies. The one entry site-kit added for it, @sonordev/site-kit/runtime, is public API, and a site doesn't need to import it.
Does this make my site's JavaScript smaller?
No, and it was never meant to. site-kit's root entry was already types-only and no core entry referenced commerce, so visitors to a site without commerce never downloaded any of it. For a site that does sell, the components are the same code, now built and shipped from commerce-kit. What shrinks is site-kit's package: about 8% fewer bytes to download and about 13% fewer on disk than 7.4.0, which is install size, not page weight.
Why 8.0, and not a 7.x release with the old paths still working?
Removing a published entry is a breaking change, and a ^7 range would have picked it up on the next install. Keeping the old paths alive would have meant a second copy of the code, or site-kit depending on a package that depends back on it. It wouldn't have saved an edit either, since commerce-kit has to be added to package.json whichever way. (The retired Engage and CMS entries were promised for 8.0 in the 7.0, 7.1 and 7.2 notes, so they go with it.)
Do my styles, environment variables or API key change?
No. The class names, the brand tokens and the credential are all as they were. See What moved.
Did anything else leave site-kit in 8.0?
Only what was removed. Every other entry works as it did in 7.4, including the deprecated aliases for renamed modules (./middleware, ./sitemap, ./robots, ./redirects, ./og, ./llms, ./images, ./slots, ./landing and ./cta-bar), because sites still import them. Earlier notes said those would go in 8.0; they stay, and will go in a later major once sites have moved off them. Migrating to 7 lists them, and the codemod (npx sonor-setup codemod --write) that moves a site onto their new homes.
Where are the commerce docs now?
At sonor.dev/commerce-kit: Commerce, Memberships and the changelog.