@doswiftly/cli 0.1.18 → 0.1.20

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 (277) hide show
  1. package/README.md +23 -323
  2. package/dist/commands/check.js +1 -1
  3. package/dist/commands/check.js.map +1 -1
  4. package/dist/commands/deploy.d.ts +20 -0
  5. package/dist/commands/deploy.d.ts.map +1 -1
  6. package/dist/commands/deploy.js +249 -17
  7. package/dist/commands/deploy.js.map +1 -1
  8. package/dist/commands/doctor.js +3 -3
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/init.js +4 -4
  11. package/dist/commands/sdk.js +5 -5
  12. package/dist/commands/sdk.js.map +1 -1
  13. package/dist/commands/template.js +4 -4
  14. package/dist/commands/template.js.map +1 -1
  15. package/dist/commands/types.js +5 -5
  16. package/dist/commands/types.js.map +1 -1
  17. package/dist/commands/verify.js +2 -2
  18. package/dist/commands/verify.js.map +1 -1
  19. package/dist/lib/package-manager.d.ts +1 -1
  20. package/dist/lib/package-manager.js +1 -1
  21. package/package.json +4 -4
  22. package/templates/storefront-minimal/.github/workflows/build-template.yml +10 -0
  23. package/templates/storefront-minimal/wrangler.toml +11 -0
  24. package/templates/storefront-nextjs/.github/workflows/build-template.yml +10 -0
  25. package/templates/storefront-nextjs/README.md +16 -12
  26. package/templates/storefront-nextjs/app/account/orders/page.tsx +2 -2
  27. package/templates/storefront-nextjs/app/account/page.tsx +2 -2
  28. package/templates/storefront-nextjs/app/auth/login/page.tsx +1 -1
  29. package/templates/storefront-nextjs/app/auth/register/page.tsx +1 -1
  30. package/templates/storefront-nextjs/app/cart/page.tsx +1 -1
  31. package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +2 -2
  32. package/templates/storefront-nextjs/app/categories/page.tsx +1 -1
  33. package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +1 -1
  34. package/templates/storefront-nextjs/app/collections/page.tsx +1 -1
  35. package/templates/storefront-nextjs/app/page.tsx +1 -1
  36. package/templates/storefront-nextjs/app/products/[slug]/page.tsx +1 -1
  37. package/templates/storefront-nextjs/app/products/page.tsx +2 -2
  38. package/templates/storefront-nextjs/app/search/page.tsx +1 -1
  39. package/templates/storefront-nextjs/components/auth/auth-guard.tsx +1 -1
  40. package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +1 -1
  41. package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +1 -1
  42. package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +2 -2
  43. package/templates/storefront-nextjs/components/commerce/product-filters.tsx +1 -1
  44. package/templates/storefront-nextjs/components/commerce/product-price.tsx +1 -1
  45. package/templates/storefront-nextjs/components/commerce/search-input.tsx +1 -1
  46. package/templates/storefront-nextjs/components/commerce/sort-select.tsx +1 -1
  47. package/templates/storefront-nextjs/components/providers.tsx +1 -1
  48. package/templates/storefront-nextjs/lib/currency.tsx +3 -3
  49. package/templates/storefront-nextjs/lib/format.ts +1 -1
  50. package/templates/storefront-nextjs/lib/graphql-queries.ts +3 -3
  51. package/templates/storefront-nextjs/package.dev.json +1 -1
  52. package/templates/storefront-nextjs/package.json +1 -1
  53. package/templates/storefront-nextjs/package.json.template +1 -1
  54. package/templates/storefront-nextjs/wrangler.toml +11 -0
  55. package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +10 -0
  56. package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +47 -0
  57. package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +47 -0
  58. package/templates/storefront-nextjs-shadcn/CLAUDE.md +172 -35
  59. package/templates/storefront-nextjs-shadcn/README.md +29 -162
  60. package/templates/storefront-nextjs-shadcn/app/{about → [locale]/about}/page.tsx +17 -14
  61. package/templates/storefront-nextjs-shadcn/app/[locale]/account/addresses/page.tsx +226 -0
  62. package/templates/storefront-nextjs-shadcn/app/[locale]/account/error.tsx +46 -0
  63. package/templates/storefront-nextjs-shadcn/app/[locale]/account/loading.tsx +19 -0
  64. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/loyalty/page.tsx +89 -193
  65. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/loading.tsx +60 -0
  66. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/[id]/page.tsx +119 -0
  67. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/orders/[id]/tracking/page.tsx +27 -25
  68. package/templates/storefront-nextjs-shadcn/app/[locale]/account/orders/page.tsx +101 -0
  69. package/templates/storefront-nextjs-shadcn/app/{account → [locale]/account}/page.tsx +9 -7
  70. package/templates/storefront-nextjs-shadcn/app/[locale]/account/settings/page.tsx +208 -0
  71. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/forgot-password/page.tsx +24 -17
  72. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/login/page.tsx +5 -2
  73. package/templates/storefront-nextjs-shadcn/app/{auth → [locale]/auth}/register/page.tsx +5 -2
  74. package/templates/storefront-nextjs-shadcn/app/[locale]/blog/[slug]/loading.tsx +17 -0
  75. package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/[slug]/page.tsx +44 -3
  76. package/templates/storefront-nextjs-shadcn/app/[locale]/blog/loading.tsx +19 -0
  77. package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/page.tsx +2 -1
  78. package/templates/storefront-nextjs-shadcn/app/[locale]/cart/loading.tsx +26 -0
  79. package/templates/storefront-nextjs-shadcn/app/{cart → [locale]/cart}/page.tsx +20 -13
  80. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/category-products-client.tsx +58 -0
  81. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/loading.tsx +32 -0
  82. package/templates/storefront-nextjs-shadcn/app/[locale]/categories/[slug]/page.tsx +95 -0
  83. package/templates/storefront-nextjs-shadcn/app/{categories → [locale]/categories}/page.tsx +21 -12
  84. package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/error.tsx +43 -0
  85. package/templates/storefront-nextjs-shadcn/app/[locale]/checkout/loading.tsx +31 -0
  86. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/page.tsx +334 -253
  87. package/templates/storefront-nextjs-shadcn/app/{checkout → [locale]/checkout}/success/[orderId]/page.tsx +36 -34
  88. package/templates/storefront-nextjs-shadcn/app/[locale]/collections/[handle]/loading.tsx +19 -0
  89. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/[handle]/page.tsx +6 -4
  90. package/templates/storefront-nextjs-shadcn/app/[locale]/collections/loading.tsx +18 -0
  91. package/templates/storefront-nextjs-shadcn/app/{collections → [locale]/collections}/page.tsx +20 -12
  92. package/templates/storefront-nextjs-shadcn/app/{contact → [locale]/contact}/page.tsx +24 -21
  93. package/templates/storefront-nextjs-shadcn/app/{error.tsx → [locale]/error.tsx} +13 -8
  94. package/templates/storefront-nextjs-shadcn/app/[locale]/layout.tsx +92 -0
  95. package/templates/storefront-nextjs-shadcn/app/{not-found.tsx → [locale]/not-found.tsx} +13 -18
  96. package/templates/storefront-nextjs-shadcn/app/{page.tsx → [locale]/page.tsx} +8 -4
  97. package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/error.tsx +43 -0
  98. package/templates/storefront-nextjs-shadcn/app/[locale]/products/[slug]/loading.tsx +29 -0
  99. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/page.tsx +17 -14
  100. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/[slug]/product-client.tsx +18 -62
  101. package/templates/storefront-nextjs-shadcn/app/[locale]/products/loading.tsx +32 -0
  102. package/templates/storefront-nextjs-shadcn/app/{products → [locale]/products}/page.tsx +6 -3
  103. package/templates/storefront-nextjs-shadcn/app/[locale]/products/products-client.tsx +450 -0
  104. package/templates/storefront-nextjs-shadcn/app/[locale]/search/loading.tsx +18 -0
  105. package/templates/storefront-nextjs-shadcn/app/{wishlist → [locale]/wishlist}/page.tsx +27 -28
  106. package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +2 -86
  107. package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +2 -124
  108. package/templates/storefront-nextjs-shadcn/app/global-error.tsx +117 -0
  109. package/templates/storefront-nextjs-shadcn/app/globals.css +8 -0
  110. package/templates/storefront-nextjs-shadcn/app/layout.tsx +8 -35
  111. package/templates/storefront-nextjs-shadcn/codegen.ts +48 -31
  112. package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +25 -20
  113. package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +11 -10
  114. package/templates/storefront-nextjs-shadcn/components/account/customer-info.fragment.graphql +36 -0
  115. package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +17 -13
  116. package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +42 -30
  117. package/templates/storefront-nextjs-shadcn/components/account/order-summary.fragment.graphql +36 -0
  118. package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +18 -16
  119. package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +37 -58
  120. package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +85 -66
  121. package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +1 -1
  122. package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +1 -1
  123. package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +1 -1
  124. package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +10 -6
  125. package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +9 -6
  126. package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +8 -6
  127. package/templates/storefront-nextjs-shadcn/components/cart/cart-line.fragment.graphql +53 -0
  128. package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +10 -8
  129. package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +8 -5
  130. package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +38 -20
  131. package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +15 -25
  132. package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +10 -8
  133. package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +9 -6
  134. package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +7 -5
  135. package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +8 -5
  136. package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +6 -4
  137. package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +10 -9
  138. package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +1 -1
  139. package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +1 -1
  140. package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +35 -11
  141. package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +9 -6
  142. package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +22 -12
  143. package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +18 -15
  144. package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +53 -28
  145. package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +7 -5
  146. package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +5 -5
  147. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +19 -15
  148. package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +13 -10
  149. package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +10 -6
  150. package/templates/storefront-nextjs-shadcn/components/home/collection-card.fragment.graphql +21 -0
  151. package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +3 -13
  152. package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +12 -8
  153. package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +13 -8
  154. package/templates/storefront-nextjs-shadcn/components/home/index.ts +0 -1
  155. package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +10 -8
  156. package/templates/storefront-nextjs-shadcn/components/hydrated.tsx +24 -0
  157. package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +41 -16
  158. package/templates/storefront-nextjs-shadcn/components/layout/category-node.fragment.graphql +22 -0
  159. package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +7 -4
  160. package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +24 -23
  161. package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +52 -34
  162. package/templates/storefront-nextjs-shadcn/components/layout/language-switcher.tsx +54 -0
  163. package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +33 -30
  164. package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +27 -24
  165. package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +2 -11
  166. package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +8 -25
  167. package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +32 -42
  168. package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +17 -41
  169. package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +2 -29
  170. package/templates/storefront-nextjs-shadcn/components/order/index.ts +6 -1
  171. package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +6 -14
  172. package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +4 -2
  173. package/templates/storefront-nextjs-shadcn/components/product/filter-active-pills.tsx +72 -0
  174. package/templates/storefront-nextjs-shadcn/components/product/filter-mobile-sheet.tsx +87 -0
  175. package/templates/storefront-nextjs-shadcn/components/product/filter-price-range.tsx +140 -0
  176. package/templates/storefront-nextjs-shadcn/components/product/index.ts +9 -2
  177. package/templates/storefront-nextjs-shadcn/components/product/product-card.fragment.graphql +49 -0
  178. package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +11 -37
  179. package/templates/storefront-nextjs-shadcn/components/product/product-detail.fragment.graphql +52 -0
  180. package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +179 -124
  181. package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +3 -5
  182. package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +3 -7
  183. package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +2 -2
  184. package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +5 -4
  185. package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +44 -19
  186. package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +8 -23
  187. package/templates/storefront-nextjs-shadcn/components/product/product-variant.fragment.graphql +51 -0
  188. package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +1 -1
  189. package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +26 -34
  190. package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +17 -2
  191. package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +3 -2
  192. package/templates/storefront-nextjs-shadcn/components/providers/index.ts +1 -1
  193. package/templates/storefront-nextjs-shadcn/components/providers/language-sync-provider.tsx +27 -0
  194. package/templates/storefront-nextjs-shadcn/components/providers/stores-provider.tsx +63 -0
  195. package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +1 -1
  196. package/templates/storefront-nextjs-shadcn/components/returns/index.ts +2 -2
  197. package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +59 -72
  198. package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +7 -4
  199. package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +3 -2
  200. package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +12 -9
  201. package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +23 -12
  202. package/templates/storefront-nextjs-shadcn/components/ui/form.tsx +174 -0
  203. package/templates/storefront-nextjs-shadcn/components/ui/index.ts +30 -2
  204. package/templates/storefront-nextjs-shadcn/components/ui/progress.tsx +40 -0
  205. package/templates/storefront-nextjs-shadcn/components/ui/sheet.tsx +107 -0
  206. package/templates/storefront-nextjs-shadcn/components/ui/slider.tsx +33 -0
  207. package/templates/storefront-nextjs-shadcn/components/ui/textarea.tsx +24 -0
  208. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +7 -4
  209. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +4 -2
  210. package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +2 -10
  211. package/templates/storefront-nextjs-shadcn/generated/graphql.ts +13387 -0
  212. package/templates/storefront-nextjs-shadcn/graphql/custom.example.graphql +159 -0
  213. package/templates/storefront-nextjs-shadcn/hooks/index.ts +3 -0
  214. package/templates/storefront-nextjs-shadcn/hooks/use-auth-sync.ts +42 -0
  215. package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +17 -295
  216. package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +34 -229
  217. package/templates/storefront-nextjs-shadcn/hooks/use-cart-di.ts +67 -0
  218. package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +16 -12
  219. package/templates/storefront-nextjs-shadcn/i18n/navigation.ts +12 -0
  220. package/templates/storefront-nextjs-shadcn/i18n/request.ts +17 -0
  221. package/templates/storefront-nextjs-shadcn/i18n/routing.ts +17 -0
  222. package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +4 -17
  223. package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +22 -99
  224. package/templates/storefront-nextjs-shadcn/lib/graphql/config.ts +33 -0
  225. package/templates/storefront-nextjs-shadcn/lib/graphql/fragments.ts +34 -0
  226. package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +720 -632
  227. package/templates/storefront-nextjs-shadcn/lib/graphql/query-keys.ts +88 -0
  228. package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +132 -182
  229. package/templates/storefront-nextjs-shadcn/lib/graphql/types.ts +62 -0
  230. package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +0 -17
  231. package/templates/storefront-nextjs-shadcn/messages/en.json +869 -0
  232. package/templates/storefront-nextjs-shadcn/messages/pl.json +869 -0
  233. package/templates/storefront-nextjs-shadcn/next-env.d.ts +6 -0
  234. package/templates/storefront-nextjs-shadcn/next.config.ts +6 -5
  235. package/templates/storefront-nextjs-shadcn/package.dev.json +1 -3
  236. package/templates/storefront-nextjs-shadcn/package.json +14 -14
  237. package/templates/storefront-nextjs-shadcn/package.json.template +6 -7
  238. package/templates/storefront-nextjs-shadcn/proxy.ts +115 -47
  239. package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +24 -56
  240. package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +64 -75
  241. package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +178 -177
  242. package/templates/storefront-nextjs-shadcn/tsconfig.json +23 -5
  243. package/templates/storefront-nextjs-shadcn/wrangler.toml +11 -0
  244. package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +0 -282
  245. package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +0 -190
  246. package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +0 -263
  247. package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +0 -135
  248. package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +0 -142
  249. package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +0 -448
  250. package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +0 -307
  251. package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +0 -245
  252. package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +0 -215
  253. package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +0 -128
  254. package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +0 -80
  255. package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +0 -171
  256. package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +0 -78
  257. package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +0 -192
  258. package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +0 -103
  259. package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +0 -168
  260. package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +0 -160
  261. package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +0 -220
  262. package/templates/storefront-nextjs-shadcn/lib/config.ts +0 -46
  263. package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +0 -254
  264. package/templates/storefront-nextjs-shadcn/lib/currency/README.md +0 -464
  265. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +0 -328
  266. package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +0 -295
  267. package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +0 -27
  268. package/templates/storefront-nextjs-shadcn/lib/format.ts +0 -226
  269. package/templates/storefront-nextjs-shadcn/lib/hooks.ts +0 -30
  270. package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +0 -66
  271. package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +0 -103
  272. /package/templates/storefront-nextjs-shadcn/app/{blog → [locale]/blog}/page.tsx +0 -0
  273. /package/templates/storefront-nextjs-shadcn/app/{brands → [locale]/brands}/[slug]/page.tsx +0 -0
  274. /package/templates/storefront-nextjs-shadcn/app/{returns → [locale]/returns}/page.tsx +0 -0
  275. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/page.tsx +0 -0
  276. /package/templates/storefront-nextjs-shadcn/app/{search → [locale]/search}/search-client.tsx +0 -0
  277. /package/templates/storefront-nextjs-shadcn/app/{shipping → [locale]/shipping}/page.tsx +0 -0
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { Metadata } from 'next';
8
8
  import Image from 'next/image';
