Biome bans vendor imports in shop UI

Shop components imported Centra and Sanity view types directly. StorefrontDto mappers plus Biome noRestrictedImports keep vendor shapes out of the UI layer.

Sander Korf2 min read
centrasanitybiometypescript

Next.js storefront monorepo. @repo/shop compositions sit above Centra commerce and Sanity CMS. Product cards, basket drawers, checkout steps live in packages/shop/src/components. They used to import @repo/centra views and @repo/sanity/view directly.

That felt fast until a Centra field rename broke a product card. Or a Sanity block type leaked into a checkout molecule. Vendor shapes in the UI layer mean every API drift becomes a JSX chase. Basket and CheckoutDraft were especially painful: half the props were Centra selection types with names I did not want on a storefront contract.

The fix is two layers, not one big refactor. Thin shop mappers expose Basket, CheckoutDraft, and settings as StorefrontDto types via ReturnType inference. No hand-rolled field bags. No re-exporting vendor types from shop. Compositions only see what the storefront needs.

Biome noRestrictedImports bans @repo/centra/** and @repo/sanity/view/** under packages/shop/src/components. Mappers and services still import vendors. Live preview and image adapters stay on an allowlist because they are adapters, not product UI.

export function mapBasket(...args: Parameters<typeof mapCartSelection>) {
	return mapCartSelection(...args);
}
export type BasketDto = ReturnType<typeof mapBasket>;
 
// biome.jsonc on packages/shop/src/components:
// noRestrictedImports: @repo/centra/**, @repo/sanity/view/**

When Centra changes a cart field, I touch the mapper once. The linter stops the next developer from importing SelectionLine into a card component because it was convenient for five minutes. Convenience is how vendor APIs become your public API.


Happy coding! Sander