@doswiftly/cli 0.1.1

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.
Files changed (453) hide show
  1. package/README.md +357 -0
  2. package/bin/doswiftly.js +2 -0
  3. package/dist/commands/auth-github.d.ts +6 -0
  4. package/dist/commands/auth-github.d.ts.map +1 -0
  5. package/dist/commands/auth-github.js +89 -0
  6. package/dist/commands/auth-github.js.map +1 -0
  7. package/dist/commands/auth-token.d.ts +12 -0
  8. package/dist/commands/auth-token.d.ts.map +1 -0
  9. package/dist/commands/auth-token.js +43 -0
  10. package/dist/commands/auth-token.js.map +1 -0
  11. package/dist/commands/auth.d.ts +22 -0
  12. package/dist/commands/auth.d.ts.map +1 -0
  13. package/dist/commands/auth.js +348 -0
  14. package/dist/commands/auth.js.map +1 -0
  15. package/dist/commands/check.d.ts +5 -0
  16. package/dist/commands/check.d.ts.map +1 -0
  17. package/dist/commands/check.js +234 -0
  18. package/dist/commands/check.js.map +1 -0
  19. package/dist/commands/config.d.ts +3 -0
  20. package/dist/commands/config.d.ts.map +1 -0
  21. package/dist/commands/config.js +104 -0
  22. package/dist/commands/config.js.map +1 -0
  23. package/dist/commands/deploy.d.ts +37 -0
  24. package/dist/commands/deploy.d.ts.map +1 -0
  25. package/dist/commands/deploy.js +580 -0
  26. package/dist/commands/deploy.js.map +1 -0
  27. package/dist/commands/dev.d.ts +8 -0
  28. package/dist/commands/dev.d.ts.map +1 -0
  29. package/dist/commands/dev.js +83 -0
  30. package/dist/commands/dev.js.map +1 -0
  31. package/dist/commands/doctor.d.ts +5 -0
  32. package/dist/commands/doctor.d.ts.map +1 -0
  33. package/dist/commands/doctor.js +363 -0
  34. package/dist/commands/doctor.js.map +1 -0
  35. package/dist/commands/domain.d.ts +13 -0
  36. package/dist/commands/domain.d.ts.map +1 -0
  37. package/dist/commands/domain.js +128 -0
  38. package/dist/commands/domain.js.map +1 -0
  39. package/dist/commands/env.d.ts +25 -0
  40. package/dist/commands/env.d.ts.map +1 -0
  41. package/dist/commands/env.js +228 -0
  42. package/dist/commands/env.js.map +1 -0
  43. package/dist/commands/init.d.ts +11 -0
  44. package/dist/commands/init.d.ts.map +1 -0
  45. package/dist/commands/init.js +1028 -0
  46. package/dist/commands/init.js.map +1 -0
  47. package/dist/commands/inspect.d.ts +12 -0
  48. package/dist/commands/inspect.d.ts.map +1 -0
  49. package/dist/commands/inspect.js +162 -0
  50. package/dist/commands/inspect.js.map +1 -0
  51. package/dist/commands/migrate.d.ts +18 -0
  52. package/dist/commands/migrate.d.ts.map +1 -0
  53. package/dist/commands/migrate.js +355 -0
  54. package/dist/commands/migrate.js.map +1 -0
  55. package/dist/commands/preview.d.ts +29 -0
  56. package/dist/commands/preview.d.ts.map +1 -0
  57. package/dist/commands/preview.js +199 -0
  58. package/dist/commands/preview.js.map +1 -0
  59. package/dist/commands/proxy.d.ts +9 -0
  60. package/dist/commands/proxy.d.ts.map +1 -0
  61. package/dist/commands/proxy.js +37 -0
  62. package/dist/commands/proxy.js.map +1 -0
  63. package/dist/commands/sdk.d.ts +5 -0
  64. package/dist/commands/sdk.d.ts.map +1 -0
  65. package/dist/commands/sdk.js +82 -0
  66. package/dist/commands/sdk.js.map +1 -0
  67. package/dist/commands/template.d.ts +107 -0
  68. package/dist/commands/template.d.ts.map +1 -0
  69. package/dist/commands/template.js +1309 -0
  70. package/dist/commands/template.js.map +1 -0
  71. package/dist/commands/types.d.ts +5 -0
  72. package/dist/commands/types.d.ts.map +1 -0
  73. package/dist/commands/types.js +82 -0
  74. package/dist/commands/types.js.map +1 -0
  75. package/dist/commands/update.d.ts +2 -0
  76. package/dist/commands/update.d.ts.map +1 -0
  77. package/dist/commands/update.js +103 -0
  78. package/dist/commands/update.js.map +1 -0
  79. package/dist/commands/upgrade.d.ts +18 -0
  80. package/dist/commands/upgrade.d.ts.map +1 -0
  81. package/dist/commands/upgrade.js +55 -0
  82. package/dist/commands/upgrade.js.map +1 -0
  83. package/dist/commands/verify.d.ts +5 -0
  84. package/dist/commands/verify.d.ts.map +1 -0
  85. package/dist/commands/verify.js +232 -0
  86. package/dist/commands/verify.js.map +1 -0
  87. package/dist/commands/whoami.d.ts +5 -0
  88. package/dist/commands/whoami.d.ts.map +1 -0
  89. package/dist/commands/whoami.js +60 -0
  90. package/dist/commands/whoami.js.map +1 -0
  91. package/dist/config/types.d.ts +173 -0
  92. package/dist/config/types.d.ts.map +1 -0
  93. package/dist/config/types.js +48 -0
  94. package/dist/config/types.js.map +1 -0
  95. package/dist/index.d.ts +3 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +416 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/lib/api-url.d.ts +14 -0
  100. package/dist/lib/api-url.d.ts.map +1 -0
  101. package/dist/lib/api-url.js +24 -0
  102. package/dist/lib/api-url.js.map +1 -0
  103. package/dist/lib/api.d.ts +67 -0
  104. package/dist/lib/api.d.ts.map +1 -0
  105. package/dist/lib/api.js +36 -0
  106. package/dist/lib/api.js.map +1 -0
  107. package/dist/lib/config.d.ts +39 -0
  108. package/dist/lib/config.d.ts.map +1 -0
  109. package/dist/lib/config.js +195 -0
  110. package/dist/lib/config.js.map +1 -0
  111. package/dist/lib/env-storage.d.ts +140 -0
  112. package/dist/lib/env-storage.d.ts.map +1 -0
  113. package/dist/lib/env-storage.js +464 -0
  114. package/dist/lib/env-storage.js.map +1 -0
  115. package/dist/lib/errors.d.ts +61 -0
  116. package/dist/lib/errors.d.ts.map +1 -0
  117. package/dist/lib/errors.js +204 -0
  118. package/dist/lib/errors.js.map +1 -0
  119. package/dist/lib/i18n.d.ts +99 -0
  120. package/dist/lib/i18n.d.ts.map +1 -0
  121. package/dist/lib/i18n.js +184 -0
  122. package/dist/lib/i18n.js.map +1 -0
  123. package/dist/lib/logger.d.ts +95 -0
  124. package/dist/lib/logger.d.ts.map +1 -0
  125. package/dist/lib/logger.js +168 -0
  126. package/dist/lib/logger.js.map +1 -0
  127. package/dist/lib/package-manager.d.ts +91 -0
  128. package/dist/lib/package-manager.d.ts.map +1 -0
  129. package/dist/lib/package-manager.js +205 -0
  130. package/dist/lib/package-manager.js.map +1 -0
  131. package/dist/lib/proxy-server.d.ts +24 -0
  132. package/dist/lib/proxy-server.d.ts.map +1 -0
  133. package/dist/lib/proxy-server.js +173 -0
  134. package/dist/lib/proxy-server.js.map +1 -0
  135. package/dist/lib/select-with-back.d.ts +34 -0
  136. package/dist/lib/select-with-back.d.ts.map +1 -0
  137. package/dist/lib/select-with-back.js +94 -0
  138. package/dist/lib/select-with-back.js.map +1 -0
  139. package/dist/lib/shared-api-client.d.ts +40 -0
  140. package/dist/lib/shared-api-client.d.ts.map +1 -0
  141. package/dist/lib/shared-api-client.js +92 -0
  142. package/dist/lib/shared-api-client.js.map +1 -0
  143. package/dist/lib/wizard-engine.d.ts +128 -0
  144. package/dist/lib/wizard-engine.d.ts.map +1 -0
  145. package/dist/lib/wizard-engine.js +168 -0
  146. package/dist/lib/wizard-engine.js.map +1 -0
  147. package/package.json +85 -0
  148. package/templates/storefront-minimal/.env.example +10 -0
  149. package/templates/storefront-minimal/.github/workflows/build-template.yml +109 -0
  150. package/templates/storefront-minimal/app/globals.css +18 -0
  151. package/templates/storefront-minimal/app/layout.tsx +26 -0
  152. package/templates/storefront-minimal/app/page.tsx +93 -0
  153. package/templates/storefront-minimal/lib/graphql-client.ts +23 -0
  154. package/templates/storefront-minimal/next.config.ts +15 -0
  155. package/templates/storefront-minimal/open-next.config.ts +3 -0
  156. package/templates/storefront-minimal/package.json +30 -0
  157. package/templates/storefront-minimal/postcss.config.mjs +5 -0
  158. package/templates/storefront-minimal/tailwind.config.ts +14 -0
  159. package/templates/storefront-minimal/tsconfig.json +27 -0
  160. package/templates/storefront-minimal/wrangler.toml +9 -0
  161. package/templates/storefront-nextjs/.env.example +68 -0
  162. package/templates/storefront-nextjs/.github/workflows/build-template.yml +109 -0
  163. package/templates/storefront-nextjs/.github/workflows/deploy.yml +25 -0
  164. package/templates/storefront-nextjs/.github/workflows/preview.yml +22 -0
  165. package/templates/storefront-nextjs/README.md +520 -0
  166. package/templates/storefront-nextjs/app/account/orders/page.tsx +216 -0
  167. package/templates/storefront-nextjs/app/account/page.tsx +167 -0
  168. package/templates/storefront-nextjs/app/auth/login/page.tsx +135 -0
  169. package/templates/storefront-nextjs/app/auth/register/page.tsx +228 -0
  170. package/templates/storefront-nextjs/app/cart/page.tsx +263 -0
  171. package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +200 -0
  172. package/templates/storefront-nextjs/app/categories/page.tsx +58 -0
  173. package/templates/storefront-nextjs/app/checkout/page.tsx +351 -0
  174. package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +158 -0
  175. package/templates/storefront-nextjs/app/collections/page.tsx +61 -0
  176. package/templates/storefront-nextjs/app/globals.css +98 -0
  177. package/templates/storefront-nextjs/app/layout.tsx +39 -0
  178. package/templates/storefront-nextjs/app/page.tsx +136 -0
  179. package/templates/storefront-nextjs/app/products/[slug]/page.tsx +119 -0
  180. package/templates/storefront-nextjs/app/products/page.tsx +107 -0
  181. package/templates/storefront-nextjs/app/search/page.tsx +127 -0
  182. package/templates/storefront-nextjs/components/auth/auth-guard.tsx +94 -0
  183. package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +77 -0
  184. package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +29 -0
  185. package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +217 -0
  186. package/templates/storefront-nextjs/components/commerce/pagination.tsx +62 -0
  187. package/templates/storefront-nextjs/components/commerce/product-actions.tsx +135 -0
  188. package/templates/storefront-nextjs/components/commerce/product-filters.tsx +109 -0
  189. package/templates/storefront-nextjs/components/commerce/product-price.tsx +375 -0
  190. package/templates/storefront-nextjs/components/commerce/search-input.tsx +178 -0
  191. package/templates/storefront-nextjs/components/commerce/sort-select.tsx +64 -0
  192. package/templates/storefront-nextjs/components/commerce/variant-selector.tsx +210 -0
  193. package/templates/storefront-nextjs/components/layout/footer.tsx +107 -0
  194. package/templates/storefront-nextjs/components/layout/header.tsx +104 -0
  195. package/templates/storefront-nextjs/components/providers.tsx +62 -0
  196. package/templates/storefront-nextjs/lib/auth/routes.ts +52 -0
  197. package/templates/storefront-nextjs/lib/currency.tsx +140 -0
  198. package/templates/storefront-nextjs/lib/format.ts +159 -0
  199. package/templates/storefront-nextjs/lib/graphql-queries.ts +629 -0
  200. package/templates/storefront-nextjs/lib/hooks.ts +30 -0
  201. package/templates/storefront-nextjs/middleware.ts +80 -0
  202. package/templates/storefront-nextjs/next.config.ts +37 -0
  203. package/templates/storefront-nextjs/open-next.config.ts +3 -0
  204. package/templates/storefront-nextjs/package.dev.json +30 -0
  205. package/templates/storefront-nextjs/package.json +32 -0
  206. package/templates/storefront-nextjs/package.json.template +32 -0
  207. package/templates/storefront-nextjs/postcss.config.mjs +8 -0
  208. package/templates/storefront-nextjs/tailwind.config.ts +111 -0
  209. package/templates/storefront-nextjs/tsconfig.json +27 -0
  210. package/templates/storefront-nextjs/wrangler.toml +9 -0
  211. package/templates/storefront-nextjs-shadcn/.env.example +68 -0
  212. package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +109 -0
  213. package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +25 -0
  214. package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +22 -0
  215. package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +282 -0
  216. package/templates/storefront-nextjs-shadcn/CLAUDE.md +96 -0
  217. package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +190 -0
  218. package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +263 -0
  219. package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +135 -0
  220. package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +142 -0
  221. package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +448 -0
  222. package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +307 -0
  223. package/templates/storefront-nextjs-shadcn/README.md +195 -0
  224. package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +245 -0
  225. package/templates/storefront-nextjs-shadcn/app/about/page.tsx +34 -0
  226. package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +215 -0
  227. package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +484 -0
  228. package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +128 -0
  229. package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/tracking/page.tsx +206 -0
  230. package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +80 -0
  231. package/templates/storefront-nextjs-shadcn/app/account/page.tsx +107 -0
  232. package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +195 -0
  233. package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +87 -0
  234. package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +125 -0
  235. package/templates/storefront-nextjs-shadcn/app/auth/forgot-password/page.tsx +131 -0
  236. package/templates/storefront-nextjs-shadcn/app/auth/login/page.tsx +24 -0
  237. package/templates/storefront-nextjs-shadcn/app/auth/register/page.tsx +20 -0
  238. package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +323 -0
  239. package/templates/storefront-nextjs-shadcn/app/blog/page.tsx +159 -0
  240. package/templates/storefront-nextjs-shadcn/app/brands/[slug]/page.tsx +170 -0
  241. package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +73 -0
  242. package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +165 -0
  243. package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +78 -0
  244. package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +75 -0
  245. package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +1752 -0
  246. package/templates/storefront-nextjs-shadcn/app/checkout/success/[orderId]/page.tsx +256 -0
  247. package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +74 -0
  248. package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +75 -0
  249. package/templates/storefront-nextjs-shadcn/app/contact/page.tsx +114 -0
  250. package/templates/storefront-nextjs-shadcn/app/error.tsx +90 -0
  251. package/templates/storefront-nextjs-shadcn/app/globals.css +125 -0
  252. package/templates/storefront-nextjs-shadcn/app/layout.tsx +57 -0
  253. package/templates/storefront-nextjs-shadcn/app/not-found.tsx +68 -0
  254. package/templates/storefront-nextjs-shadcn/app/page.tsx +21 -0
  255. package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +246 -0
  256. package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +343 -0
  257. package/templates/storefront-nextjs-shadcn/app/products/page.tsx +25 -0
  258. package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +192 -0
  259. package/templates/storefront-nextjs-shadcn/app/returns/page.tsx +77 -0
  260. package/templates/storefront-nextjs-shadcn/app/robots.ts +53 -0
  261. package/templates/storefront-nextjs-shadcn/app/search/page.tsx +16 -0
  262. package/templates/storefront-nextjs-shadcn/app/search/search-client.tsx +47 -0
  263. package/templates/storefront-nextjs-shadcn/app/shipping/page.tsx +62 -0
  264. package/templates/storefront-nextjs-shadcn/app/sitemap.ts +144 -0
  265. package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +179 -0
  266. package/templates/storefront-nextjs-shadcn/codegen.ts +51 -0
  267. package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +348 -0
  268. package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +144 -0
  269. package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +258 -0
  270. package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +107 -0
  271. package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +132 -0
  272. package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +188 -0
  273. package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +305 -0
  274. package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +240 -0
  275. package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +177 -0
  276. package/templates/storefront-nextjs-shadcn/components/blog/index.ts +8 -0
  277. package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +119 -0
  278. package/templates/storefront-nextjs-shadcn/components/brand/brand-grid.tsx +64 -0
  279. package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +140 -0
  280. package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +48 -0
  281. package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +112 -0
  282. package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +84 -0
  283. package/templates/storefront-nextjs-shadcn/components/cart/index.ts +17 -0
  284. package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +121 -0
  285. package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +162 -0
  286. package/templates/storefront-nextjs-shadcn/components/checkout/index.ts +25 -0
  287. package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +187 -0
  288. package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +160 -0
  289. package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +154 -0
  290. package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +225 -0
  291. package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +62 -0
  292. package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +158 -0
  293. package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +174 -0
  294. package/templates/storefront-nextjs-shadcn/components/commerce/variant-selector.tsx +210 -0
  295. package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +97 -0
  296. package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +187 -0
  297. package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +151 -0
  298. package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +166 -0
  299. package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +245 -0
  300. package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +246 -0
  301. package/templates/storefront-nextjs-shadcn/components/discount/index.ts +19 -0
  302. package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +113 -0
  303. package/templates/storefront-nextjs-shadcn/components/error/index.ts +7 -0
  304. package/templates/storefront-nextjs-shadcn/components/filters/attribute-filter.tsx +153 -0
  305. package/templates/storefront-nextjs-shadcn/components/filters/checkbox-group-filter.tsx +167 -0
  306. package/templates/storefront-nextjs-shadcn/components/filters/color-swatch-filter.tsx +176 -0
  307. package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +220 -0
  308. package/templates/storefront-nextjs-shadcn/components/filters/index.ts +36 -0
  309. package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +193 -0
  310. package/templates/storefront-nextjs-shadcn/components/filters/toggle-filter.tsx +132 -0
  311. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +321 -0
  312. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +309 -0
  313. package/templates/storefront-nextjs-shadcn/components/gift-card/index.ts +24 -0
  314. package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +72 -0
  315. package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +107 -0
  316. package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +85 -0
  317. package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +34 -0
  318. package/templates/storefront-nextjs-shadcn/components/home/index.ts +8 -0
  319. package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +108 -0
  320. package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +133 -0
  321. package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +341 -0
  322. package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +128 -0
  323. package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +147 -0
  324. package/templates/storefront-nextjs-shadcn/components/layout/index.ts +9 -0
  325. package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +211 -0
  326. package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +95 -0
  327. package/templates/storefront-nextjs-shadcn/components/layout/theme-switcher.tsx +192 -0
  328. package/templates/storefront-nextjs-shadcn/components/loyalty/index.ts +11 -0
  329. package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +93 -0
  330. package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +177 -0
  331. package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +250 -0
  332. package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +217 -0
  333. package/templates/storefront-nextjs-shadcn/components/loyalty/tier-badge.tsx +106 -0
  334. package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +131 -0
  335. package/templates/storefront-nextjs-shadcn/components/order/delivery-estimate.tsx +196 -0
  336. package/templates/storefront-nextjs-shadcn/components/order/index.ts +11 -0
  337. package/templates/storefront-nextjs-shadcn/components/order/order-tracking.tsx +200 -0
  338. package/templates/storefront-nextjs-shadcn/components/order/shipment-card.tsx +407 -0
  339. package/templates/storefront-nextjs-shadcn/components/order/tracking-status.tsx +222 -0
  340. package/templates/storefront-nextjs-shadcn/components/order/tracking-timeline.tsx +205 -0
  341. package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +161 -0
  342. package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +250 -0
  343. package/templates/storefront-nextjs-shadcn/components/product/discount-badge.tsx +196 -0
  344. package/templates/storefront-nextjs-shadcn/components/product/index.ts +41 -0
  345. package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +147 -0
  346. package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +217 -0
  347. package/templates/storefront-nextjs-shadcn/components/product/product-gallery.tsx +143 -0
  348. package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +83 -0
  349. package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +155 -0
  350. package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +158 -0
  351. package/templates/storefront-nextjs-shadcn/components/product/product-quantity-selector.tsx +111 -0
  352. package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +238 -0
  353. package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +58 -0
  354. package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +169 -0
  355. package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +220 -0
  356. package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +338 -0
  357. package/templates/storefront-nextjs-shadcn/components/product/review-summary.tsx +143 -0
  358. package/templates/storefront-nextjs-shadcn/components/product/sale-countdown.tsx +166 -0
  359. package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +213 -0
  360. package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +57 -0
  361. package/templates/storefront-nextjs-shadcn/components/product/stock-indicator.tsx +91 -0
  362. package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +103 -0
  363. package/templates/storefront-nextjs-shadcn/components/providers/index.ts +8 -0
  364. package/templates/storefront-nextjs-shadcn/components/providers/query-provider.tsx +260 -0
  365. package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +13 -0
  366. package/templates/storefront-nextjs-shadcn/components/returns/index.ts +26 -0
  367. package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +608 -0
  368. package/templates/storefront-nextjs-shadcn/components/returns/return-status-card.tsx +554 -0
  369. package/templates/storefront-nextjs-shadcn/components/search/index.ts +8 -0
  370. package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +140 -0
  371. package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +58 -0
  372. package/templates/storefront-nextjs-shadcn/components/search/search-suggestions.tsx +43 -0
  373. package/templates/storefront-nextjs-shadcn/components/seo/index.ts +12 -0
  374. package/templates/storefront-nextjs-shadcn/components/seo/json-ld.tsx +56 -0
  375. package/templates/storefront-nextjs-shadcn/components/seo/product-json-ld.ts +167 -0
  376. package/templates/storefront-nextjs-shadcn/components/shipping/index.ts +16 -0
  377. package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +337 -0
  378. package/templates/storefront-nextjs-shadcn/components/ui/accordion.tsx +153 -0
  379. package/templates/storefront-nextjs-shadcn/components/ui/alert.tsx +59 -0
  380. package/templates/storefront-nextjs-shadcn/components/ui/badge.tsx +34 -0
  381. package/templates/storefront-nextjs-shadcn/components/ui/button.tsx +51 -0
  382. package/templates/storefront-nextjs-shadcn/components/ui/card.tsx +77 -0
  383. package/templates/storefront-nextjs-shadcn/components/ui/checkbox.tsx +30 -0
  384. package/templates/storefront-nextjs-shadcn/components/ui/dialog.tsx +137 -0
  385. package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +207 -0
  386. package/templates/storefront-nextjs-shadcn/components/ui/index.ts +67 -0
  387. package/templates/storefront-nextjs-shadcn/components/ui/input.tsx +65 -0
  388. package/templates/storefront-nextjs-shadcn/components/ui/label.tsx +26 -0
  389. package/templates/storefront-nextjs-shadcn/components/ui/pagination.tsx +205 -0
  390. package/templates/storefront-nextjs-shadcn/components/ui/radio-group.tsx +44 -0
  391. package/templates/storefront-nextjs-shadcn/components/ui/select.tsx +160 -0
  392. package/templates/storefront-nextjs-shadcn/components/ui/separator.tsx +28 -0
  393. package/templates/storefront-nextjs-shadcn/components/ui/skeleton.tsx +20 -0
  394. package/templates/storefront-nextjs-shadcn/components/ui/spinner.tsx +82 -0
  395. package/templates/storefront-nextjs-shadcn/components/ui/tabs.tsx +119 -0
  396. package/templates/storefront-nextjs-shadcn/components/ui/toast.tsx +96 -0
  397. package/templates/storefront-nextjs-shadcn/components/wishlist/index.ts +9 -0
  398. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +148 -0
  399. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +47 -0
  400. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +165 -0
  401. package/templates/storefront-nextjs-shadcn/components.json +19 -0
  402. package/templates/storefront-nextjs-shadcn/generated/.gitkeep +2 -0
  403. package/templates/storefront-nextjs-shadcn/graphql/.gitkeep +31 -0
  404. package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +168 -0
  405. package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +160 -0
  406. package/templates/storefront-nextjs-shadcn/hooks/index.ts +9 -0
  407. package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +310 -0
  408. package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +286 -0
  409. package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +110 -0
  410. package/templates/storefront-nextjs-shadcn/hooks/use-filter-params.test.ts +173 -0
  411. package/templates/storefront-nextjs-shadcn/hooks/use-filter-params.ts +298 -0
  412. package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +220 -0
  413. package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +57 -0
  414. package/templates/storefront-nextjs-shadcn/lib/config.ts +46 -0
  415. package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +254 -0
  416. package/templates/storefront-nextjs-shadcn/lib/currency/README.md +464 -0
  417. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +328 -0
  418. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +295 -0
  419. package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +27 -0
  420. package/templates/storefront-nextjs-shadcn/lib/format.test.ts +397 -0
  421. package/templates/storefront-nextjs-shadcn/lib/format.ts +226 -0
  422. package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +109 -0
  423. package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +1183 -0
  424. package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +267 -0
  425. package/templates/storefront-nextjs-shadcn/lib/hooks.ts +30 -0
  426. package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +89 -0
  427. package/templates/storefront-nextjs-shadcn/lib/utils.ts +6 -0
  428. package/templates/storefront-nextjs-shadcn/next.config.ts +47 -0
  429. package/templates/storefront-nextjs-shadcn/open-next.config.ts +3 -0
  430. package/templates/storefront-nextjs-shadcn/package.dev.json +30 -0
  431. package/templates/storefront-nextjs-shadcn/package.json +60 -0
  432. package/templates/storefront-nextjs-shadcn/package.json.template +46 -0
  433. package/templates/storefront-nextjs-shadcn/postcss.config.mjs +8 -0
  434. package/templates/storefront-nextjs-shadcn/proxy.ts +80 -0
  435. package/templates/storefront-nextjs-shadcn/public/icons/payment/apple-pay.svg +8 -0
  436. package/templates/storefront-nextjs-shadcn/public/icons/payment/bank-transfer.svg +10 -0
  437. package/templates/storefront-nextjs-shadcn/public/icons/payment/blik.svg +6 -0
  438. package/templates/storefront-nextjs-shadcn/public/icons/payment/cash-on-delivery.svg +11 -0
  439. package/templates/storefront-nextjs-shadcn/public/icons/payment/google-pay.svg +11 -0
  440. package/templates/storefront-nextjs-shadcn/public/icons/payment/mastercard.svg +7 -0
  441. package/templates/storefront-nextjs-shadcn/public/icons/payment/paypal.svg +7 -0
  442. package/templates/storefront-nextjs-shadcn/public/icons/payment/payu.svg +7 -0
  443. package/templates/storefront-nextjs-shadcn/public/icons/payment/przelewy24.svg +7 -0
  444. package/templates/storefront-nextjs-shadcn/public/icons/payment/stripe.svg +4 -0
  445. package/templates/storefront-nextjs-shadcn/public/icons/payment/visa.svg +5 -0
  446. package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +66 -0
  447. package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +56 -0
  448. package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +184 -0
  449. package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +103 -0
  450. package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +291 -0
  451. package/templates/storefront-nextjs-shadcn/tailwind.config.ts +111 -0
  452. package/templates/storefront-nextjs-shadcn/tsconfig.json +27 -0
  453. package/templates/storefront-nextjs-shadcn/wrangler.toml +9 -0