9
- import Link from 'next/link';
9
+ import { Link } from '@/i18n/navigation';
10
10
  import { notFound } from 'next/navigation';
11
11
  import { Calendar, Clock, Eye, User, ChevronLeft, Share2 } from 'lucide-react';
12
12
  import { Breadcrumbs } from '@/components/layout/breadcrumbs';
@@ -16,9 +16,50 @@ import { Card, CardContent } from '@/components/ui/card';
16
16
  import { Separator } from '@/components/ui/separator';
17
17
  import { BlogCard } from '@/components/blog/blog-card';
18
18
  import { BlogSidebar } from '@/components/blog/blog-sidebar';
19
+ import { sanitizeHtml } from '@doswiftly/storefront-sdk';
20
+
21
+ interface BlogImage {
22
+ url: string;
23
+ altText?: string;
24
+ }
25
+
26
+ interface BlogPost {
27
+ id: string;
28
+ title: string;
29
+ slug: string;
30
+ excerpt: string;
31
+ content: string;
32
+ contentType: string;
33
+ featuredImage: BlogImage | null;
34
+ author: {
35
+ id: string;
36
+ name: string;
37
+ bio: string;
38
+ avatar: BlogImage | null;
39
+ };
40
+ category: {
41
+ id: string;
42
+ name: string;
43
+ slug: string;
44
+ } | null;
45
+ tags: { id: string; name: string; slug: string; postCount: number }[];
46
+ status: string;
47
+ publishedAt: string;
48
+ readingTime: number;
49
+ viewCount: number;
50
+ commentCount: number;
51
+ allowComments: boolean;
52
+ isFeatured: boolean;
53
+ seo: {
54
+ title: string;
55
+ description: string;
56
+ } | null;
57
+ createdAt: string;
58
+ updatedAt: string;
59
+ }
19
60
 
