@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,98 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --color-primary: rgb(59 130 246); /* blue-500 */
5
+ --color-primary-foreground: rgb(255 255 255);
6
+ --color-secondary: rgb(100 116 139); /* slate-500 */
7
+ --color-secondary-foreground: rgb(255 255 255);
8
+ --color-accent: rgb(249 115 22); /* orange-500 */
9
+ --color-accent-foreground: rgb(255 255 255);
10
+ --color-background: rgb(255 255 255);
11
+ --color-foreground: rgb(15 23 42); /* slate-900 */
12
+ --color-muted: rgb(241 245 249); /* slate-100 */
13
+ --color-muted-foreground: rgb(100 116 139); /* slate-500 */
14
+ --color-border: rgb(226 232 240); /* slate-200 */
15
+ --color-ring: rgb(59 130 246); /* blue-500 */
16
+ --radius: 0.5rem;
17
+ }
18
+
19
+ @layer base {
20
+ * {
21
+ border-color: var(--color-border);
22
+ }
23
+ body {
24
+ background-color: var(--color-background);
25
+ color: var(--color-foreground);
26
+ }
27
+ }
28
+
29
+ @utility btn {
30
+ display: inline-flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ border-radius: 0.5rem;
34
+ padding: 0.5rem 1rem;
35
+ font-weight: 500;
36
+ transition: color 150ms;
37
+ }
38
+
39
+ @utility btn-primary {
40
+ background-color: var(--color-primary);
41
+ color: white;
42
+ &:hover {
43
+ background-color: rgb(59 130 246 / 0.9);
44
+ }
45
+ }
46
+
47
+ @utility btn-secondary {
48
+ background-color: var(--color-secondary);
49
+ color: white;
50
+ &:hover {
51
+ background-color: rgb(100 116 139 / 0.9);
52
+ }
53
+ }
54
+
55
+ @utility btn-outline {
56
+ border: 1px solid var(--color-border);
57
+ background-color: transparent;
58
+ &:hover {
59
+ background-color: var(--color-muted);
60
+ }
61
+ }
62
+
63
+ @utility input {
64
+ display: flex;
65
+ height: 2.5rem;
66
+ width: 100%;
67
+ border-radius: 0.5rem;
68
+ border: 1px solid var(--color-border);
69
+ background-color: var(--color-background);
70
+ padding: 0.5rem 0.75rem;
71
+ font-size: 0.875rem;
72
+ &::placeholder {
73
+ color: var(--color-muted-foreground);
74
+ }
75
+ &:focus-visible {
76
+ outline: none;
77
+ ring: 2px solid var(--color-ring);
78
+ ring-offset: 2px;
79
+ }
80
+ &:disabled {
81
+ cursor: not-allowed;
82
+ opacity: 0.5;
83
+ }
84
+ }
85
+
86
+ @utility card {
87
+ border-radius: 0.5rem;
88
+ border: 1px solid var(--color-border);
89
+ background-color: var(--color-background);
90
+ padding: 1rem;
91
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
92
+ }
93
+
94
+ @layer utilities {
95
+ .text-balance {
96
+ text-wrap: balance;
97
+ }
98
+ }
@@ -0,0 +1,39 @@
1
+ import type { Metadata } from "next";
2
+ import { Inter } from "next/font/google";
3
+ import "./globals.css";
4
+ import { Header } from "@/components/layout/header";
5
+ import { Footer } from "@/components/layout/footer";
6
+ import { Providers } from "@/components/providers";
7
+
8
+ const inter = Inter({ subsets: ["latin"] });
9
+
10
+ const siteName = process.env.NEXT_PUBLIC_SITE_NAME || "My Store";
11
+
12
+ export const metadata: Metadata = {
13
+ title: `${siteName} - E-commerce Store`,
14
+ description: "Welcome to our online store powered by DoSwiftly Commerce",
15
+ };
16
+
17
+ // Force dynamic rendering because Header uses React Query hooks (CurrencySelector, CartIcon)
18
+ // TODO: Optimize by lazy-loading Header components that use hooks for better SSG support
19
+ export const dynamic = "force-dynamic";
20
+
21
+ export default function RootLayout({
22
+ children,
23
+ }: {
24
+ children: React.ReactNode;
25
+ }) {
26
+ return (
27
+ <html lang="en">
28
+ <body className={inter.className}>
29
+ <Providers>
30
+ <div className="flex min-h-screen flex-col">
31
+ <Header />
32
+ <main className="flex-1">{children}</main>
33
+ <Footer />
34
+ </div>
35
+ </Providers>
36
+ </body>
37
+ </html>
38
+ );
39
+ }
@@ -0,0 +1,136 @@
1
+ import Link from "next/link";
2
+ import {
3
+ useProducts,
4
+ useCategories,
5
+ } from "@doswiftly/commerce-sdk/graphql/server";
6
+
7
+ export default async function HomePage() {
8
+ // Fetch featured products
9
+ const { products } = await useProducts({ first: 8 });
10
+
11
+ // Fetch categories (roots are the top-level categories)
12
+ const { categories } = await useCategories();
13
+ const categoryRoots = categories.slice(0, 4);
14
+
15
+ return (
16
+ <div className="container mx-auto px-4 py-8">
17
+ {/* Hero Section */}
18
+ <section className="mb-16 text-center">
19
+ <h1 className="mb-4 text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl md:text-6xl">
20
+ Welcome to{" "}
21
+ <span className="text-primary">
22
+ {process.env.NEXT_PUBLIC_SITE_NAME || "My Store"}
23
+ </span>
24
+ </h1>
25
+ <p className="mx-auto mb-8 max-w-2xl text-lg text-gray-600">
26
+ Discover our curated collection of products. Quality meets
27
+ affordability.
28
+ </p>
29
+ <div className="flex justify-center gap-4">
30
+ <Link
31
+ href="/products"
32
+ className="rounded-lg bg-primary px-6 py-3 font-medium text-white transition hover:bg-primary/90"
33
+ >
34
+ Shop Now
35
+ </Link>
36
+ <Link
37
+ href="/collections"
38
+ className="rounded-lg border border-gray-300 px-6 py-3 font-medium text-gray-700 transition hover:bg-gray-50"
39
+ >
40
+ Browse Collections
41
+ </Link>
42
+ </div>
43
+ </section>
44
+
45
+ {/* Featured Products Section */}
46
+ <section className="mb-16">
47
+ <h2 className="mb-8 text-2xl font-bold text-gray-900">
48
+ Featured Products
49
+ </h2>
50
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
51
+ {products.length === 0 ? (
52
+ <div className="col-span-full rounded-lg border border-gray-200 p-8 text-center">
53
+ <div className="mb-4 h-48 rounded-lg bg-gray-100" />
54
+ <p className="text-gray-500">No products available</p>
55
+ <p className="mt-2 text-sm text-gray-400">
56
+ {process.env.NEXT_PUBLIC_SHOP_SLUG === "demo-shop"
57
+ ? "Start backend to load demo products"
58
+ : "Connect your shop to display products"}
59
+ </p>
60
+ </div>
61
+ ) : (
62
+ products.slice(0, 4).map((product) => (
63
+ <Link
64
+ key={product.id}
65
+ href={`/products/${product.handle}`}
66
+ className="group card transition hover:shadow-lg"
67
+ >
68
+ <div className="mb-4 aspect-square overflow-hidden rounded-lg bg-gray-100">
69
+ {product.featuredImage?.url ? (
70
+ <img
71
+ src={product.featuredImage.url}
72
+ alt={product.featuredImage.altText || product.title}
73
+ className="h-full w-full object-cover"
74
+ />
75
+ ) : (
76
+ <div className="flex h-full items-center justify-center text-gray-400">
77
+ {product.title}
78
+ </div>
79
+ )}
80
+ </div>
81
+ <h3 className="font-medium text-gray-900 group-hover:text-primary">
82
+ {product.title}
83
+ </h3>
84
+ <p className="mt-1 text-sm text-gray-500 line-clamp-2">
85
+ {product.description || "No description"}
86
+ </p>
87
+ <p className="mt-2 font-semibold text-primary">
88
+ {product.priceRange?.minVariantPrice?.amount}{" "}
89
+ {product.priceRange?.minVariantPrice?.currencyCode}
90
+ </p>
91
+ </Link>
92
+ ))
93
+ )}
94
+ </div>
95
+ </section>
96
+
97
+ {/* Categories Section */}
98
+ <section>
99
+ <h2 className="mb-8 text-2xl font-bold text-gray-900">
100
+ Shop by Category
101
+ </h2>
102
+ <div className="grid grid-cols-2 gap-4 md:grid-cols-4">
103
+ {categoryRoots.length > 0
104
+ ? categoryRoots.map((category) => (
105
+ <Link
106
+ key={category.id}
107
+ href={`/categories/${category.slug}`}
108
+ className="group rounded-lg border border-gray-200 p-6 text-center transition hover:border-primary hover:shadow-md"
109
+ >
110
+ <div className="mb-2 text-3xl">🛍️</div>
111
+ <span className="font-medium text-gray-700 group-hover:text-primary">
112
+ {category.name}
113
+ </span>
114
+ </Link>
115
+ ))
116
+ : ["Electronics", "Clothing", "Home & Garden", "Sports"].map(
117
+ (category) => (
118
+ <Link
119
+ key={category}
120
+ href={`/collections/${category
121
+ .toLowerCase()
122
+ .replace(/ & /g, "-")}`}
123
+ className="group rounded-lg border border-gray-200 p-6 text-center transition hover:border-primary hover:shadow-md"
124
+ >
125
+ <div className="mb-2 text-3xl">🛍️</div>
126
+ <span className="font-medium text-gray-700 group-hover:text-primary">
127
+ {category}
128
+ </span>
129
+ </Link>
130
+ )
131
+ )}
132
+ </div>
133
+ </section>
134
+ </div>
135
+ );
136
+ }
@@ -0,0 +1,119 @@
1
+ import Link from "next/link";
2
+ import { notFound } from "next/navigation";
3
+ import { useProduct } from "@doswiftly/commerce-sdk/graphql/server";
4
+ import { ProductActions } from "@/components/commerce/product-actions";
5
+
6
+ interface ProductPageProps {
7
+ params: Promise<{ slug: string }>;
8
+ }
9
+
10
+ interface ProductImage {
11
+ id?: string | null;
12
+ url: string;
13
+ altText?: string | null;
14
+ }
15
+
16
+ export default async function ProductPage({ params }: ProductPageProps) {
17
+ const { slug } = await params;
18
+
19
+ // Fetch product - normalized (direct object)
20
+ const { product } = await useProduct({ handle: slug });
21
+
22
+ if (!product) {
23
+ notFound();
24
+ }
25
+
26
+ return (
27
+ <div className="container mx-auto px-4 py-8">
28
+ {/* Breadcrumb */}
29
+ <nav className="mb-8 text-sm text-gray-500">
30
+ <Link href="/" className="hover:text-primary">
31
+ Home
32
+ </Link>
33
+ <span className="mx-2">/</span>
34
+ <Link href="/products" className="hover:text-primary">
35
+ Products
36
+ </Link>
37
+ <span className="mx-2">/</span>
38
+ <span className="text-gray-900">{product.title}</span>
39
+ </nav>
40
+
41
+ <div className="grid gap-12 lg:grid-cols-2">
42
+ {/* Product Images */}
43
+ <div className="space-y-4">
44
+ <div className="aspect-square overflow-hidden rounded-lg bg-gray-100">
45
+ {product.featuredImage?.url ? (
46
+ <img
47
+ src={product.featuredImage.url}
48
+ alt={product.featuredImage.altText || product.title}
49
+ className="h-full w-full object-cover"
50
+ />
51
+ ) : (
52
+ <div className="flex h-full items-center justify-center text-gray-400">
53
+ Product Image
54
+ </div>
55
+ )}
56
+ </div>
57
+ <div className="grid grid-cols-4 gap-4">
58
+ {product.images
59
+ ?.slice(0, 4)
60
+ .map((image: ProductImage, i: number) => (
61
+ <button
62
+ key={image.id || i}
63
+ className="aspect-square overflow-hidden rounded-lg bg-gray-100"
64
+ >
65
+ <img
66
+ src={image.url}
67
+ alt={image.altText || `Image ${i + 1}`}
68
+ className="h-full w-full object-cover"
69
+ />
70
+ </button>
71
+ ))}
72
+ </div>
73
+ </div>
74
+
75
+ {/* Product Info */}
76
+ <div>
77
+ <h1 className="text-3xl font-bold text-gray-900">{product.title}</h1>
78
+
79
+ <p className="mt-6 text-gray-600">
80
+ {product.description || "No description available"}
81
+ </p>
82
+
83
+ {/* Variant Selection, Quantity & Add to Cart */}
84
+ <div className="mt-8">
85
+ <ProductActions
86
+ variants={product.variants || []}
87
+ productId={product.id}
88
+ />
89
+ </div>
90
+
91
+ {/* Product Details */}
92
+ <div className="mt-12 border-t border-gray-200 pt-8">
93
+ <h2 className="text-lg font-semibold text-gray-900">
94
+ Product Details
95
+ </h2>
96
+ <dl className="mt-4 space-y-4 text-sm">
97
+ {product.vendor && (
98
+ <div className="flex justify-between">
99
+ <dt className="text-gray-500">Vendor</dt>
100
+ <dd className="text-gray-900">{product.vendor}</dd>
101
+ </div>
102
+ )}
103
+ {product.productType && (
104
+ <div className="flex justify-between">
105
+ <dt className="text-gray-500">Type</dt>
106
+ <dd className="text-gray-900">{product.productType}</dd>
107
+ </div>
108
+ )}
109
+ <div className="flex justify-between">
110
+ <dt className="text-gray-500">Handle</dt>
111
+ <dd className="text-gray-900">{product.handle}</dd>
112
+ </div>
113
+ </dl>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ </div>
118
+ );
119
+ }
@@ -0,0 +1,107 @@
1
+ import Link from "next/link";
2
+ import {
3
+ useProducts,
4
+ useCategories,
5
+ } from "@doswiftly/commerce-sdk/graphql/server";
6
+ import { ProductSortKeys } from "@doswiftly/commerce-sdk/graphql";
7
+ import { ProductFilters } from "@/components/commerce/product-filters";
8
+ import { Pagination } from "@/components/commerce/pagination";
9
+
10
+ interface ProductsPageProps {
11
+ searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
12
+ }
13
+
14
+ export default async function ProductsPage({
15
+ searchParams,
16
+ }: ProductsPageProps) {
17
+ // Parse search params (Next.js 15 requires await)
18
+ const params = await searchParams;
19
+ const cursor = params.after as string | undefined;
20
+ const limit = 12;
21
+ const sortKey =
22
+ (params.sort as keyof typeof ProductSortKeys) || ProductSortKeys.CreatedAt;
23
+ const query = params.q as string | undefined;
24
+ const category = params.category as string | undefined;
25
+
26
+ // Build query string for category filtering
27
+ const searchQuery = category ? `category:${category}` : query;
28
+
29
+ // Fetch products
30
+ const { products, pageInfo } = await useProducts({
31
+ first: limit,
32
+ after: cursor || undefined,
33
+ query: searchQuery || undefined,
34
+ sortKey: ProductSortKeys[sortKey as keyof typeof ProductSortKeys],
35
+ reverse: params.order === "desc",
36
+ });
37
+
38
+ // Fetch categories (roots are the top-level categories)
39
+ const { categories } = await useCategories();
40
+
41
+ // Calculate total (approximation since GraphQL uses cursor pagination)
42
+ const hasMore = pageInfo?.hasNextPage ?? false;
43
+
44
+ return (
45
+ <div className="container mx-auto px-4 py-8">
46
+ {/* Page Header */}
47
+ <div className="mb-8">
48
+ <h1 className="text-3xl font-bold text-gray-900">All Products</h1>
49
+ <p className="mt-2 text-gray-600">
50
+ Browse our complete collection of products
51
+ </p>
52
+ </div>
53
+
54
+ {/* Filters & Sort */}
55
+ <ProductFilters categories={categories} />
56
+
57
+ {/* Products Grid */}
58
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
59
+ {products.length === 0 ? (
60
+ <div className="col-span-full py-12 text-center text-gray-500">
61
+ No products found
62
+ </div>
63
+ ) : (
64
+ products.map((product) => (
65
+ <Link
66
+ key={product.id}
67
+ href={`/products/${product.handle}`}
68
+ className="group card transition hover:shadow-lg"
69
+ >
70
+ <div className="mb-4 aspect-square overflow-hidden rounded-lg bg-gray-100">
71
+ {product.featuredImage?.url ? (
72
+ <img
73
+ src={product.featuredImage.url}
74
+ alt={product.featuredImage.altText || product.title}
75
+ className="h-full w-full object-cover"
76
+ />
77
+ ) : (
78
+ <div className="flex h-full items-center justify-center text-gray-400">
79
+ {product.title}
80
+ </div>
81
+ )}
82
+ </div>
83
+ <h3 className="font-medium text-gray-900 group-hover:text-primary">
84
+ {product.title}
85
+ </h3>
86
+ <p className="mt-1 line-clamp-2 text-sm text-gray-500">
87
+ {product.description || "No description"}
88
+ </p>
89
+ <p className="mt-2 font-semibold text-primary">
90
+ {product.priceRange?.minVariantPrice?.amount}{" "}
91
+ {product.priceRange?.minVariantPrice?.currencyCode}
92
+ </p>
93
+ </Link>
94
+ ))
95
+ )}
96
+ </div>
97
+
98
+ {/* Pagination */}
99
+ <Pagination
100
+ hasMore={hasMore}
101
+ endCursor={pageInfo?.endCursor}
102
+ currentCursor={cursor}
103
+ totalShown={products.length}
104
+ />
105
+ </div>
106
+ );
107
+ }
@@ -0,0 +1,127 @@
1
+ import Link from "next/link";
2
+ import { useProducts } from "@doswiftly/commerce-sdk/graphql/server";
3
+ import { SearchInput } from "@/components/commerce/search-input";
4
+ import { Pagination } from "@/components/commerce/pagination";
5
+
6
+ interface SearchPageProps {
7
+ searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
8
+ }
9
+
10
+ export default async function SearchPage({ searchParams }: SearchPageProps) {
11
+ const params = await searchParams;
12
+ const query = (params.q as string) || "";
13
+ const cursor = params.after as string | undefined;
14
+ const limit = 12;
15
+
16
+ // Fetch search results
17
+ const result = query
18
+ ? await useProducts({
19
+ first: limit,
20
+ after: cursor || undefined,
21
+ query: query,
22
+ })
23
+ : null;
24
+ const products = result?.products ?? [];
25
+ const pageInfo = result?.pageInfo ?? null;
26
+
27
+ const hasMore = pageInfo?.hasNextPage ?? false;
28
+
29
+ return (
30
+ <div className="container mx-auto px-4 py-8">
31
+ {/* Search Header */}
32
+ <div className="mb-8">
33
+ <h1 className="mb-4 text-3xl font-bold text-gray-900">Search</h1>
34
+ <div className="max-w-xl">
35
+ <SearchInput placeholder="Search products..." />
36
+ </div>
37
+ </div>
38
+
39
+ {/* Results */}
40
+ {query ? (
41
+ <>
42
+ <p className="mb-6 text-gray-600">
43
+ {products.length > 0 ? (
44
+ <>
45
+ Showing results for &quot;<strong>{query}</strong>&quot;
46
+ </>
47
+ ) : (
48
+ <>
49
+ No results found for &quot;<strong>{query}</strong>&quot;
50
+ </>
51
+ )}
52
+ </p>
53
+
54
+ {products.length > 0 ? (
55
+ <>
56
+ {/* Products Grid */}
57
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
58
+ {products.map((product) => (
59
+ <Link
60
+ key={product.id}
61
+ href={`/products/${product.handle}`}
62
+ className="group card transition hover:shadow-lg"
63
+ >
64
+ <div className="mb-4 aspect-square overflow-hidden rounded-lg bg-gray-100">
65
+ {product.featuredImage?.url ? (
66
+ <img
67
+ src={product.featuredImage.url}
68
+ alt={product.featuredImage.altText || product.title}
69
+ className="h-full w-full object-cover"
70
+ />
71
+ ) : (
72
+ <div className="flex h-full items-center justify-center text-gray-400">
73
+ {product.title}
74
+ </div>
75
+ )}
76
+ </div>
77
+ <h3 className="font-medium text-gray-900 group-hover:text-primary">
78
+ {product.title}
79
+ </h3>
80
+ <p className="mt-1 line-clamp-2 text-sm text-gray-500">
81
+ {product.description || "No description"}
82
+ </p>
83
+ <p className="mt-2 font-semibold text-primary">
84
+ {product.priceRange?.minVariantPrice?.amount}{" "}
85
+ {product.priceRange?.minVariantPrice?.currencyCode}
86
+ </p>
87
+ </Link>
88
+ ))}
89
+ </div>
90
+
91
+ {/* Pagination */}
92
+ <Pagination
93
+ hasMore={hasMore}
94
+ endCursor={pageInfo?.endCursor}
95
+ currentCursor={cursor}
96
+ totalShown={products.length}
97
+ />
98
+ </>
99
+ ) : (
100
+ <div className="py-16 text-center">
101
+ <div className="mb-4 text-6xl">🔍</div>
102
+ <h2 className="mb-2 text-xl font-semibold text-gray-900">
103
+ No products found
104
+ </h2>
105
+ <p className="mb-8 text-gray-600">
106
+ Try adjusting your search terms or browse our products.
107
+ </p>
108
+ <Link href="/products" className="btn btn-primary">
109
+ Browse Products
110
+ </Link>
111
+ </div>
112
+ )}
113
+ </>
114
+ ) : (
115
+ <div className="py-16 text-center">
116
+ <div className="mb-4 text-6xl">🔎</div>
117
+ <h2 className="mb-2 text-xl font-semibold text-gray-900">
118
+ Search for products
119
+ </h2>
120
+ <p className="text-gray-600">
121
+ Enter a search term above to find products.
122
+ </p>
123
+ </div>
124
+ )}
125
+ </div>
126
+ );
127
+ }