@@ -0,0 +1,22 @@
1
+ name: Preview Deployment
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize]
6
+
7
+ jobs:
8
+ preview:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: pnpm/action-setup@v4
13
+ - uses: actions/setup-node@v4
14
+ with:
15
+ node-version: 20
16
+ cache: pnpm
17
+ - run: pnpm install --frozen-lockfile
18
+ - run: npx doswiftly deploy run --type PREVIEW --branch ${{ github.head_ref }}
19
+ env:
20
+ DOSWIFTLY_DEPLOY_TOKEN: ${{ secrets.DOSWIFTLY_DEPLOY_TOKEN }}
21
+ NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
22
+ NEXT_PUBLIC_SHOP_SLUG: ${{ secrets.NEXT_PUBLIC_SHOP_SLUG }}
@@ -0,0 +1,520 @@
1
+ # DoSwiftly Storefront Template
2
+
3
+ A modern, production-ready e-commerce storefront built with Next.js 15 and the DoSwiftly Commerce SDK.
4
+
5
+ ## Features
6
+
7
+ - ⚡ **Next.js 15** - App Router, Server Components, React 19
8
+ - 🛒 **Commerce SDK** - Type-safe GraphQL API integration
9
+ - 💱 **Multi-currency** - Automatic currency switching with SSR support
10
+ - 🎨 **TailwindCSS** - Beautiful, responsive UI
11
+ - 🔒 **Type-safe** - Full TypeScript support
12
+ - 🚀 **Hybrid Architecture** - RSC for SEO, Client for interactivity
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ # Install dependencies
18
+ pnpm install
19
+
20
+ # Start development server
21
+ pnpm dev
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Architecture: RSC vs Client Components
27
+
28
+ This template uses a **hybrid architecture** that combines React Server Components (RSC) for performance and SEO with Client Components for interactivity.
29
+
30
+ ### When to Use RSC (Server)
31
+
32
+ | Use Case | Reason |
33
+ | ------------------- | ----------------------- |
34
+ | Product listings | SEO, cacheability |
35
+ | Category pages | SEO, static content |
36
+ | Collection pages | SEO, static content |
37
+ | Search results | SEO for search engines |
38
+ | Single product info | SEO, initial load speed |
39
+
40
+ ### When to Use Client Components
41
+
42
+ | Use Case | Reason |
43
+ | ------------------ | ------------------------------ |
44
+ | Shopping cart | Real-time updates, mutations |
45
+ | Add to cart button | User interaction |
46
+ | Account/profile | User-specific, mutations |
47
+ | Checkout | Forms, payments, interactivity |
48
+ | Currency selector | Client-side state |
49
+
50
+ ### Route Architecture
51
+
52
+ ```
53
+ /app
54
+ ├── layout.tsx (RSC)
55
+ │ └── providers.tsx (Client) ← QueryClient + StorefrontProvider
56
+
57
+ ├── page.tsx (RSC) ← useProducts, useCategories
58
+ ├── products/
59
+ │ ├── page.tsx (RSC) ← useProducts
60
+ │ └── [slug]/page.tsx (RSC + Client island)
61
+ │ └── <ProductActions/> (Client) ← Add to cart
62
+
63
+ ├── categories/
64
+ │ ├── page.tsx (RSC) ← useCategories
65
+ │ └── [slug]/page.tsx (RSC) ← useCategory, useProducts
66
+
67
+ ├── collections/
68
+ │ ├── page.tsx (RSC) ← useCollections
69
+ │ └── [slug]/page.tsx (RSC) ← useCollection, useProducts
70
+
71
+ ├── search/page.tsx (RSC) ← useProducts
72
+
73
+ ├── cart/page.tsx (Client) ← useCart, useCartLinesUpdate
74
+
75
+ ├── account/
76
+ │ ├── page.tsx (Client) ← useCustomer
77
+ │ └── login/page.tsx (Client) ← useCustomerLogin
78
+
79
+ └── checkout/page.tsx (Client) ← Full interactivity
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Data Fetching
85
+
86
+ > **🔑 IMPORTANT:** Both server and client return **normalized data** (flat arrays).
87
+ > GraphQL edges/nodes are automatically unwrapped. No `.edges.map((e) => e.node)` needed!
88
+ >
89
+ > This provides the best developer experience and seamless migration between RSC and Client components.
90
+
91
+ ### Server Components (RSC)
92
+
93
+ Import from `@doswiftly/commerce-sdk/graphql/server`:
94
+
95
+ ```typescript
96
+ import {
97
+ useProducts,
98
+ useProduct,
99
+ useCategories,
100
+ } from "@doswiftly/commerce-sdk/graphql/server";
101
+
102
+ // All functions return normalized data (no edges/nodes)
103
+ // Cached per-request via React cache()
104
+ export default async function ProductsPage() {
105
+ const { products, pageInfo } = await useProducts({ first: 10 });
106
+ const { categories } = await useCategories();
107
+
108
+ // products is already a flat array - no .edges.map needed!
109
+ return <ProductGrid products={products} />;
110
+ }
111
+ ```
112
+
113
+ **Available server helpers:**
114
+
115
+ - `useProducts()` - Product listings with pagination
116
+ - `useProduct()` - Single product by handle
117
+ - `useCategories()` - All categories
118
+ - `useCategory()` - Single category by slug
119
+ - `useCollections()` - All collections
120
+ - `useCollection()` - Single collection by handle
121
+ - `useCart()` - Cart by ID
122
+ - `useShop()` - Shop configuration
123
+ - `useCustomer()` - Authenticated customer data
124
+
125
+ ### Client Components
126
+
127
+ Import from `@doswiftly/commerce-sdk/graphql/client`:
128
+
129
+ ```tsx
130
+ "use client";
131
+
132
+ import {
133
+ useProducts,
134
+ useCart,
135
+ useCartLinesAdd,
136
+ } from "@doswiftly/commerce-sdk/graphql/client";
137
+
138
+ export function ProductList() {
139
+ // React Query hook - returns normalized data (same as server!)
140
+ const { data, isLoading } = useProducts({ first: 10 });
141
+
142
+ if (isLoading) return <Skeleton />;
143
+
144
+ // data.products is already a flat array!
145
+ return <Grid products={data?.products} />;
146
+ }
147
+
148
+ export function AddToCartButton({ variantId }: { variantId: string }) {
149
+ const { mutate: addToCart, isPending } = useCartLinesAdd();
150
+
151
+ return (
152
+ <button
153
+ onClick={() =>
154
+ addToCart({
155
+ cartId,
156
+ lines: [{ merchandiseId: variantId, quantity: 1 }],
157
+ })
158
+ }
159
+ disabled={isPending}
160
+ >
161
+ {isPending ? "Adding..." : "Add to Cart"}
162
+ </button>
163
+ );
164
+ }
165
+ ```
166
+
167
+ **Available client hooks:**
168
+
169
+ Queries:
170
+
171
+ - `useProducts()` - Product listings
172
+ - `useProduct()` - Single product
173
+ - `useCategories()` - Categories
174
+ - `useCategory()` - Single category
175
+ - `useCollections()` - Collections
176
+ - `useCollection()` - Single collection
177
+ - `useCart()` - Cart data
178
+ - `useCustomer()` - Customer data
179
+
180
+ Mutations:
181
+
182
+ - `useCartCreate()` - Create new cart
183
+ - `useCartLinesAdd()` - Add items to cart
184
+ - `useCartLinesUpdate()` - Update cart items
185
+ - `useCartLinesRemove()` - Remove from cart
186
+ - `useCustomerLogin()` - Login
187
+ - `useCustomerCreate()` - Register
188
+ - `useCustomerLogout()` - Logout
189
+
190
+ ---
191
+
192
+ ## Naming Convention
193
+
194
+ Both server and client use **identical function names AND return structures**:
195
+
196
+ ```typescript
197
+ // Server (RSC) - async function, returns normalized data
198
+ import { useProducts } from "@doswiftly/commerce-sdk/graphql/server";
199
+ const { products, pageInfo } = await useProducts({ first: 10 });
200
+ // products is a flat array ✅
201
+
202
+ // Client - React Query hook, returns normalized data (same!)
203
+ import { useProducts } from "@doswiftly/commerce-sdk/graphql/client";
204
+ const { data } = useProducts({ first: 10 });
205
+ const products = data?.products; // Also a flat array ✅
206
+ ```
207
+
208
+ ### Return Types Comparison
209
+
210
+ | Aspect | Server (`/server`) | Client (`/client`) |
211
+ | ----------- | ------------------------------------- | -------------------------------------------- |
212
+ | Return type | `Promise<NormalizedProductsResponse>` | `UseQueryResult<NormalizedProductsResponse>` |
213
+ | Data access | `const { products, pageInfo }` | `const { data }` → `data.products` |
214
+ | Data format | **Flat array** (normalized, no edges) | **Flat array** (normalized, no edges) |
215
+ | Loading | N/A (await) | `isLoading`, `isFetching` |
216
+ | Error | try/catch | `error`, `isError` |
217
+ | Refetch | Call again | `refetch()` |
218
+ | Cache | `React.cache()` per-request | React Query client cache |
219
+
220
+ ---
221
+
222
+ ## Authentication & Session Persistence
223
+
224
+ ### How It Works
225
+
226
+ 1. **Login** → `useCustomerLogin()` mutation returns token
227
+ 2. **Token stored** in cookie: `doswiftly_customer_token`
228
+ 3. **Page refresh**:
229
+ - RSC reads cookie → injects `X-Customer-Token` header
230
+ - Client hydrates with same state from server props
231
+ 4. **No flash of unauthenticated content**
232
+
233
+ ### Implementation
234
+
235
+ ```tsx
236
+ // RSC - automatically authenticated via cookies
237
+ import { useCustomer } from "@doswiftly/commerce-sdk/graphql/server";
238
+
239
+ export default async function AccountPage() {
240
+ const { customer } = await useCustomer();
241
+
242
+ if (!customer) {
243
+ redirect("/login");
244
+ }
245
+
246
+ return <Profile customer={customer} />;
247
+ }
248
+
249
+ // Client - same pattern with loading state
250
+ ("use client");
251
+ import { useCustomer, useAuth } from "@doswiftly/commerce-sdk/graphql/client";
252
+
253
+ export function ProfileClient() {
254
+ const { data, isLoading } = useCustomer();
255
+ const { logout } = useAuth();
256
+
257
+ if (isLoading) return <Skeleton />;
258
+ if (!data?.customer) return <LoginPrompt />;
259
+
260
+ return <Profile customer={data.customer} onLogout={logout} />;
261
+ }
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Currency Handling
267
+
268
+ ### Automatic Currency Injection
269
+
270
+ Currency is read from `doswiftly_preferred_currency` cookie and automatically applied to all GraphQL requests.
271
+
272
+ ### Changing Currency
273
+
274
+ ```tsx
275
+ "use client";
276
+ import { useCurrency } from "@doswiftly/commerce-sdk/graphql/react";
277
+ import { useRouter } from "next/navigation";
278
+
279
+ export function CurrencySelector() {
280
+ const { currency, setCurrency, availableCurrencies } = useCurrency();
281
+ const router = useRouter();
282
+
283
+ const handleChange = (newCurrency: string) => {
284
+ setCurrency(newCurrency); // Updates cookie + context
285
+ router.refresh(); // Refreshes RSC pages with new currency
286
+ };
287
+
288
+ return (
289
+ <select value={currency} onChange={(e) => handleChange(e.target.value)}>
290
+ {availableCurrencies.map((c) => (
291
+ <option key={c} value={c}>
292
+ {c}
293
+ </option>
294
+ ))}
295
+ </select>
296
+ );
297
+ }
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Filtering & Sorting
303
+
304
+ ### Filter Products
305
+
306
+ ```typescript
307
+ const { products } = await useProducts({
308
+ first: 20,
309
+ filters: {
310
+ minPrice: 50,
311
+ maxPrice: 200,
312
+ vendor: "Nike",
313
+ available: true,
314
+ },
315
+ sortKey: "PRICE",
316
+ reverse: false, // ascending
317
+ });
318
+ ```
319
+
320
+ ### Available Filters
321
+
322
+ | Filter | Type | Description |
323
+ | ------------- | ------- | ------------------ |
324
+ | `minPrice` | number | Minimum price |
325
+ | `maxPrice` | number | Maximum price |
326
+ | `vendor` | string | Brand/vendor name |
327
+ | `available` | boolean | Stock availability |
328
+ | `productType` | string | Product type |
329
+ | `tag` | string | Product tag |
330
+
331
+ ### Sort Keys
332
+
333
+ - `TITLE` - Alphabetically
334
+ - `PRICE` - By price
335
+ - `CREATED_AT` - By date
336
+ - `BEST_SELLING` - By popularity
337
+
338
+ ---
339
+
340
+ ## Pagination
341
+
342
+ Cursor-based pagination for all list endpoints:
343
+
344
+ ```typescript
345
+ const { products, pageInfo } = await useProducts({ first: 10 });
346
+
347
+ if (pageInfo?.hasNextPage) {
348
+ const nextPage = await useProducts({
349
+ first: 10,
350
+ after: pageInfo.endCursor,
351
+ });
352
+ }
353
+ ```
354
+
355
+ ---
356
+
357
+ ## Island of Interactivity Pattern
358
+
359
+ Combine RSC and Client Components for optimal performance:
360
+
361
+ ```tsx
362
+ // app/products/[slug]/page.tsx (RSC)
363
+ import { useProduct } from "@doswiftly/commerce-sdk/graphql/server";
364
+ import { AddToCartButton } from "@/components/commerce/add-to-cart";
365
+
366
+ export default async function ProductPage({ params }) {
367
+ const { product } = await useProduct({ handle: params.slug });
368
+
369
+ return (
370
+ <div>
371
+ {/* RSC - Static, SEO-friendly */}
372
+ <h1>{product.title}</h1>
373
+ <p>{product.description}</p>
374
+ <img src={product.featuredImage?.url} alt={product.title} />
375
+
376
+ {/* Client Island - Interactive */}
377
+ <AddToCartButton productId={product.id} variants={product.variants} />
378
+ </div>
379
+ );
380
+ }
381
+ ```
382
+
383
+ ```tsx
384
+ // components/commerce/add-to-cart.tsx (Client)
385
+ "use client";
386
+
387
+ import { useCartManager } from "@doswiftly/commerce-sdk/graphql/react";
388
+
389
+ export function AddToCartButton({ productId, variants }) {
390
+ const { addItem, loading } = useCartManager();
391
+ const [quantity, setQuantity] = useState(1);
392
+ const [selectedVariant, setSelectedVariant] = useState(variants[0]?.id);
393
+
394
+ return (
395
+ <div>
396
+ <QuantitySelector value={quantity} onChange={setQuantity} />
397
+ <VariantSelector
398
+ variants={variants}
399
+ value={selectedVariant}
400
+ onChange={setSelectedVariant}
401
+ />
402
+ <button
403
+ onClick={() => addItem(selectedVariant, quantity)}
404
+ disabled={loading}
405
+ >
406
+ {loading ? "Adding..." : "Add to Cart"}
407
+ </button>
408
+ </div>
409
+ );
410
+ }
411
+ ```
412
+
413
+ ---
414
+
415
+ ## Environment Variables
416
+
417
+ ```env
418
+ # Required
419
+ NEXT_PUBLIC_API_URL=http://localhost:8000
420
+ NEXT_PUBLIC_SHOP_SLUG=your-shop-slug
421
+
422
+ # Optional
423
+ NEXT_PUBLIC_SITE_NAME=My Store
424
+ ```
425
+
426
+ ---
427
+
428
+ ## Project Structure
429
+
430
+ ```
431
+ app/
432
+ layout.tsx # Root layout (RSC)
433
+ page.tsx # Homepage (RSC)
434
+ products/
435
+ page.tsx # Product listing (RSC)
436
+ [slug]/page.tsx # Product detail (RSC + Client)
437
+ categories/
438
+ page.tsx # Categories (RSC)
439
+ [slug]/page.tsx # Category products (RSC)
440
+ collections/
441
+ page.tsx # Collections (RSC)
442
+ [slug]/page.tsx # Collection products (RSC)
443
+ search/page.tsx # Search results (RSC)
444
+ cart/page.tsx # Shopping cart (Client)
445
+ account/
446
+ page.tsx # Account dashboard (Client)
447
+ login/page.tsx # Login form (Client)
448
+
449
+ components/
450
+ commerce/
451
+ add-to-cart.tsx # Add to cart button (Client)
452
+ currency-selector.tsx # Currency switcher (Client)
453
+ product-actions.tsx # Product page actions (Client)
454
+ providers.tsx # QueryClient + StorefrontProvider (Client)
455
+ ```
456
+
457
+ ---
458
+
459
+ ## Migration from Raw GraphQL
460
+
461
+ If you're migrating from a previous version that returned raw GraphQL responses (edges/nodes), here's what changed:
462
+
463
+ ### ✅ Before (Raw GraphQL)
464
+
465
+ ```tsx
466
+ // Client hooks returned raw edges/nodes
467
+ const { data } = useProducts({ first: 10 });
468
+ const products = data?.products.edges.map((e) => e.node);
469
+ ```
470
+
471
+ ### ✅ After (Normalized)
472
+
473
+ ```tsx
474
+ // Client hooks now return flat arrays (same as server)
475
+ const { data } = useProducts({ first: 10 });
476
+ const products = data?.products; // Already flat!
477
+ ```
478
+
479
+ ### Migration Steps
480
+
481
+ 1. **Remove `.edges.map((e) => e.node)`** from all client components
482
+ 2. **Access data directly**: `data.products` instead of `data.products.edges`
483
+ 3. **PageInfo unchanged**: Still accessed via `data.pageInfo`
484
+
485
+ ### Why This Change?
486
+
487
+ - **Consistency**: Server and client APIs are now identical
488
+ - **Developer Experience**: Zero boilerplate, less code
489
+ - **Fewer Errors**: No more "Cannot read properties of undefined (reading 'map')"
490
+ - **Seamless Migration**: Move components between RSC/Client without changes
491
+
492
+ ### Need Raw GraphQL?
493
+
494
+ For advanced use cases requiring raw GraphQL (custom fragments, \_\_typename, etc.), use `graphql-request` directly:
495
+
496
+ ```typescript
497
+ import { GraphQLClient } from "graphql-request";
498
+ import { gql } from "graphql-tag";
499
+
500
+ const client = new GraphQLClient(apiUrl);
501
+ const data = await client.request(gql`
502
+ query {
503
+ products(first: 10) {
504
+ edges {
505
+ node {
506
+ id
507
+ __typename
508
+ }
509
+ cursor
510
+ }
511
+ }
512
+ }
513
+ `);
514
+ ```
515
+
516
+ ---
517
+
518
+ ## License
519
+
520
+ MIT