@decocms/apps 1.12.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,9 +3,13 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@decocms/apps.svg)](https://www.npmjs.com/package/@decocms/apps)
4
4
  [![license](https://img.shields.io/npm/l/@decocms/apps.svg)](https://github.com/decocms/apps-start/blob/main/LICENSE)
5
5
 
6
- Commerce integrations for [Deco](https://deco.cx) storefronts on **TanStack Start + React 19 + Cloudflare Workers**.
6
+ Commerce integrations for [deco.cx](https://deco.cx) storefronts on **TanStack Start + React 19 + Cloudflare Workers**.
7
7
 
8
- Provides VTEX and Shopify loaders, actions, hooks, and shared commerce types based on schema.org. Built on top of [`@decocms/start`](https://www.npmjs.com/package/@decocms/start).
8
+ `@decocms/apps` provides VTEX, Shopify, and Resend integrations (loaders, actions, hooks, middleware) plus shared schema.org commerce types. It depends on [`@decocms/start`](https://www.npmjs.com/package/@decocms/start).
9
+
10
+ 📖 **[Read the full documentation →](https://docs.deco.cx/v2/en/commerce/overview)**
11
+
12
+ ---
9
13
 
10
14
  ## Install
11
15
 
@@ -13,55 +17,192 @@ Provides VTEX and Shopify loaders, actions, hooks, and shared commerce types bas
13
17
  npm install @decocms/apps
14
18
  ```
15
19
 
16
- ## Integrations
20
+ ---
21
+
22
+ ## Minimum wiring
17
23
 
18
24
  ### VTEX
19
25
 
20
- Full VTEX Intelligent Search and Checkout integration.
26
+ A working VTEX storefront needs three things: a `deco-vtex` config block, an `initVtexFromBlocks()` call in setup, and the commerce loader registry.
27
+
28
+ #### 1. Config block (`.deco/blocks/deco-vtex.json`)
29
+
30
+ ```json
31
+ {
32
+ "__resolveType": "deco-vtex",
33
+ "account": "my-store",
34
+ "publicUrl": "https://www.my-store.com.br",
35
+ "salesChannel": "1",
36
+ "appKey": { "__resolveType": "secret/key" },
37
+ "appToken": { "__resolveType": "secret/key" }
38
+ }
39
+ ```
40
+
41
+ #### 2. Setup (`src/setup.ts`)
42
+
43
+ ```ts
44
+ import { createSiteSetup } from "@decocms/start/setup";
45
+ import { createInstrumentedFetch } from "@decocms/start/sdk/instrumentedFetch";
46
+ import { initVtexFromBlocks, setVtexFetch } from "@decocms/apps/vtex/client";
47
+ import { createVtexCommerceLoaders } from "@decocms/apps/vtex/commerceLoaders";
48
+
49
+ createSiteSetup({
50
+ sections: import.meta.glob("./sections/**/*.tsx", { eager: true }),
51
+ blocks,
52
+ meta: () => meta,
53
+ initPlatform: () => initVtexFromBlocks(),
54
+ getCommerceLoaders: () => createVtexCommerceLoaders(),
55
+ });
56
+
57
+ setVtexFetch(createInstrumentedFetch("vtex"));
58
+ ```
59
+
60
+ #### 3. Hooks in components
61
+
62
+ ```tsx
63
+ import { useCart, useUser, useWishlist } from "@decocms/apps/vtex/hooks";
64
+
65
+ function AddToCartButton({ sku }: { sku: string }) {
66
+ const { addItems, isMutating } = useCart();
67
+ return (
68
+ <button
69
+ onClick={() => addItems([{ id: sku, quantity: 1 }])}
70
+ disabled={isMutating}
71
+ >
72
+ Add to cart
73
+ </button>
74
+ );
75
+ }
76
+ ```
21
77
 
22
- | Import | Purpose |
23
- |--------|---------|
24
- | `@decocms/apps/vtex` | Configuration and setup |
25
- | `@decocms/apps/vtex/client` | VTEX API client with SWR caching |
26
- | `@decocms/apps/vtex/loaders/*` | Product, cart, search, catalog, session, wishlist |
27
- | `@decocms/apps/vtex/actions/*` | Checkout, auth, newsletter, profile, wishlist |
28
- | `@decocms/apps/vtex/hooks` | useCart, useUser, useWishlist, useAutocomplete |
29
- | `@decocms/apps/vtex/inline-loaders/*` | PDP, PLP, product list, suggestions |
30
- | `@decocms/apps/vtex/middleware` | Cookie propagation and session handling |
31
- | `@decocms/apps/vtex/invoke` | Server function wrappers |
32
- | `@decocms/apps/vtex/utils/*` | Transform, enrichment, segment, cookies |
78
+ That's it. Loaders are auto-registered, hooks are typed, edge cache + cookie propagation work out of the box.
33
79
 
34
80
  ### Shopify
35
81
 
36
- Storefront API integration via GraphQL.
82
+ ```ts
83
+ import { createSiteSetup } from "@decocms/start/setup";
84
+ import { initShopifyFromBlocks } from "@decocms/apps/shopify/client";
85
+ import { createShopifyCommerceLoaders } from "@decocms/apps/shopify/commerceLoaders";
86
+
87
+ createSiteSetup({
88
+ sections: import.meta.glob("./sections/**/*.tsx", { eager: true }),
89
+ blocks,
90
+ meta: () => meta,
91
+ initPlatform: () => initShopifyFromBlocks(),
92
+ getCommerceLoaders: () => createShopifyCommerceLoaders(),
93
+ });
94
+ ```
95
+
96
+ Config block (`deco-shopify`) needs `storeName`, `storefrontAccessToken`, `languageCode`, `countryCode`.
97
+
98
+ > ⚠️ Shopify cart loaders require **cart-cookie wiring** in your route handler. See [Shopify reference](https://docs.deco.cx/v2/en/commerce/shopify) for the canonical pattern.
99
+
100
+ ### Resend
101
+
102
+ ```ts
103
+ import { initResendFromBlocks } from "@decocms/apps/resend/client";
104
+ import { sendEmail } from "@decocms/apps/resend/sdk";
105
+
106
+ await sendEmail({
107
+ to: "customer@example.com",
108
+ subject: "Order confirmed",
109
+ html: "<h1>Thanks!</h1>",
110
+ });
111
+ ```
112
+
113
+ ---
114
+
115
+ ## What's exported
37
116
 
38
- | Import | Purpose |
39
- |--------|---------|
40
- | `@decocms/apps/shopify` | Configuration and setup |
41
- | `@decocms/apps/shopify/client` | Storefront GraphQL client |
42
- | `@decocms/apps/shopify/loaders/*` | PDP, PLP, product list, cart, user |
43
- | `@decocms/apps/shopify/actions/cart/*` | Add, update items, coupons |
44
- | `@decocms/apps/shopify/actions/user/*` | Sign in, sign up |
117
+ ### VTEX
118
+
119
+ | Subpath | Purpose |
120
+ |---------|---------|
121
+ | `@decocms/apps/vtex` | Barrel index |
122
+ | `@decocms/apps/vtex/client` | `vtexFetch`, `vtexFetchWithCookies`, `intelligentSearch`, `setVtexFetch`, `initVtexFromBlocks`, `configureVtex` |
123
+ | `@decocms/apps/vtex/commerceLoaders` | `createVtexCommerceLoaders` |
124
+ | `@decocms/apps/vtex/loaders/*` | Cart, user, wishlist, search, catalog, sessions, orders, autocomplete |
125
+ | `@decocms/apps/vtex/actions/*` | Cart mutations, auth, profile, address, wishlist, newsletter |
126
+ | `@decocms/apps/vtex/hooks` | `useCart`, `useUser`, `useWishlist`, `useAutocomplete`, plus `createUseCart` / `createUseUser` / `createUseWishlist` factories |
127
+ | `@decocms/apps/vtex/inline-loaders/*` | PDP, PLP, shelves, suggestions, minicart |
128
+ | `@decocms/apps/vtex/middleware` | `extractVtexContext`, `vtexCacheKeySuffix`, `propagateISCookies`, `createVtexCheckoutProxy` |
129
+ | `@decocms/apps/vtex/utils/*` | Transform, segment, cookies, slugCache, sortwhitelist |
130
+
131
+ > 💡 **Calling VTEX loaders/actions from the client.** Use the typed `invoke` client generated by `@decocms/start` — `invoke["vtex/loaders/cart.ts"](props)` — or use the React hooks above. There is **no** `@decocms/apps/vtex/invoke` subpath.
132
+
133
+ ### Shopify
134
+
135
+ | Subpath | Purpose |
136
+ |---------|---------|
137
+ | `@decocms/apps/shopify` | Barrel |
138
+ | `@decocms/apps/shopify/client` | `setShopifyFetch`, GraphQL helpers |
139
+ | `@decocms/apps/shopify/loaders/*` | PDP, PLP, ProductList, RelatedProducts, Cart, Account |
140
+ | `@decocms/apps/shopify/actions/cart/*` | `addItems`, `updateItems`, `discountCodesUpdate` |
141
+ | `@decocms/apps/shopify/actions/user/*` | `signIn`, `signUp` |
45
142
  | `@decocms/apps/shopify/utils/*` | Transform, cookies, GraphQL queries |
46
143
 
47
- ### Shared Commerce
144
+ ### Resend
48
145
 
49
- Platform-agnostic types and utilities.
146
+ | Subpath | Purpose |
147
+ |---------|---------|
148
+ | `@decocms/apps/resend/client` | `initResendFromBlocks` |
149
+ | `@decocms/apps/resend/sdk` | `sendEmail` |
150
+ | `@decocms/apps/resend/actions/send` | Invocable email action |
50
151
 
51
- | Import | Purpose |
52
- |--------|---------|
53
- | `@decocms/apps/commerce/types` | schema.org Product, Offer, BreadcrumbList, etc. |
54
- | `@decocms/apps/commerce/components/Image` | Optimized commerce image component |
152
+ ### Shared commerce
153
+
154
+ Platform-agnostic types and components.
155
+
156
+ | Subpath | Purpose |
157
+ |---------|---------|
158
+ | `@decocms/apps/commerce/types` | schema.org `Product`, `ProductDetailsPage`, `ProductListingPage`, `Offer`, `BreadcrumbList`, etc. |
159
+ | `@decocms/apps/commerce/components/Image` | Optimized commerce image with CDN routing |
160
+ | `@decocms/apps/commerce/components/Picture` | `<picture>` with responsive sources |
55
161
  | `@decocms/apps/commerce/components/JsonLd` | Structured data for SEO |
56
- | `@decocms/apps/commerce/sdk/*` | useOffer, formatPrice, analytics, URL utils |
57
- | `@decocms/apps/commerce/utils/*` | productToAnalyticsItem, canonical, stateByZip |
162
+ | `@decocms/apps/commerce/sdk/useOffer` | Pick the best offer per region/seller |
163
+ | `@decocms/apps/commerce/sdk/format` | `formatPrice`, `formatPriceRange` |
164
+ | `@decocms/apps/commerce/sdk/analytics` | Event types + `mapProductToAnalyticsItem` |
165
+ | `@decocms/apps/commerce/sdk/useVariantPossibilities` | Variant axis builder for selectors |
166
+
167
+ ### Website (utility app)
168
+
169
+ | Subpath | Purpose |
170
+ |---------|---------|
171
+ | `@decocms/apps/website` | `configureWebsite`, `configureSeo` |
172
+ | `@decocms/apps/website/loaders/redirectsFromCsv` | Bulk redirects from CSV |
173
+ | `@decocms/apps/website/loaders/fonts/*` | Google fonts, custom CDN font loaders |
174
+
175
+ Complete export tables: [docs.deco.cx/v2/en/reference/commerce-exports](https://docs.deco.cx/v2/en/reference/commerce-exports).
58
176
 
59
- ## Peer Dependencies
177
+ ---
60
178
 
61
- - `@decocms/start` >= 0.19.0
62
- - `@tanstack/react-query` >= 5
63
- - `react` >= 18
64
- - `react-dom` >= 18
179
+ ## Documentation
180
+
181
+ The commerce documentation lives at **[docs.deco.cx/v2/en/commerce](https://docs.deco.cx/v2/en/commerce/overview)**:
182
+
183
+ - [VTEX overview](https://docs.deco.cx/v2/en/commerce/vtex-overview) — config block, secrets, install steps.
184
+ - [VTEX loaders & actions](https://docs.deco.cx/v2/en/commerce/vtex-loaders-and-actions) — input/output cookbook.
185
+ - [VTEX hooks](https://docs.deco.cx/v2/en/commerce/vtex-hooks) — `useCart`, `useUser`, `useWishlist`, `useAutocomplete`.
186
+ - [VTEX gotchas](https://docs.deco.cx/v2/en/commerce/vtex-gotchas) — cookies, sales channel, regionId, IS sort sanitization.
187
+ - [Shopify](https://docs.deco.cx/v2/en/commerce/shopify) — configure, loaders, actions, cart-cookie wiring.
188
+ - [Resend](https://docs.deco.cx/v2/en/commerce/resend) — email setup.
189
+
190
+ ---
191
+
192
+ ## Peer dependencies
193
+
194
+ ```json
195
+ {
196
+ "@decocms/start": ">=2.0.0",
197
+ "@tanstack/react-query": ">=5.0.0",
198
+ "react": ">=19.0.0",
199
+ "react-dom": ">=19.0.0"
200
+ }
201
+ ```
202
+
203
+ The published peer floor is React 18 to ease incremental migration, but the v2 stack assumes React 19 + the React Compiler.
204
+
205
+ ---
65
206
 
66
207
  ## Development
67
208
 
@@ -70,6 +211,10 @@ npm run typecheck # tsc --noEmit
70
211
  npm run check # typecheck + unused export detection
71
212
  ```
72
213
 
214
+ This is a library — there is no dev server. Consumer storefronts run their own `vite dev`.
215
+
216
+ ---
217
+
73
218
  ## License
74
219
 
75
220
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/apps",
3
- "version": "1.12.1",
3
+ "version": "1.13.0",
4
4
  "type": "module",
5
5
  "description": "Deco commerce apps for TanStack Start - Shopify, VTEX, commerce types, analytics utils",
6
6
  "exports": {
@@ -17,12 +17,14 @@ export interface PDPProps {
17
17
  indexingSkus?: boolean;
18
18
  /** Use product.description instead of metaTagDescription for SEO */
19
19
  preferDescription?: boolean;
20
+ /** Use lean variant transform (no images/video) for hasVariant[]. Defaults to true. */
21
+ leanVariants?: boolean;
20
22
  }
21
23
 
22
24
  export default async function vtexProductDetailsPage(
23
25
  props: PDPProps,
24
26
  ): Promise<ProductDetailsPage | null> {
25
- const { slug, skuId, indexingSkus, preferDescription } = props;
27
+ const { slug, skuId, indexingSkus, preferDescription, leanVariants = true } = props;
26
28
  if (!slug) return null;
27
29
 
28
30
  try {
@@ -53,7 +55,7 @@ export default async function vtexProductDetailsPage(
53
55
  const page = toProductPage(product, sku, kitItems, {
54
56
  baseUrl,
55
57
  priceCurrency: "BRL",
56
- leanVariants: true,
58
+ leanVariants,
57
59
  });
58
60
 
59
61
  return {