@techsio/storefront-data
Version:
Medusa-first storefront data layer built on TanStack Query.
210 lines (152 loc) • 5.97 kB
Markdown
---
name: setup-storefront-platform-in-next-app
description: >
Load this skill when wiring @techsio/storefront-data into a Next.js App
Router storefront through createMedusaStorefrontPreset,
StorefrontDataProvider, createMedusaSdk, createLocalStorageValueStore, and
explicit subpath imports. Use it for the app-level composition module,
provider placement, browser storage seams, and avoiding package-root or
ad-hoc preset wiring.
type: framework
library: "@techsio/storefront-data"
framework: react
library_version: "0.1.0"
requires: []
sources:
- "TechsioCZ/new-engine:libs/storefront-data/README.md"
- "TechsioCZ/new-engine:libs/storefront-data/AGENTS.md"
- "TechsioCZ/new-engine:libs/storefront-data/package.json"
- "TechsioCZ/new-engine:libs/storefront-data/src/shared/medusa-client.ts"
- "TechsioCZ/new-engine:libs/storefront-data/src/shared/storage-value-store.ts"
- "TechsioCZ/new-engine:libs/storefront-data/src/shared/query-client.ts"
- "TechsioCZ/new-engine:libs/storefront-data/src/client/provider.tsx"
- "TechsioCZ/new-engine:libs/storefront-data/src/medusa/preset.ts"
---
# Setup storefront platform in Next app
## Setup
Use one thin storefront composition module, one app-level provider boundary, and explicit file-level imports.
```js
// next.config.mjs
const nextConfig = {
transpilePackages: ["@techsio/storefront-data"],
}
export default nextConfig
```
```ts
// src/lib/storefront.ts
import { createMedusaSdk } from "@techsio/storefront-data/shared/medusa-client"
import { createLocalStorageValueStore } from "@techsio/storefront-data/shared/storage-value-store"
import { createMedusaStorefrontPreset } from "@techsio/storefront-data/medusa/preset"
const sdk = createMedusaSdk({
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL ?? "http://localhost:9000",
publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY ?? "",
})
const cartStorage = createLocalStorageValueStore({
key: "shop-cart-id",
})
export const storefront = createMedusaStorefrontPreset({
sdk,
queryKeyNamespace: "shop",
cart: {
hooks: {
cartStorage,
},
},
})
```
```tsx
// app/providers.tsx
"use client"
import type { PropsWithChildren } from "react"
import { StorefrontDataProvider } from "@techsio/storefront-data/client/provider"
export function Providers({ children }: PropsWithChildren) {
return <StorefrontDataProvider>{children}</StorefrontDataProvider>
}
```
## Hooks and Components
### Expose only the preset surface the app actually needs
```ts
// src/lib/storefront-surface.ts
import { storefront } from "@/src/lib/storefront"
export const { auth, cart, catalog, checkout, collections, products, regions } =
storefront.hooks
export const { cart: cartFlow, checkout: checkoutFlow } = storefront.flows
```
Keep this layer thin. SDK config, local field defaults, address adapters, and storefront-specific policy belong here. Query keys, services, hooks, and flows stay owned by the preset.
### Pass a stable browser QueryClient only when the app really needs overrides
```tsx
// app/providers.tsx
"use client"
import type { PropsWithChildren } from "react"
import { StorefrontDataProvider } from "@techsio/storefront-data/client/provider"
import { getQueryClient } from "@techsio/storefront-data/shared/query-client"
const client = getQueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
},
},
})
export function Providers({ children }: PropsWithChildren) {
return <StorefrontDataProvider client={client}>{children}</StorefrontDataProvider>
}
```
If the app does not need browser-client overrides, keep the provider as `<StorefrontDataProvider>{children}</StorefrontDataProvider>`.
## Common Mistakes
### CRITICAL Package-root imports
Wrong:
```ts
import { StorefrontDataProvider } from "@techsio/storefront-data"
```
Correct:
```ts
import { StorefrontDataProvider } from "@techsio/storefront-data/client/provider"
import { createMedusaStorefrontPreset } from "@techsio/storefront-data/medusa/preset"
```
The root export is intentionally disabled. Treat explicit subpaths as the supported public surface.
Source: `libs/storefront-data/package.json`, `libs/storefront-data/README.md`
### HIGH Ad-hoc hook assembly instead of a preset
Wrong:
```ts
const products = createProductHooks({ service, queryKeyNamespace: "shop" })
const cart = createCartHooks({ service, queryKeyNamespace: "shop" })
```
Correct:
```ts
const storefront = createMedusaStorefrontPreset({
sdk,
queryKeyNamespace: "shop",
})
```
The current architecture expects one preset to own hooks, services, query keys, cache semantics, and flow wrappers for a storefront.
Source: `libs/storefront-data/README.md`, `libs/storefront-data/src/medusa/preset.ts`
### CRITICAL Server helpers inside client code
Wrong:
```tsx
"use client"
import { getServerQueryClient } from "@techsio/storefront-data/server/get-query-client"
```
Correct:
```tsx
"use client"
import { StorefrontDataProvider } from "@techsio/storefront-data/client/provider"
```
`server/get-query-client` guards against client usage because its request-scoped behavior only makes sense on the server.
Source: `libs/storefront-data/src/server/get-query-client.ts`
### HIGH Late provider config changes rebuild the browser client
Wrong:
```tsx
<StorefrontDataProvider clientConfig={{ defaultOptions: { queries: { staleTime: 0 } } }}>
{children}
</StorefrontDataProvider>
```
Correct:
```tsx
const client = getQueryClient({
defaultOptions: { queries: { staleTime: 0 } },
})
<StorefrontDataProvider client={client}>{children}</StorefrontDataProvider>
```
The internal browser QueryClient is a singleton. Only the first internal initialization sees `clientConfig`.
Source: `libs/storefront-data/src/client/provider.tsx`, `libs/storefront-data/src/shared/query-client.ts`
See also: `implement-ssr-prefetch-and-query-client-boundaries` for server-side hydration and query-client ownership.