20
61
  // Mock data - replace with actual GraphQL fetch
21
- const mockPost = {
62
+ const mockPost: BlogPost = {
22
63
  id: '1',
23
64
  title: 'Jak wybrać idealny produkt dla siebie',
24
65
  slug: 'jak-wybrac-idealny-produkt',
@@ -234,7 +275,7 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
234
275
  {/* Content */}
235
276
  <div
236
277
  className="prose prose-lg max-w-none dark:prose-invert mb-8"
237
- dangerouslySetInnerHTML={{ __html: post.content }}
278
+ dangerouslySetInnerHTML={{ __html: sanitizeHtml(post.content) }}
238
279
  />
239
280
 
240
281
  {/* Tags */}
@@ -0,0 +1,19 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function BlogLoading() {
4
+ return (
5
+ <div className="container mx-auto px-4 py-8">
6
+ <Skeleton className="mb-8 h-10 w-32" />
7
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
8
+ {[...Array(6)].map((_, i) => (
9
+ <div key={i} className="space-y-3">
10
+ <Skeleton className="aspect-video w-full rounded-lg" />
11
+ <Skeleton className="h-4 w-24" />
12
+ <Skeleton className="h-6 w-full" />
13
+ <Skeleton className="h-4 w-5/6" />
14
+ </div>
15
+ ))}
16
+ </div>
17
+ </div>
18
+ );
19
+ }
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import { Breadcrumbs } from "@/components/layout/breadcrumbs";
4
- import { BrandGrid, type BrandCardProps } from "@/components/brand/brand-grid";
4
+ import { BrandGrid } from "@/components/brand/brand-grid";
5
+ import type { BrandCardProps } from "@/components/brand/brand-card";
5
6
 
6
7
  export default function BrandsPage() {
7
8
  // TODO: Fetch brands from backend using GraphQL
@@ -0,0 +1,26 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function CartLoading() {
4
+ return (
5
+ <div className="container mx-auto px-4 py-8">
6
+ <Skeleton className="mb-8 h-10 w-48" />
7
+ <div className="grid gap-8 lg:grid-cols-3">
8
+ <div className="space-y-4 lg:col-span-2">
9
+ {[...Array(3)].map((_, i) => (
10
+ <div key={i} className="flex gap-4 rounded-lg border p-4">
11
+ <Skeleton className="h-24 w-24 shrink-0 rounded-md" />
12
+ <div className="flex-1 space-y-2">
13
+ <Skeleton className="h-5 w-3/4" />
14
+ <Skeleton className="h-4 w-1/3" />
15
+ <Skeleton className="h-8 w-24" />
16
+ </div>
17
+ </div>
18
+ ))}
19
+ </div>
20
+ <div>
21
+ <Skeleton className="h-64 w-full rounded-lg" />
22
+ </div>
23
+ </div>
24
+ </div>
25
+ );
26
+ }
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
 
3
- import Link from "next/link";
4
- import { useCartStore } from "@/stores/cart-store";
3
+ import { Link, useRouter } from "@/i18n/navigation";
4
+ import { useTranslations } from "next-intl";
5
+ import { useCartStoreApi } from "@/stores/cart-store";
5
6
  import { useCartSync } from "@/hooks/use-cart-sync";
6
7
  import { useCartActions } from "@/hooks/use-cart-actions";
7
8
  import { useCartDiscountCodesUpdate } from "@/lib/graphql/hooks";
@@ -14,6 +15,9 @@ import { Button } from "@/components/ui/button";
14
15
  import { ArrowLeft, Loader2 } from "lucide-react";
15
16
 
16
17
  export default function CartPage() {
18
+ const t = useTranslations("cart");
19
+ const router = useRouter();
20
+
17
21
  // Server cart data (source of truth)
18
22
  const {
19
23
  items,
@@ -26,6 +30,9 @@ export default function CartPage() {
26
30
  isLoading,
27
31
  } = useCartSync();
28
32
 
33
+ // Cart store API for getState() in callbacks
34
+ const cartStoreApi = useCartStoreApi();
35
+
29
36
  // Actions that mutate via GraphQL
30
37
  const { updateQuantity, removeFromCart } = useCartActions();
31
38
 
@@ -44,14 +51,14 @@ export default function CartPage() {
44
51
  }
45
52
 
46
53
  const handleCheckout = () => {
47
- window.location.href = "/checkout";
54
+ router.push("/checkout");
48
55
  };
49
56
 
50
57
  const handleApplyPromo = async (code: string) => {
51
58
  try {
52
- const cartId = useCartStore.getState().cartId;
59
+ const cartId = cartStoreApi.getState().cartId;
53
60
  if (!cartId) {
54
- return { success: false, message: "Your cart is empty" };
61
+ return { success: false, message: t("empty") };
55
62
  }
56
63
 
57
64
  const result = await discountMutation.mutateAsync({
@@ -71,22 +78,22 @@ export default function CartPage() {
71
78
  if (!payload?.cart) {
72
79
  return {
73
80
  success: false,
74
- message: "Failed to apply promo code",
81
+ message: t("promoError"),
75
82
  };
76
83
  }
77
84
 
78
- return { success: true, message: "Promo code applied!" };
85
+ return { success: true, message: t("promoApplied") };
79
86
  } catch (error) {
80
87
  return {
81
88
  success: false,
82
- message: "Failed to apply promo code",
89
+ message: t("promoError"),
83
90
  };
84
91
  }
85
92
  };
86
93
 
87
94
  const handleRemovePromo = async () => {
88
95
  try {
89
- const cartId = useCartStore.getState().cartId;
96
+ const cartId = cartStoreApi.getState().cartId;
90
97
  if (!cartId) return;
91
98
 
92
99
  await discountMutation.mutateAsync({
@@ -101,7 +108,7 @@ export default function CartPage() {
101
108
  if (items.length === 0) {
102
109
  return (
103
110
  <div className="container mx-auto px-4 py-16">
104
- <EmptyCart onContinueShopping={() => (window.location.href = "/products")} />
111
+ <EmptyCart onContinueShopping={() => router.push("/products")} />
105
112
  </div>
106
113
  );
107
114
  }
@@ -113,11 +120,11 @@ export default function CartPage() {
113
120
  <Breadcrumbs className="mb-6" />
114
121
 
115
122
  <div className="mb-8 flex items-center justify-between">
116
- <h1 className="text-3xl font-bold text-foreground">Shopping Cart</h1>
123
+ <h1 className="text-3xl font-bold text-foreground">{t("title")}</h1>
117
124
  <Button variant="ghost" asChild>
118
125
  <Link href="/products">
119
126
  <ArrowLeft className="mr-2 h-4 w-4" />
120
- Continue Shopping
127
+ {t("continueShopping")}
121
128
  </Link>
122
129
  </Button>
123
130
  </div>
@@ -141,7 +148,7 @@ export default function CartPage() {
141
148
  {/* Summary */}
142
149
  <div className="lg:col-span-1">
143
150
  <div className="sticky top-4 space-y-4 rounded-lg border border-border bg-muted/50 p-6">
144
- <h2 className="text-lg font-semibold text-foreground">Order Summary</h2>
151
+ <h2 className="text-lg font-semibold text-foreground">{t("yourOrder")}</h2>
145
152
 
146
153
  <PromoCodeInput
147
154
  onApply={handleApplyPromo}
@@ -0,0 +1,58 @@
1
+ "use client";
2
+
3
+ import { useTranslations } from "next-intl";
4
+ import { ProductGrid } from "@/components/product/product-grid";
5
+ import { Skeleton } from "@/components/ui/skeleton";
6
+ import { useProducts } from "@/lib/graphql/hooks";
7
+
8
+ interface CategoryProductsClientProps {
9
+ categoryId: string;
10
+ }
11
+
12
+ /**
13
+ * Client component for category product listing.
14
+ *
15
+ * Receives categoryId from server and uses filters.categoryId
16
+ * for correct backend filtering.
17
+ */
18
+ export function CategoryProductsClient({
19
+ categoryId,
20
+ }: CategoryProductsClientProps) {
21
+ const t = useTranslations("product");
22
+ const { data, isLoading, error } = useProducts({
23
+ first: 20,
24
+ filters: { categoryId },
25
+ });
26
+
27
+ const products = data?.products ?? [];
28
+
29
+ if (isLoading) {
30
+ return (
31
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
32
+ {Array.from({ length: 8 }).map((_, i) => (
33
+ <Skeleton key={i} className="aspect-square w-full rounded-lg" />
34
+ ))}
35
+ </div>
36
+ );
37
+ }
38
+
39
+ if (error) {
40
+ return (
41
+ <div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
42
+ <p className="text-muted-foreground">
43
+ {t("failedLoadProducts")}
44
+ </p>
45
+ </div>
46
+ );
47
+ }
48
+
49
+ return (
50
+ <ProductGrid
51
+ products={products}
52
+ columns={4}
53
+ priorityCount={8}
54
+ showBadges
55
+ emptyMessage={t("noProductsInCategory")}
56
+ />
57
+ );
58
+ }
@@ -0,0 +1,32 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function CategoryLoading() {
4
+ return (
5
+ <div className="container mx-auto px-4 py-8">
6
+ {/* Breadcrumbs */}
7
+ <Skeleton className="mb-6 h-5 w-64" />
8
+
9
+ {/* Category title */}
10
+ <Skeleton className="mb-2 h-9 w-48" />
11
+ <Skeleton className="mb-6 h-5 w-96" />
12
+
13
+ {/* Subcategory chips */}
14
+ <div className="mb-8 flex gap-2">
15
+ {[...Array(4)].map((_, i) => (
16
+ <Skeleton key={i} className="h-8 w-24 rounded-full" />
17
+ ))}
18
+ </div>
19
+
20
+ {/* Product grid 2x4 */}
21
+ <div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4">
22
+ {[...Array(8)].map((_, i) => (
23
+ <div key={i} className="space-y-3">
24
+ <Skeleton className="aspect-square w-full rounded-lg" />
25
+ <Skeleton className="h-4 w-3/4" />
26
+ <Skeleton className="h-4 w-1/2" />
27
+ </div>
28
+ ))}
29
+ </div>
30
+ </div>
31
+ );
32
+ }
@@ -0,0 +1,95 @@
1
+ import { Metadata } from "next";
2
+ import { notFound } from "next/navigation";
3
+ import { Breadcrumbs } from "@/components/layout/breadcrumbs";
4
+ import { fetchCategory } from "@/lib/graphql/server";
5
+ import { CategoryProductsClient } from "./category-products-client";
6
+
7
+ /**
8
+ * Generate metadata for category pages (SEO)
9
+ */
10
+ export async function generateMetadata({
11
+ params,
12
+ }: {
13
+ params: Promise<{ slug: string }>;
14
+ }): Promise<Metadata> {
15
+ try {
16
+ const { slug } = await params;
17
+ const data = await fetchCategory(slug);
18
+ const category = data?.category;
19
+
20
+ if (!category) {
21
+ return { title: "Category Not Found" };
22
+ }
23
+
24
+ return {
25
+ title: category.name,
26
+ description:
27
+ category.description || `Browse ${category.name} products`,
28
+ };
29
+ } catch {
30
+ return { title: "Category" };
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Category detail page — Server Component
36
+ *
37
+ * Fetches category metadata on the server for SEO,
38
+ * passes category ID to client component for product filtering.
39
+ */
40
+ export default async function CategoryPage({
41
+ params,
42
+ }: {
43
+ params: Promise<{ slug: string }>;
44
+ }) {
45
+ const { slug } = await params;
46
+
47
+ let category;
48
+ try {
49
+ const data = await fetchCategory(slug);
50
+ category = data?.category;
51
+ } catch (error) {
52
+ console.error('[CategoryPage] Failed to fetch category:', error instanceof Error ? error.message : error);
53
+ }
54
+
55
+ if (!category) {
56
+ notFound();
57
+ }
58
+
59
+ return (
60
+ <div className="container mx-auto px-4 py-8">
61
+ <Breadcrumbs className="mb-6" />
62
+
63
+ {/* Category Header — SSR, SEO-friendly */}
64
+ <div className="mb-8">
65
+ <h1 className="text-3xl font-bold text-foreground">{category.name}</h1>
66
+ {category.description && (
67
+ <p className="mt-2 text-muted-foreground">{category.description}</p>
68
+ )}
69
+ {category.children.length > 0 && (
70
+ <div className="mt-4 flex flex-wrap gap-2">
71
+ {category.children.map((child) => (
72
+ <a
73
+ key={child.id}
74
+ href={`/categories/${child.slug}`}
75
+ className="rounded-full border border-border bg-muted px-3 py-1 text-sm text-foreground hover:bg-accent transition-colors"
76
+ >
77
+ {child.name}
78
+ {child.productCount > 0 && (
79
+ <span className="ml-1 text-muted-foreground">
80
+ ({child.productCount})
81
+ </span>
82
+ )}
83
+ </a>
84
+ ))}
85
+ </div>
86
+ )}
87
+ </div>
88
+
89
+ {/* Client component for product listing with filters */}
90
+ <CategoryProductsClient categoryId={category.id} />
91
+ </div>
92
+ );
93
+ }
94
+
95
+ export const revalidate = 60;
@@ -1,35 +1,44 @@
1
1
  import { Metadata } from "next";
2
- import Link from "next/link";
2
+ import { getTranslations } from "next-intl/server";
3
+ import { Link } from "@/i18n/navigation";
3
4
  import { Card } from "@/components/ui/card";
4
5
  import { fetchCategories } from "@/lib/graphql/server";
6
+ import type { CategoryNodeFields } from "@/lib/graphql/fragments";
5
7
 
6
- export const metadata: Metadata = {
7
- title: "Categories",
8
- description: "Browse products by category",
9
- };
8
+ export async function generateMetadata(): Promise<Metadata> {
9
+ const t = await getTranslations("categories");
10
+ return {
11
+ title: t("title"),
12
+ description: t("description"),
13
+ };
14
+ }
10
15
 
11
16
  // Enable ISR with 60 second revalidation
12
17
  export const revalidate = 60;
13
18
 
14
19
  export default async function CategoriesPage() {
15
- // Fetch categories from GraphQL API
16
- // Response structure: { categories: { roots: [...], totalCount } }
17
- const data = await fetchCategories();
20
+ const t = await getTranslations("categories");
21
+ let categoryList: CategoryNodeFields[] = [];
18
22
 
19
- const categoryList = data?.categories?.roots || [];
23
+ try {
24
+ const data = await fetchCategories();
25
+ categoryList = data?.categories?.roots || [];
26
+ } catch (error) {
27
+ console.error('[CategoriesPage] Failed to fetch categories:', error instanceof Error ? error.message : error);
28
+ }
20
29
 
21
30
  return (
22
31
  <div className="container mx-auto px-4 py-8">
23
32
  <div className="mb-8">
24
- <h1 className="text-3xl font-bold text-foreground">Categories</h1>
33
+ <h1 className="text-3xl font-bold text-foreground">{t("title")}</h1>
25
34
  <p className="mt-2 text-muted-foreground">
26
- Browse products by category
35
+ {t("description")}
27
36
  </p>
28
37
  </div>
29
38
 
30
39
  {categoryList.length === 0 ? (
31
40
  <div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
32
- <p className="text-muted-foreground">No categories available yet</p>
41
+ <p className="text-muted-foreground">{t("noCategories")}</p>
33
42
  </div>
34
43
  ) : (
35
44
  <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
@@ -0,0 +1,43 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import { Link } from "@/i18n/navigation";
5
+ import { AlertCircle } from "lucide-react";
6
+ import { Button } from "@/components/ui/button";
7
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
8
+
9
+ export default function CheckoutError({
10
+ error,
11
+ reset,
12
+ }: {
13
+ error: Error & { digest?: string };
14
+ reset: () => void;
15
+ }) {
16
+ useEffect(() => {
17
+ console.error("[Checkout Error]", error);
18
+ }, [error]);
19
+
20
+ return (
21
+ <div className="container mx-auto flex min-h-[400px] items-center justify-center px-4 py-16">
22
+ <Card className="max-w-md">
23
+ <CardHeader>
24
+ <CardTitle className="flex items-center gap-2 text-destructive">
25
+ <AlertCircle className="h-5 w-5" />
26
+ Checkout error
27
+ </CardTitle>
28
+ </CardHeader>
29
+ <CardContent className="space-y-4">
30
+ <p className="text-sm text-muted-foreground">
31
+ Something went wrong during checkout. Your cart items are safe.
32
+ </p>
33
+ <div className="flex gap-3">
34
+ <Button onClick={reset}>Try again</Button>
35
+ <Button variant="outline" asChild>
36
+ <Link href="/cart">Back to cart</Link>
37
+ </Button>
38
+ </div>
39
+ </CardContent>
40
+ </Card>
41
+ </div>
42
+ );
43
+ }
@@ -0,0 +1,31 @@
1
+ import { Skeleton } from "@/components/ui/skeleton";
2
+
3
+ export default function CheckoutLoading() {
4
+ return (
5
+ <div className="container mx-auto px-4 py-8">
6
+ <Skeleton className="mb-8 h-10 w-40" />
7
+ <div className="grid gap-8 lg:grid-cols-5">
8
+ {/* Checkout form */}
9
+ <div className="space-y-6 lg:col-span-3">
10
+ <Skeleton className="h-6 w-48" />
11
+ <div className="space-y-4">
12
+ <div className="grid grid-cols-2 gap-4">
13
+ <Skeleton className="h-10 w-full" />
14
+ <Skeleton className="h-10 w-full" />
15
+ </div>
16
+ <Skeleton className="h-10 w-full" />
17
+ <Skeleton className="h-10 w-full" />
18
+ <div className="grid grid-cols-2 gap-4">
19
+ <Skeleton className="h-10 w-full" />
20
+ <Skeleton className="h-10 w-full" />
21
+ </div>
22
+ </div>
23
+ </div>
24
+ {/* Order summary */}
25
+ <div className="lg:col-span-2">
26
+ <Skeleton className="h-80 w-full rounded-lg" />
27
+ </div>
28
+ </div>
29
+ </div>
30
+ );
31
+ }