@cimplify/cli 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (457) hide show
  1. package/README.md +69 -0
  2. package/dist/add-ZJQJZJEF.mjs +125 -0
  3. package/dist/chunk-4YSOZ6LY.mjs +61 -0
  4. package/dist/chunk-4ZVTPMUZ.mjs +155 -0
  5. package/dist/chunk-5XH72JMJ.mjs +211 -0
  6. package/dist/chunk-D7D75ONX.mjs +36 -0
  7. package/dist/chunk-JJYWETGA.mjs +127 -0
  8. package/dist/chunk-L6474RPL.mjs +37 -0
  9. package/dist/chunk-MQMNWLMU.mjs +48 -0
  10. package/dist/chunk-NZ4RG62Z.mjs +141 -0
  11. package/dist/chunk-TAMGCHIL.mjs +81 -0
  12. package/dist/chunk-XSWWWO6H.mjs +3779 -0
  13. package/dist/deploy-WCZOGMED.mjs +206 -0
  14. package/dist/dev-4HKIXWXX.mjs +130 -0
  15. package/dist/dispatcher.mjs +321 -0
  16. package/dist/domains-3RJ4T5IX.mjs +387 -0
  17. package/dist/env-LBYBCBWV.mjs +268 -0
  18. package/dist/link-SEJNW7JS.mjs +45 -0
  19. package/dist/list-D4JC2VWY.mjs +48 -0
  20. package/dist/login-MRYWLQRY.mjs +276 -0
  21. package/dist/logout-ZFZLSJ32.mjs +16 -0
  22. package/dist/logs-LK7CMBCE.mjs +95 -0
  23. package/dist/projects-QJUGOCQZ.mjs +164 -0
  24. package/dist/repo-MV22OHON.mjs +8 -0
  25. package/dist/rollback-XO7RIG2A.mjs +107 -0
  26. package/dist/status-7CMVLD54.mjs +127 -0
  27. package/dist/unlink-5ABCT7B6.mjs +16 -0
  28. package/dist/whoami-INHDUHWA.mjs +24 -0
  29. package/package.json +44 -0
  30. package/templates/storefront-bakery/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  31. package/templates/storefront-bakery/.cursor/rules/cimplify-storefront.mdc +25 -0
  32. package/templates/storefront-bakery/.env.example +16 -0
  33. package/templates/storefront-bakery/AGENTS.md +120 -0
  34. package/templates/storefront-bakery/CLAUDE.md +22 -0
  35. package/templates/storefront-bakery/README.md +73 -0
  36. package/templates/storefront-bakery/__tests__/brand.test.ts +4 -0
  37. package/templates/storefront-bakery/__tests__/cart-flow.test.ts +4 -0
  38. package/templates/storefront-bakery/__tests__/contract.test.ts +4 -0
  39. package/templates/storefront-bakery/app/about/page.tsx +38 -0
  40. package/templates/storefront-bakery/app/accessibility/page.tsx +11 -0
  41. package/templates/storefront-bakery/app/account/addresses/page.tsx +21 -0
  42. package/templates/storefront-bakery/app/account/orders/page.tsx +21 -0
  43. package/templates/storefront-bakery/app/account/page.tsx +22 -0
  44. package/templates/storefront-bakery/app/account/settings/page.tsx +21 -0
  45. package/templates/storefront-bakery/app/cart/page.tsx +9 -0
  46. package/templates/storefront-bakery/app/categories/[slug]/listing-client.tsx +19 -0
  47. package/templates/storefront-bakery/app/categories/[slug]/page.tsx +118 -0
  48. package/templates/storefront-bakery/app/checkout/page.tsx +17 -0
  49. package/templates/storefront-bakery/app/collections/[slug]/listing-client.tsx +20 -0
  50. package/templates/storefront-bakery/app/collections/[slug]/page.tsx +118 -0
  51. package/templates/storefront-bakery/app/contact/contact-form.tsx +109 -0
  52. package/templates/storefront-bakery/app/contact/page.tsx +54 -0
  53. package/templates/storefront-bakery/app/error.tsx +60 -0
  54. package/templates/storefront-bakery/app/faq/page.tsx +46 -0
  55. package/templates/storefront-bakery/app/globals.css +47 -0
  56. package/templates/storefront-bakery/app/layout.tsx +82 -0
  57. package/templates/storefront-bakery/app/llms.txt/route.ts +94 -0
  58. package/templates/storefront-bakery/app/login/page.tsx +17 -0
  59. package/templates/storefront-bakery/app/not-found.tsx +39 -0
  60. package/templates/storefront-bakery/app/opensearch.xml/route.ts +37 -0
  61. package/templates/storefront-bakery/app/orders/[id]/page.tsx +21 -0
  62. package/templates/storefront-bakery/app/page.tsx +97 -0
  63. package/templates/storefront-bakery/app/privacy/page.tsx +44 -0
  64. package/templates/storefront-bakery/app/returns/page.tsx +11 -0
  65. package/templates/storefront-bakery/app/robots.ts +18 -0
  66. package/templates/storefront-bakery/app/search/page.tsx +38 -0
  67. package/templates/storefront-bakery/app/search/search-client.tsx +7 -0
  68. package/templates/storefront-bakery/app/shipping/page.tsx +16 -0
  69. package/templates/storefront-bakery/app/shop/page.tsx +31 -0
  70. package/templates/storefront-bakery/app/shop/shop-client.tsx +27 -0
  71. package/templates/storefront-bakery/app/signup/page.tsx +17 -0
  72. package/templates/storefront-bakery/app/sitemap-page/page.tsx +167 -0
  73. package/templates/storefront-bakery/app/sitemap.ts +62 -0
  74. package/templates/storefront-bakery/app/terms/page.tsx +44 -0
  75. package/templates/storefront-bakery/app/track-order/page.tsx +24 -0
  76. package/templates/storefront-bakery/app/track-order/track-order-form.tsx +69 -0
  77. package/templates/storefront-bakery/components/account-iframe.tsx +13 -0
  78. package/templates/storefront-bakery/components/cart-drawer.tsx +14 -0
  79. package/templates/storefront-bakery/components/cart-pill.tsx +36 -0
  80. package/templates/storefront-bakery/components/category-grid.tsx +28 -0
  81. package/templates/storefront-bakery/components/collection-strip.tsx +45 -0
  82. package/templates/storefront-bakery/components/footer.tsx +148 -0
  83. package/templates/storefront-bakery/components/header.tsx +43 -0
  84. package/templates/storefront-bakery/components/hero.tsx +25 -0
  85. package/templates/storefront-bakery/components/nav-link.tsx +20 -0
  86. package/templates/storefront-bakery/components/policy-page.tsx +49 -0
  87. package/templates/storefront-bakery/components/product-modal.tsx +104 -0
  88. package/templates/storefront-bakery/components/providers.tsx +35 -0
  89. package/templates/storefront-bakery/components/store-product-card.tsx +87 -0
  90. package/templates/storefront-bakery/lib/brand.ts +570 -0
  91. package/templates/storefront-bakery/lib/cart.ts +12 -0
  92. package/templates/storefront-bakery/next.config.ts +42 -0
  93. package/templates/storefront-bakery/package.json +35 -0
  94. package/templates/storefront-bakery/postcss.config.mjs +7 -0
  95. package/templates/storefront-bakery/tsconfig.json +23 -0
  96. package/templates/storefront-bakery/vitest.config.ts +9 -0
  97. package/templates/storefront-fashion/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  98. package/templates/storefront-fashion/.cursor/rules/cimplify-storefront.mdc +25 -0
  99. package/templates/storefront-fashion/.env.example +16 -0
  100. package/templates/storefront-fashion/AGENTS.md +126 -0
  101. package/templates/storefront-fashion/CLAUDE.md +22 -0
  102. package/templates/storefront-fashion/README.md +77 -0
  103. package/templates/storefront-fashion/__tests__/brand.test.ts +4 -0
  104. package/templates/storefront-fashion/__tests__/cart-flow.test.ts +55 -0
  105. package/templates/storefront-fashion/__tests__/contract.test.ts +4 -0
  106. package/templates/storefront-fashion/app/about/page.tsx +41 -0
  107. package/templates/storefront-fashion/app/accessibility/page.tsx +11 -0
  108. package/templates/storefront-fashion/app/account/addresses/page.tsx +21 -0
  109. package/templates/storefront-fashion/app/account/orders/page.tsx +21 -0
  110. package/templates/storefront-fashion/app/account/page.tsx +22 -0
  111. package/templates/storefront-fashion/app/account/settings/page.tsx +21 -0
  112. package/templates/storefront-fashion/app/cart/page.tsx +9 -0
  113. package/templates/storefront-fashion/app/categories/[slug]/listing-client.tsx +19 -0
  114. package/templates/storefront-fashion/app/categories/[slug]/page.tsx +130 -0
  115. package/templates/storefront-fashion/app/checkout/page.tsx +17 -0
  116. package/templates/storefront-fashion/app/collections/[slug]/listing-client.tsx +20 -0
  117. package/templates/storefront-fashion/app/collections/[slug]/page.tsx +130 -0
  118. package/templates/storefront-fashion/app/contact/contact-form.tsx +109 -0
  119. package/templates/storefront-fashion/app/contact/page.tsx +54 -0
  120. package/templates/storefront-fashion/app/error.tsx +61 -0
  121. package/templates/storefront-fashion/app/faq/page.tsx +46 -0
  122. package/templates/storefront-fashion/app/globals.css +46 -0
  123. package/templates/storefront-fashion/app/layout.tsx +78 -0
  124. package/templates/storefront-fashion/app/llms.txt/route.ts +94 -0
  125. package/templates/storefront-fashion/app/login/page.tsx +17 -0
  126. package/templates/storefront-fashion/app/lookbook/page.tsx +132 -0
  127. package/templates/storefront-fashion/app/not-found.tsx +39 -0
  128. package/templates/storefront-fashion/app/opensearch.xml/route.ts +37 -0
  129. package/templates/storefront-fashion/app/orders/[id]/page.tsx +24 -0
  130. package/templates/storefront-fashion/app/page.tsx +183 -0
  131. package/templates/storefront-fashion/app/privacy/page.tsx +44 -0
  132. package/templates/storefront-fashion/app/products/[slug]/page.tsx +165 -0
  133. package/templates/storefront-fashion/app/products/[slug]/product-detail.tsx +70 -0
  134. package/templates/storefront-fashion/app/returns/page.tsx +11 -0
  135. package/templates/storefront-fashion/app/robots.ts +18 -0
  136. package/templates/storefront-fashion/app/search/page.tsx +38 -0
  137. package/templates/storefront-fashion/app/search/search-client.tsx +7 -0
  138. package/templates/storefront-fashion/app/shipping/page.tsx +16 -0
  139. package/templates/storefront-fashion/app/shop/page.tsx +63 -0
  140. package/templates/storefront-fashion/app/shop/shop-client.tsx +32 -0
  141. package/templates/storefront-fashion/app/signup/page.tsx +17 -0
  142. package/templates/storefront-fashion/app/sitemap-page/page.tsx +167 -0
  143. package/templates/storefront-fashion/app/sitemap.ts +59 -0
  144. package/templates/storefront-fashion/app/size-guide/page.tsx +155 -0
  145. package/templates/storefront-fashion/app/terms/page.tsx +44 -0
  146. package/templates/storefront-fashion/app/track-order/page.tsx +24 -0
  147. package/templates/storefront-fashion/app/track-order/track-order-form.tsx +69 -0
  148. package/templates/storefront-fashion/components/account-iframe.tsx +13 -0
  149. package/templates/storefront-fashion/components/brand-marquee.tsx +27 -0
  150. package/templates/storefront-fashion/components/cart-drawer.tsx +14 -0
  151. package/templates/storefront-fashion/components/cart-pill.tsx +36 -0
  152. package/templates/storefront-fashion/components/category-grid.tsx +28 -0
  153. package/templates/storefront-fashion/components/category-tiles.tsx +104 -0
  154. package/templates/storefront-fashion/components/collection-strip.tsx +45 -0
  155. package/templates/storefront-fashion/components/feature-hero.tsx +82 -0
  156. package/templates/storefront-fashion/components/footer.tsx +153 -0
  157. package/templates/storefront-fashion/components/header.tsx +43 -0
  158. package/templates/storefront-fashion/components/hero.tsx +28 -0
  159. package/templates/storefront-fashion/components/nav-link.tsx +20 -0
  160. package/templates/storefront-fashion/components/newsletter.tsx +50 -0
  161. package/templates/storefront-fashion/components/policy-page.tsx +49 -0
  162. package/templates/storefront-fashion/components/promo-banner.tsx +41 -0
  163. package/templates/storefront-fashion/components/providers.tsx +35 -0
  164. package/templates/storefront-fashion/components/section-heading.tsx +37 -0
  165. package/templates/storefront-fashion/components/store-product-card.tsx +87 -0
  166. package/templates/storefront-fashion/components/trade-in-cta.tsx +54 -0
  167. package/templates/storefront-fashion/components/trust-bar.tsx +66 -0
  168. package/templates/storefront-fashion/e2e/visual.spec.ts +52 -0
  169. package/templates/storefront-fashion/lib/brand.ts +518 -0
  170. package/templates/storefront-fashion/lib/cart.ts +12 -0
  171. package/templates/storefront-fashion/next.config.ts +42 -0
  172. package/templates/storefront-fashion/package.json +38 -0
  173. package/templates/storefront-fashion/playwright.config.ts +48 -0
  174. package/templates/storefront-fashion/postcss.config.mjs +7 -0
  175. package/templates/storefront-fashion/tsconfig.json +23 -0
  176. package/templates/storefront-fashion/vitest.config.ts +9 -0
  177. package/templates/storefront-grocery/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  178. package/templates/storefront-grocery/.cursor/rules/cimplify-storefront.mdc +25 -0
  179. package/templates/storefront-grocery/.env.example +16 -0
  180. package/templates/storefront-grocery/AGENTS.md +96 -0
  181. package/templates/storefront-grocery/CLAUDE.md +22 -0
  182. package/templates/storefront-grocery/README.md +73 -0
  183. package/templates/storefront-grocery/__tests__/brand.test.ts +4 -0
  184. package/templates/storefront-grocery/__tests__/cart-flow.test.ts +4 -0
  185. package/templates/storefront-grocery/__tests__/contract.test.ts +4 -0
  186. package/templates/storefront-grocery/app/about/page.tsx +38 -0
  187. package/templates/storefront-grocery/app/accessibility/page.tsx +11 -0
  188. package/templates/storefront-grocery/app/account/addresses/page.tsx +21 -0
  189. package/templates/storefront-grocery/app/account/orders/page.tsx +21 -0
  190. package/templates/storefront-grocery/app/account/page.tsx +22 -0
  191. package/templates/storefront-grocery/app/account/settings/page.tsx +21 -0
  192. package/templates/storefront-grocery/app/cart/page.tsx +9 -0
  193. package/templates/storefront-grocery/app/categories/[slug]/listing-client.tsx +19 -0
  194. package/templates/storefront-grocery/app/categories/[slug]/page.tsx +118 -0
  195. package/templates/storefront-grocery/app/checkout/page.tsx +17 -0
  196. package/templates/storefront-grocery/app/collections/[slug]/listing-client.tsx +20 -0
  197. package/templates/storefront-grocery/app/collections/[slug]/page.tsx +118 -0
  198. package/templates/storefront-grocery/app/contact/contact-form.tsx +109 -0
  199. package/templates/storefront-grocery/app/contact/page.tsx +54 -0
  200. package/templates/storefront-grocery/app/error.tsx +60 -0
  201. package/templates/storefront-grocery/app/faq/page.tsx +46 -0
  202. package/templates/storefront-grocery/app/globals.css +45 -0
  203. package/templates/storefront-grocery/app/layout.tsx +77 -0
  204. package/templates/storefront-grocery/app/llms.txt/route.ts +94 -0
  205. package/templates/storefront-grocery/app/login/page.tsx +17 -0
  206. package/templates/storefront-grocery/app/not-found.tsx +39 -0
  207. package/templates/storefront-grocery/app/opensearch.xml/route.ts +37 -0
  208. package/templates/storefront-grocery/app/orders/[id]/page.tsx +21 -0
  209. package/templates/storefront-grocery/app/page.tsx +97 -0
  210. package/templates/storefront-grocery/app/privacy/page.tsx +44 -0
  211. package/templates/storefront-grocery/app/returns/page.tsx +11 -0
  212. package/templates/storefront-grocery/app/robots.ts +18 -0
  213. package/templates/storefront-grocery/app/search/page.tsx +38 -0
  214. package/templates/storefront-grocery/app/search/search-client.tsx +7 -0
  215. package/templates/storefront-grocery/app/shipping/page.tsx +16 -0
  216. package/templates/storefront-grocery/app/shop/page.tsx +31 -0
  217. package/templates/storefront-grocery/app/shop/shop-client.tsx +27 -0
  218. package/templates/storefront-grocery/app/signup/page.tsx +17 -0
  219. package/templates/storefront-grocery/app/sitemap-page/page.tsx +167 -0
  220. package/templates/storefront-grocery/app/sitemap.ts +62 -0
  221. package/templates/storefront-grocery/app/terms/page.tsx +44 -0
  222. package/templates/storefront-grocery/app/track-order/page.tsx +24 -0
  223. package/templates/storefront-grocery/app/track-order/track-order-form.tsx +69 -0
  224. package/templates/storefront-grocery/components/account-iframe.tsx +13 -0
  225. package/templates/storefront-grocery/components/cart-drawer.tsx +14 -0
  226. package/templates/storefront-grocery/components/cart-pill.tsx +36 -0
  227. package/templates/storefront-grocery/components/category-grid.tsx +28 -0
  228. package/templates/storefront-grocery/components/collection-strip.tsx +45 -0
  229. package/templates/storefront-grocery/components/footer.tsx +148 -0
  230. package/templates/storefront-grocery/components/header.tsx +43 -0
  231. package/templates/storefront-grocery/components/hero.tsx +25 -0
  232. package/templates/storefront-grocery/components/nav-link.tsx +20 -0
  233. package/templates/storefront-grocery/components/policy-page.tsx +49 -0
  234. package/templates/storefront-grocery/components/product-modal.tsx +104 -0
  235. package/templates/storefront-grocery/components/providers.tsx +35 -0
  236. package/templates/storefront-grocery/components/store-product-card.tsx +87 -0
  237. package/templates/storefront-grocery/lib/brand.ts +375 -0
  238. package/templates/storefront-grocery/lib/cart.ts +12 -0
  239. package/templates/storefront-grocery/next.config.ts +42 -0
  240. package/templates/storefront-grocery/package.json +35 -0
  241. package/templates/storefront-grocery/postcss.config.mjs +7 -0
  242. package/templates/storefront-grocery/tsconfig.json +23 -0
  243. package/templates/storefront-grocery/vitest.config.ts +9 -0
  244. package/templates/storefront-restaurant/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  245. package/templates/storefront-restaurant/.cursor/rules/cimplify-storefront.mdc +25 -0
  246. package/templates/storefront-restaurant/.env.example +16 -0
  247. package/templates/storefront-restaurant/AGENTS.md +102 -0
  248. package/templates/storefront-restaurant/CLAUDE.md +22 -0
  249. package/templates/storefront-restaurant/README.md +73 -0
  250. package/templates/storefront-restaurant/__tests__/brand.test.ts +4 -0
  251. package/templates/storefront-restaurant/__tests__/cart-flow.test.ts +4 -0
  252. package/templates/storefront-restaurant/__tests__/contract.test.ts +4 -0
  253. package/templates/storefront-restaurant/app/about/page.tsx +38 -0
  254. package/templates/storefront-restaurant/app/accessibility/page.tsx +11 -0
  255. package/templates/storefront-restaurant/app/account/addresses/page.tsx +21 -0
  256. package/templates/storefront-restaurant/app/account/orders/page.tsx +21 -0
  257. package/templates/storefront-restaurant/app/account/page.tsx +22 -0
  258. package/templates/storefront-restaurant/app/account/settings/page.tsx +21 -0
  259. package/templates/storefront-restaurant/app/cart/page.tsx +9 -0
  260. package/templates/storefront-restaurant/app/categories/[slug]/listing-client.tsx +19 -0
  261. package/templates/storefront-restaurant/app/categories/[slug]/page.tsx +118 -0
  262. package/templates/storefront-restaurant/app/checkout/page.tsx +17 -0
  263. package/templates/storefront-restaurant/app/collections/[slug]/listing-client.tsx +20 -0
  264. package/templates/storefront-restaurant/app/collections/[slug]/page.tsx +118 -0
  265. package/templates/storefront-restaurant/app/contact/contact-form.tsx +109 -0
  266. package/templates/storefront-restaurant/app/contact/page.tsx +54 -0
  267. package/templates/storefront-restaurant/app/error.tsx +60 -0
  268. package/templates/storefront-restaurant/app/faq/page.tsx +46 -0
  269. package/templates/storefront-restaurant/app/globals.css +44 -0
  270. package/templates/storefront-restaurant/app/layout.tsx +82 -0
  271. package/templates/storefront-restaurant/app/llms.txt/route.ts +94 -0
  272. package/templates/storefront-restaurant/app/login/page.tsx +17 -0
  273. package/templates/storefront-restaurant/app/not-found.tsx +39 -0
  274. package/templates/storefront-restaurant/app/opensearch.xml/route.ts +37 -0
  275. package/templates/storefront-restaurant/app/orders/[id]/page.tsx +21 -0
  276. package/templates/storefront-restaurant/app/page.tsx +97 -0
  277. package/templates/storefront-restaurant/app/privacy/page.tsx +44 -0
  278. package/templates/storefront-restaurant/app/reservations/page.tsx +66 -0
  279. package/templates/storefront-restaurant/app/reservations/reservations-client.tsx +234 -0
  280. package/templates/storefront-restaurant/app/returns/page.tsx +11 -0
  281. package/templates/storefront-restaurant/app/robots.ts +18 -0
  282. package/templates/storefront-restaurant/app/search/page.tsx +38 -0
  283. package/templates/storefront-restaurant/app/search/search-client.tsx +7 -0
  284. package/templates/storefront-restaurant/app/shipping/page.tsx +16 -0
  285. package/templates/storefront-restaurant/app/shop/page.tsx +31 -0
  286. package/templates/storefront-restaurant/app/shop/shop-client.tsx +27 -0
  287. package/templates/storefront-restaurant/app/signup/page.tsx +17 -0
  288. package/templates/storefront-restaurant/app/sitemap-page/page.tsx +167 -0
  289. package/templates/storefront-restaurant/app/sitemap.ts +62 -0
  290. package/templates/storefront-restaurant/app/terms/page.tsx +44 -0
  291. package/templates/storefront-restaurant/app/track-order/page.tsx +24 -0
  292. package/templates/storefront-restaurant/app/track-order/track-order-form.tsx +69 -0
  293. package/templates/storefront-restaurant/components/account-iframe.tsx +13 -0
  294. package/templates/storefront-restaurant/components/cart-drawer.tsx +14 -0
  295. package/templates/storefront-restaurant/components/cart-pill.tsx +36 -0
  296. package/templates/storefront-restaurant/components/category-grid.tsx +28 -0
  297. package/templates/storefront-restaurant/components/collection-strip.tsx +45 -0
  298. package/templates/storefront-restaurant/components/footer.tsx +148 -0
  299. package/templates/storefront-restaurant/components/header.tsx +43 -0
  300. package/templates/storefront-restaurant/components/hero.tsx +25 -0
  301. package/templates/storefront-restaurant/components/nav-link.tsx +20 -0
  302. package/templates/storefront-restaurant/components/policy-page.tsx +49 -0
  303. package/templates/storefront-restaurant/components/product-modal.tsx +104 -0
  304. package/templates/storefront-restaurant/components/providers.tsx +35 -0
  305. package/templates/storefront-restaurant/components/store-product-card.tsx +87 -0
  306. package/templates/storefront-restaurant/lib/brand.ts +377 -0
  307. package/templates/storefront-restaurant/lib/cart.ts +12 -0
  308. package/templates/storefront-restaurant/next.config.ts +42 -0
  309. package/templates/storefront-restaurant/package.json +35 -0
  310. package/templates/storefront-restaurant/postcss.config.mjs +7 -0
  311. package/templates/storefront-restaurant/tsconfig.json +23 -0
  312. package/templates/storefront-restaurant/vitest.config.ts +9 -0
  313. package/templates/storefront-retail/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  314. package/templates/storefront-retail/.cursor/rules/cimplify-storefront.mdc +25 -0
  315. package/templates/storefront-retail/.env.example +16 -0
  316. package/templates/storefront-retail/AGENTS.md +117 -0
  317. package/templates/storefront-retail/CLAUDE.md +22 -0
  318. package/templates/storefront-retail/README.md +77 -0
  319. package/templates/storefront-retail/__tests__/brand.test.ts +4 -0
  320. package/templates/storefront-retail/__tests__/cart-flow.test.ts +4 -0
  321. package/templates/storefront-retail/__tests__/contract.test.ts +4 -0
  322. package/templates/storefront-retail/app/about/page.tsx +41 -0
  323. package/templates/storefront-retail/app/accessibility/page.tsx +11 -0
  324. package/templates/storefront-retail/app/account/addresses/page.tsx +21 -0
  325. package/templates/storefront-retail/app/account/orders/page.tsx +21 -0
  326. package/templates/storefront-retail/app/account/page.tsx +22 -0
  327. package/templates/storefront-retail/app/account/settings/page.tsx +21 -0
  328. package/templates/storefront-retail/app/cart/page.tsx +9 -0
  329. package/templates/storefront-retail/app/categories/[slug]/listing-client.tsx +19 -0
  330. package/templates/storefront-retail/app/categories/[slug]/page.tsx +130 -0
  331. package/templates/storefront-retail/app/checkout/page.tsx +17 -0
  332. package/templates/storefront-retail/app/collections/[slug]/listing-client.tsx +20 -0
  333. package/templates/storefront-retail/app/collections/[slug]/page.tsx +130 -0
  334. package/templates/storefront-retail/app/contact/contact-form.tsx +109 -0
  335. package/templates/storefront-retail/app/contact/page.tsx +54 -0
  336. package/templates/storefront-retail/app/error.tsx +61 -0
  337. package/templates/storefront-retail/app/faq/page.tsx +46 -0
  338. package/templates/storefront-retail/app/globals.css +47 -0
  339. package/templates/storefront-retail/app/layout.tsx +77 -0
  340. package/templates/storefront-retail/app/llms.txt/route.ts +94 -0
  341. package/templates/storefront-retail/app/login/page.tsx +17 -0
  342. package/templates/storefront-retail/app/not-found.tsx +39 -0
  343. package/templates/storefront-retail/app/opensearch.xml/route.ts +37 -0
  344. package/templates/storefront-retail/app/orders/[id]/page.tsx +24 -0
  345. package/templates/storefront-retail/app/page.tsx +182 -0
  346. package/templates/storefront-retail/app/privacy/page.tsx +44 -0
  347. package/templates/storefront-retail/app/products/[slug]/page.tsx +165 -0
  348. package/templates/storefront-retail/app/products/[slug]/product-detail.tsx +70 -0
  349. package/templates/storefront-retail/app/returns/page.tsx +11 -0
  350. package/templates/storefront-retail/app/robots.ts +18 -0
  351. package/templates/storefront-retail/app/search/page.tsx +38 -0
  352. package/templates/storefront-retail/app/search/search-client.tsx +7 -0
  353. package/templates/storefront-retail/app/shipping/page.tsx +16 -0
  354. package/templates/storefront-retail/app/shop/page.tsx +63 -0
  355. package/templates/storefront-retail/app/shop/shop-client.tsx +32 -0
  356. package/templates/storefront-retail/app/signup/page.tsx +17 -0
  357. package/templates/storefront-retail/app/sitemap-page/page.tsx +167 -0
  358. package/templates/storefront-retail/app/sitemap.ts +59 -0
  359. package/templates/storefront-retail/app/terms/page.tsx +44 -0
  360. package/templates/storefront-retail/app/track-order/page.tsx +24 -0
  361. package/templates/storefront-retail/app/track-order/track-order-form.tsx +69 -0
  362. package/templates/storefront-retail/components/account-iframe.tsx +13 -0
  363. package/templates/storefront-retail/components/brand-marquee.tsx +27 -0
  364. package/templates/storefront-retail/components/cart-drawer.tsx +14 -0
  365. package/templates/storefront-retail/components/cart-pill.tsx +36 -0
  366. package/templates/storefront-retail/components/category-grid.tsx +28 -0
  367. package/templates/storefront-retail/components/category-tiles.tsx +104 -0
  368. package/templates/storefront-retail/components/collection-strip.tsx +45 -0
  369. package/templates/storefront-retail/components/feature-hero.tsx +84 -0
  370. package/templates/storefront-retail/components/footer.tsx +153 -0
  371. package/templates/storefront-retail/components/header.tsx +45 -0
  372. package/templates/storefront-retail/components/hero.tsx +28 -0
  373. package/templates/storefront-retail/components/nav-link.tsx +20 -0
  374. package/templates/storefront-retail/components/newsletter.tsx +50 -0
  375. package/templates/storefront-retail/components/policy-page.tsx +49 -0
  376. package/templates/storefront-retail/components/promo-banner.tsx +41 -0
  377. package/templates/storefront-retail/components/providers.tsx +35 -0
  378. package/templates/storefront-retail/components/section-heading.tsx +37 -0
  379. package/templates/storefront-retail/components/store-product-card.tsx +87 -0
  380. package/templates/storefront-retail/components/trade-in-cta.tsx +54 -0
  381. package/templates/storefront-retail/components/trust-bar.tsx +66 -0
  382. package/templates/storefront-retail/lib/brand.ts +664 -0
  383. package/templates/storefront-retail/lib/cart.ts +12 -0
  384. package/templates/storefront-retail/next.config.ts +42 -0
  385. package/templates/storefront-retail/package.json +35 -0
  386. package/templates/storefront-retail/postcss.config.mjs +7 -0
  387. package/templates/storefront-retail/tsconfig.json +23 -0
  388. package/templates/storefront-retail/vitest.config.ts +9 -0
  389. package/templates/storefront-services/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  390. package/templates/storefront-services/.cursor/rules/cimplify-storefront.mdc +25 -0
  391. package/templates/storefront-services/.env.example +16 -0
  392. package/templates/storefront-services/AGENTS.md +101 -0
  393. package/templates/storefront-services/CLAUDE.md +22 -0
  394. package/templates/storefront-services/README.md +73 -0
  395. package/templates/storefront-services/__tests__/brand.test.ts +4 -0
  396. package/templates/storefront-services/__tests__/cart-flow.test.ts +4 -0
  397. package/templates/storefront-services/__tests__/contract.test.ts +4 -0
  398. package/templates/storefront-services/app/about/page.tsx +38 -0
  399. package/templates/storefront-services/app/accessibility/page.tsx +11 -0
  400. package/templates/storefront-services/app/account/addresses/page.tsx +21 -0
  401. package/templates/storefront-services/app/account/orders/page.tsx +21 -0
  402. package/templates/storefront-services/app/account/page.tsx +22 -0
  403. package/templates/storefront-services/app/account/settings/page.tsx +21 -0
  404. package/templates/storefront-services/app/book/book-client.tsx +195 -0
  405. package/templates/storefront-services/app/book/page.tsx +65 -0
  406. package/templates/storefront-services/app/cart/page.tsx +9 -0
  407. package/templates/storefront-services/app/categories/[slug]/listing-client.tsx +19 -0
  408. package/templates/storefront-services/app/categories/[slug]/page.tsx +118 -0
  409. package/templates/storefront-services/app/checkout/page.tsx +17 -0
  410. package/templates/storefront-services/app/collections/[slug]/listing-client.tsx +20 -0
  411. package/templates/storefront-services/app/collections/[slug]/page.tsx +118 -0
  412. package/templates/storefront-services/app/contact/contact-form.tsx +109 -0
  413. package/templates/storefront-services/app/contact/page.tsx +54 -0
  414. package/templates/storefront-services/app/error.tsx +60 -0
  415. package/templates/storefront-services/app/faq/page.tsx +46 -0
  416. package/templates/storefront-services/app/globals.css +45 -0
  417. package/templates/storefront-services/app/layout.tsx +82 -0
  418. package/templates/storefront-services/app/llms.txt/route.ts +94 -0
  419. package/templates/storefront-services/app/login/page.tsx +17 -0
  420. package/templates/storefront-services/app/not-found.tsx +39 -0
  421. package/templates/storefront-services/app/opensearch.xml/route.ts +37 -0
  422. package/templates/storefront-services/app/orders/[id]/page.tsx +21 -0
  423. package/templates/storefront-services/app/page.tsx +97 -0
  424. package/templates/storefront-services/app/privacy/page.tsx +44 -0
  425. package/templates/storefront-services/app/returns/page.tsx +11 -0
  426. package/templates/storefront-services/app/robots.ts +18 -0
  427. package/templates/storefront-services/app/search/page.tsx +38 -0
  428. package/templates/storefront-services/app/search/search-client.tsx +7 -0
  429. package/templates/storefront-services/app/shipping/page.tsx +16 -0
  430. package/templates/storefront-services/app/shop/page.tsx +31 -0
  431. package/templates/storefront-services/app/shop/shop-client.tsx +27 -0
  432. package/templates/storefront-services/app/signup/page.tsx +17 -0
  433. package/templates/storefront-services/app/sitemap-page/page.tsx +167 -0
  434. package/templates/storefront-services/app/sitemap.ts +62 -0
  435. package/templates/storefront-services/app/terms/page.tsx +44 -0
  436. package/templates/storefront-services/app/track-order/page.tsx +24 -0
  437. package/templates/storefront-services/app/track-order/track-order-form.tsx +69 -0
  438. package/templates/storefront-services/components/account-iframe.tsx +13 -0
  439. package/templates/storefront-services/components/cart-drawer.tsx +14 -0
  440. package/templates/storefront-services/components/cart-pill.tsx +36 -0
  441. package/templates/storefront-services/components/category-grid.tsx +28 -0
  442. package/templates/storefront-services/components/collection-strip.tsx +45 -0
  443. package/templates/storefront-services/components/footer.tsx +148 -0
  444. package/templates/storefront-services/components/header.tsx +43 -0
  445. package/templates/storefront-services/components/hero.tsx +25 -0
  446. package/templates/storefront-services/components/nav-link.tsx +20 -0
  447. package/templates/storefront-services/components/policy-page.tsx +49 -0
  448. package/templates/storefront-services/components/product-modal.tsx +104 -0
  449. package/templates/storefront-services/components/providers.tsx +35 -0
  450. package/templates/storefront-services/components/store-product-card.tsx +87 -0
  451. package/templates/storefront-services/lib/brand.ts +396 -0
  452. package/templates/storefront-services/lib/cart.ts +12 -0
  453. package/templates/storefront-services/next.config.ts +42 -0
  454. package/templates/storefront-services/package.json +35 -0
  455. package/templates/storefront-services/postcss.config.mjs +7 -0
  456. package/templates/storefront-services/tsconfig.json +23 -0
  457. package/templates/storefront-services/vitest.config.ts +9 -0
@@ -0,0 +1,78 @@
1
+ import type { Metadata } from "next";
2
+ import { Inter, Anton } from "next/font/google";
3
+ import "./globals.css";
4
+ import { Providers } from "@/components/providers";
5
+ import { Header } from "@/components/header";
6
+ import { Footer } from "@/components/footer";
7
+ import { CartDrawer } from "@/components/cart-drawer";
8
+ import { brand } from "@/lib/brand";
9
+
10
+ const inter = Inter({
11
+ subsets: ["latin"],
12
+ variable: "--font-sans",
13
+ display: "swap",
14
+ });
15
+
16
+ const anton = Anton({
17
+ subsets: ["latin"],
18
+ variable: "--font-display",
19
+ weight: "400",
20
+ display: "swap",
21
+ });
22
+
23
+ const SITE_URL =
24
+ process.env.NEXT_PUBLIC_SITE_URL?.trim() || "https://example.com";
25
+
26
+ export const metadata: Metadata = {
27
+ metadataBase: new URL(SITE_URL),
28
+ title: {
29
+ default: brand.name,
30
+ template: `%s — ${brand.name}`,
31
+ },
32
+ description: brand.description,
33
+ openGraph: {
34
+ type: "website",
35
+ siteName: brand.name,
36
+ locale: brand.locale,
37
+ },
38
+ twitter: { card: "summary_large_image" },
39
+ };
40
+
41
+ const ORGANIZATION_LD = {
42
+ "@context": "https://schema.org",
43
+ "@type": brand.schemaType,
44
+ name: brand.name,
45
+ url: SITE_URL,
46
+ description: brand.description,
47
+ email: brand.contact.email,
48
+ telephone: brand.contact.phoneTel,
49
+ address: {
50
+ "@type": "PostalAddress",
51
+ streetAddress: brand.contact.streetAddress,
52
+ addressLocality: brand.contact.city,
53
+ addressCountry: brand.contact.countryCode,
54
+ },
55
+ sameAs: brand.socials.map((s) => s.href),
56
+ };
57
+
58
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
59
+ return (
60
+ <html lang="en" suppressHydrationWarning className={`${inter.variable} ${anton.variable}`}>
61
+ <body
62
+ suppressHydrationWarning
63
+ className="min-h-screen flex flex-col bg-background text-foreground font-sans"
64
+ >
65
+ <script
66
+ type="application/ld+json"
67
+ dangerouslySetInnerHTML={{ __html: JSON.stringify(ORGANIZATION_LD) }}
68
+ />
69
+ <Providers>
70
+ <Header />
71
+ <main className="flex-1 pb-12 w-full">{children}</main>
72
+ <Footer />
73
+ <CartDrawer />
74
+ </Providers>
75
+ </body>
76
+ </html>
77
+ );
78
+ }
@@ -0,0 +1,94 @@
1
+ import { cacheTag, cacheLife } from "next/cache";
2
+ import { getServerClient, tags, type Product } from "@cimplify/sdk/server";
3
+ import { brand } from "@/lib/brand";
4
+
5
+ const SITE_URL =
6
+ process.env.NEXT_PUBLIC_SITE_URL?.trim() || "https://example.com";
7
+
8
+ async function buildLlmsTxt(): Promise<string> {
9
+ "use cache";
10
+ cacheTag(tags.products(), tags.categories(), tags.collections());
11
+ cacheLife("hours");
12
+
13
+ const client = getServerClient();
14
+ const [productsRes, categoriesRes, collectionsRes] = await Promise.all([
15
+ client.catalogue.getProducts({ limit: 500 }),
16
+ client.catalogue.getCategories(),
17
+ client.catalogue.getCollections(),
18
+ ]);
19
+
20
+ const products: Product[] = productsRes.ok ? productsRes.value.items : [];
21
+ const categories = categoriesRes.ok ? categoriesRes.value : [];
22
+ const collections = collectionsRes.ok ? collectionsRes.value : [];
23
+
24
+ const lines: string[] = [];
25
+ lines.push(`# ${brand.name}`);
26
+ lines.push("");
27
+ lines.push(`> ${brand.llms.summary}`);
28
+ lines.push("");
29
+ lines.push("## Browse");
30
+ lines.push(`- [Home](${SITE_URL}/)`);
31
+ lines.push(`- [Shop](${SITE_URL}/shop): Full catalogue with filter and sort.`);
32
+
33
+ if (categories.length > 0) {
34
+ lines.push("");
35
+ lines.push("## Categories");
36
+ for (const c of categories) {
37
+ lines.push(
38
+ `- [${c.name}](${SITE_URL}/categories/${c.slug})${c.description ? `: ${c.description}` : ""}`,
39
+ );
40
+ }
41
+ }
42
+
43
+ if (collections.length > 0) {
44
+ lines.push("");
45
+ lines.push("## Collections");
46
+ for (const c of collections) {
47
+ lines.push(
48
+ `- [${c.name}](${SITE_URL}/collections/${c.slug})${c.description ? `: ${c.description}` : ""}`,
49
+ );
50
+ }
51
+ }
52
+
53
+ if (products.length > 0) {
54
+ lines.push("");
55
+ lines.push("## Products");
56
+ for (const p of products) {
57
+ const slug = p.slug ?? p.id;
58
+ const price = `${brand.currency} ${p.default_price}`;
59
+ const desc = p.description ? ` — ${p.description.replace(/\s+/g, " ").slice(0, 200)}` : "";
60
+ lines.push(`- [${p.name}](${SITE_URL}/products/${slug}) (${price})${desc}`);
61
+ }
62
+ }
63
+
64
+ lines.push("");
65
+ lines.push("## Information");
66
+ lines.push(`- [About](${SITE_URL}/about)`);
67
+ lines.push(`- [Support / FAQ](${SITE_URL}/faq)`);
68
+ lines.push(`- [Terms of Service](${SITE_URL}/terms)`);
69
+ lines.push(`- [Privacy Policy](${SITE_URL}/privacy)`);
70
+ lines.push(`- [Sitemap (XML)](${SITE_URL}/sitemap.xml)`);
71
+ lines.push("");
72
+ lines.push("## Contact");
73
+ lines.push(`- Email: ${brand.contact.email}`);
74
+ lines.push(`- Phone: ${brand.contact.phone}`);
75
+ lines.push(`- Address: ${brand.contact.address}`);
76
+
77
+ return lines.join("\n") + "\n";
78
+ }
79
+
80
+ /**
81
+ * `/llms.txt` — machine-readable site index for LLMs (per llmstxt.org).
82
+ * Lets coding agents and chat assistants find products, categories, and
83
+ * support pages without scraping HTML. Plain Markdown so it streams cheaply
84
+ * into context windows.
85
+ */
86
+ export async function GET(): Promise<Response> {
87
+ const body = await buildLlmsTxt();
88
+ return new Response(body, {
89
+ headers: {
90
+ "Content-Type": "text/plain; charset=utf-8",
91
+ "Cache-Control": "public, max-age=0, s-maxage=3600, stale-while-revalidate=86400",
92
+ },
93
+ });
94
+ }
@@ -0,0 +1,17 @@
1
+ import type { Metadata } from "next";
2
+ import { redirect } from "next/navigation";
3
+ import { brand } from "@/lib/brand";
4
+
5
+ export const metadata: Metadata = {
6
+ title: `Sign in — ${brand.name}`,
7
+ description: brand.account.loginSubtitle,
8
+ };
9
+
10
+ /**
11
+ * Cimplify Link (the iframe in `<CimplifyAccount>`) handles sign-in
12
+ * automatically when no session exists. We just bounce /login to /account
13
+ * so consumers landing here get the right UI without a duplicate form.
14
+ */
15
+ export default function LoginPage(): never {
16
+ redirect("/account");
17
+ }
@@ -0,0 +1,132 @@
1
+ import type { Metadata } from "next";
2
+ import Image from "next/image";
3
+ import Link from "next/link";
4
+ import { brand } from "@/lib/brand";
5
+
6
+ export const metadata: Metadata = {
7
+ title: `Lookbook — ${brand.name}`,
8
+ description: "Editorial photography from each Studio FRX drop.",
9
+ };
10
+
11
+ interface LookbookEntry {
12
+ drop: string;
13
+ title: string;
14
+ hero: string;
15
+ tiles: string[];
16
+ byline: string;
17
+ date: string;
18
+ }
19
+
20
+ // Each entry is a drop; tiles are the editorial shots. Replace the URLs
21
+ // with your own asset bucket / CDN before going live.
22
+ const ENTRIES: LookbookEntry[] = [
23
+ {
24
+ drop: "Drop 04",
25
+ title: "Built for now.",
26
+ date: "Spring 2026",
27
+ byline: "Photographed by Selasi Adjei in Jamestown, Accra.",
28
+ hero: "https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=1800&h=1100&fit=crop&auto=format&q=85",
29
+ tiles: [
30
+ "https://images.unsplash.com/photo-1483985988355-763728e1935b?w=900&h=1200&fit=crop&auto=format&q=85",
31
+ "https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?w=900&h=1200&fit=crop&auto=format&q=85",
32
+ "https://images.unsplash.com/photo-1485518882345-15568b007407?w=900&h=1200&fit=crop&auto=format&q=85",
33
+ ],
34
+ },
35
+ {
36
+ drop: "Drop 03",
37
+ title: "Heavyweight, hand-screened.",
38
+ date: "Winter 2025",
39
+ byline: "Shot at the Tema dye works.",
40
+ hero: "https://images.unsplash.com/photo-1467043153537-a4fba2cd39ef?w=1800&h=1100&fit=crop&auto=format&q=85",
41
+ tiles: [
42
+ "https://images.unsplash.com/photo-1576566588028-4147f3842f27?w=900&h=1200&fit=crop&auto=format&q=85",
43
+ "https://images.unsplash.com/photo-1542838686-37da4a9fd1b3?w=900&h=1200&fit=crop&auto=format&q=85",
44
+ "https://images.unsplash.com/photo-1496747611176-843222e1e57c?w=900&h=1200&fit=crop&auto=format&q=85",
45
+ ],
46
+ },
47
+ {
48
+ drop: "Drop 02",
49
+ title: "From the studio floor.",
50
+ date: "Autumn 2025",
51
+ byline: "Studio days, Osu.",
52
+ hero: "https://images.unsplash.com/photo-1525507119028-ed4c629a60a3?w=1800&h=1100&fit=crop&auto=format&q=85",
53
+ tiles: [
54
+ "https://images.unsplash.com/photo-1512436991641-6745cdb1723f?w=900&h=1200&fit=crop&auto=format&q=85",
55
+ "https://images.unsplash.com/photo-1539109136881-3be0616acf4b?w=900&h=1200&fit=crop&auto=format&q=85",
56
+ "https://images.unsplash.com/photo-1490114538077-0a7f8cb49891?w=900&h=1200&fit=crop&auto=format&q=85",
57
+ ],
58
+ },
59
+ ];
60
+
61
+ export default function LookbookPage() {
62
+ return (
63
+ <article>
64
+ <section className="border-b border-border">
65
+ <div className="max-w-7xl mx-auto px-6 sm:px-10 py-14">
66
+ <p className="text-[11px] font-mono uppercase tracking-[0.2em] text-primary mb-3">
67
+ Lookbook
68
+ </p>
69
+ <h1 className="font-display text-[clamp(3rem,9vw,7rem)] uppercase mb-4 -tracking-[0.04em] leading-[0.92]">
70
+ The drops, in full.
71
+ </h1>
72
+ <p className="text-base text-muted-foreground max-w-2xl leading-relaxed">
73
+ Each drop is photographed in the room it's built in. Editorials below;
74
+ full collection in the shop.
75
+ </p>
76
+ </div>
77
+ </section>
78
+
79
+ {ENTRIES.map((entry, i) => (
80
+ <section key={entry.drop} className="border-b border-border">
81
+ <div className="max-w-7xl mx-auto px-6 sm:px-10 py-16">
82
+ <div className="flex items-end justify-between gap-6 mb-8">
83
+ <div>
84
+ <p className="text-[11px] font-mono uppercase tracking-[0.2em] text-muted-foreground mb-2">
85
+ {entry.drop} · {entry.date}
86
+ </p>
87
+ <h2 className="font-display text-[clamp(2rem,5vw,3.5rem)] uppercase m-0 -tracking-[0.04em] leading-[0.95]">
88
+ {entry.title}
89
+ </h2>
90
+ <p className="text-sm text-muted-foreground mt-2">{entry.byline}</p>
91
+ </div>
92
+ <Link
93
+ href="/shop"
94
+ className="hidden sm:inline-flex items-center gap-2 text-sm font-semibold uppercase tracking-wider text-foreground hover:text-primary transition-colors whitespace-nowrap"
95
+ >
96
+ Shop {entry.drop} →
97
+ </Link>
98
+ </div>
99
+
100
+ <div className="relative w-full aspect-[16/9] rounded-2xl overflow-hidden bg-muted mb-3">
101
+ <Image
102
+ src={entry.hero}
103
+ alt={`${entry.drop} hero — ${entry.title}`}
104
+ fill
105
+ sizes="(min-width: 1280px) 1280px, 100vw"
106
+ className="object-cover"
107
+ priority={i === 0}
108
+ />
109
+ </div>
110
+
111
+ <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
112
+ {entry.tiles.map((src, ti) => (
113
+ <div
114
+ key={src}
115
+ className="relative aspect-[3/4] rounded-2xl overflow-hidden bg-muted"
116
+ >
117
+ <Image
118
+ src={src}
119
+ alt={`${entry.drop} editorial ${ti + 1}`}
120
+ fill
121
+ sizes="(min-width: 768px) 33vw, 100vw"
122
+ className="object-cover"
123
+ />
124
+ </div>
125
+ ))}
126
+ </div>
127
+ </div>
128
+ </section>
129
+ ))}
130
+ </article>
131
+ );
132
+ }
@@ -0,0 +1,39 @@
1
+ import type { Metadata } from "next";
2
+ import Link from "next/link";
3
+ import { brand } from "@/lib/brand";
4
+
5
+ export const metadata: Metadata = {
6
+ title: `Page not found — ${brand.name}`,
7
+ description: "We couldn't find that page.",
8
+ };
9
+
10
+ export default function NotFound() {
11
+ return (
12
+ <section className="max-w-2xl mx-auto px-6 sm:px-8 py-20 text-center">
13
+ <p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary mb-3">
14
+ 404
15
+ </p>
16
+ <h1 className="text-[clamp(2.5rem,5vw,4rem)] font-bold mb-4 -tracking-[0.03em]">
17
+ Page not found.
18
+ </h1>
19
+ <p className="text-muted-foreground leading-relaxed mb-8">
20
+ The URL you followed might be old, a typo, or pointing at a product
21
+ that&apos;s no longer in stock. Try the menu or head back home.
22
+ </p>
23
+ <div className="flex flex-wrap items-center justify-center gap-3">
24
+ <Link
25
+ href="/shop"
26
+ className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md bg-primary text-primary-foreground font-semibold text-sm hover:bg-primary/90 transition-colors"
27
+ >
28
+ Browse the shop
29
+ </Link>
30
+ <Link
31
+ href="/"
32
+ className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md border border-border hover:bg-muted transition-colors text-sm font-medium"
33
+ >
34
+ Back home
35
+ </Link>
36
+ </div>
37
+ </section>
38
+ );
39
+ }
@@ -0,0 +1,37 @@
1
+ import { brand } from "@/lib/brand";
2
+
3
+ const SITE_URL =
4
+ process.env.NEXT_PUBLIC_SITE_URL?.trim() || "https://example.com";
5
+
6
+ /**
7
+ * OpenSearch description document — lets browsers add this site to the
8
+ * address bar's search engine list. When users press Tab after typing the
9
+ * domain, they get an inline search box that hits /search?q=...
10
+ */
11
+ export async function GET(): Promise<Response> {
12
+ const xml = `<?xml version="1.0" encoding="UTF-8"?>
13
+ <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
14
+ <ShortName>${escapeXml(brand.shortName)}</ShortName>
15
+ <Description>Search ${escapeXml(brand.name)}</Description>
16
+ <InputEncoding>UTF-8</InputEncoding>
17
+ <Url type="text/html" method="get" template="${SITE_URL}/search?q={searchTerms}" />
18
+ <Url type="application/opensearchdescription+xml" rel="self" template="${SITE_URL}/opensearch.xml" />
19
+ <moz:SearchForm>${SITE_URL}/search</moz:SearchForm>
20
+ </OpenSearchDescription>
21
+ `;
22
+ return new Response(xml, {
23
+ headers: {
24
+ "Content-Type": "application/opensearchdescription+xml; charset=utf-8",
25
+ "Cache-Control": "public, max-age=86400",
26
+ },
27
+ });
28
+ }
29
+
30
+ function escapeXml(s: string): string {
31
+ return s
32
+ .replace(/&/g, "&amp;")
33
+ .replace(/</g, "&lt;")
34
+ .replace(/>/g, "&gt;")
35
+ .replace(/"/g, "&quot;")
36
+ .replace(/'/g, "&apos;");
37
+ }
@@ -0,0 +1,24 @@
1
+ import Link from "next/link";
2
+
3
+ export default async function OrderPage({ params }: { params: Promise<{ id: string }> }) {
4
+ const { id } = await params;
5
+ return (
6
+ <section className="max-w-2xl mx-auto px-8 py-20 text-center">
7
+ <h1 className="text-3xl mt-0 mb-3 font-bold -tracking-[0.025em]">
8
+ Order confirmed.
9
+ </h1>
10
+ <p className="text-muted-foreground">
11
+ Order <code className="font-mono text-foreground">{id}</code> — you&apos;ll
12
+ get an SMS with tracking within 30 minutes.
13
+ </p>
14
+ <p className="mt-6">
15
+ <Link
16
+ href="/"
17
+ className="inline-block px-6 py-3 rounded-md bg-primary text-primary-foreground font-semibold text-sm transition-colors hover:bg-primary/90"
18
+ >
19
+ Continue shopping
20
+ </Link>
21
+ </p>
22
+ </section>
23
+ );
24
+ }
@@ -0,0 +1,183 @@
1
+ import type { Metadata } from "next";
2
+ import { Suspense } from "react";
3
+ import { cacheTag, cacheLife } from "next/cache";
4
+ import { getServerClient, tags, type Collection, type Product } from "@cimplify/sdk/server";
5
+ import { FeatureHero } from "@/components/feature-hero";
6
+ import { CategoryTiles } from "@/components/category-tiles";
7
+ import { CollectionStrip } from "@/components/collection-strip";
8
+ import { PromoBanner } from "@/components/promo-banner";
9
+ import { TrustBar } from "@/components/trust-bar";
10
+ import { BrandMarquee } from "@/components/brand-marquee";
11
+ import { TradeInCta } from "@/components/trade-in-cta";
12
+ import { Newsletter } from "@/components/newsletter";
13
+ import { SectionHeading } from "@/components/section-heading";
14
+ import { StoreProductCard } from "@/components/store-product-card";
15
+ import { brand } from "@/lib/brand";
16
+
17
+ export const metadata: Metadata = {
18
+ title: brand.hero.title,
19
+ description: brand.description,
20
+ };
21
+
22
+ interface CollectionWithProducts {
23
+ collection: Collection;
24
+ products: Product[];
25
+ }
26
+
27
+ async function getHomeData() {
28
+ "use cache";
29
+ cacheTag(tags.collections(), tags.categories(), tags.products());
30
+ cacheLife("hours");
31
+
32
+ const client = getServerClient();
33
+ const [colRes, catRes, productsRes] = await Promise.all([
34
+ client.catalogue.getCollections(),
35
+ client.catalogue.getCategories(),
36
+ client.catalogue.getProducts({ limit: 12 }),
37
+ ]);
38
+ const collections = colRes.ok ? colRes.value : [];
39
+ const categories = catRes.ok ? catRes.value : [];
40
+ const allProducts = productsRes.ok ? productsRes.value.items : [];
41
+
42
+ const collectionsWithProducts: CollectionWithProducts[] = await Promise.all(
43
+ collections.map(async (col) => {
44
+ const r = await client.catalogue.getCollectionProducts(col.id);
45
+ const items = r.ok
46
+ ? ((r.value as { items?: Product[] }).items ?? (r.value as Product[]))
47
+ : [];
48
+ return { collection: col, products: items };
49
+ }),
50
+ );
51
+
52
+ return {
53
+ collections: collectionsWithProducts.filter((x) => x.products.length > 0),
54
+ categories,
55
+ featured: allProducts.slice(0, 4),
56
+ newArrivals: allProducts.slice(4, 12),
57
+ };
58
+ }
59
+
60
+ // Verified-reachable Unsplash fashion editorial — replace with your own asset.
61
+ const HERO_FALLBACK_IMAGE =
62
+ "https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=2000&h=1400&fit=crop&auto=format&q=85";
63
+
64
+ export default async function HomePage() {
65
+ const { collections, categories, featured, newArrivals } = await getHomeData();
66
+ const heroProduct = featured[0];
67
+
68
+ return (
69
+ <>
70
+ <FeatureHero
71
+ eyebrow="Featured · in stock"
72
+ badge="Just landed"
73
+ title={brand.hero.title}
74
+ description={heroProduct?.description ?? brand.hero.subtitle}
75
+ primaryCta={{
76
+ label: heroProduct ? `Shop ${heroProduct.name}` : brand.hero.primaryCtaLabel,
77
+ href: heroProduct ? `/products/${heroProduct.slug ?? heroProduct.id}` : "/shop",
78
+ }}
79
+ secondaryCta={
80
+ brand.hero.secondaryCtaLabel && brand.hero.secondaryCtaHref
81
+ ? { label: brand.hero.secondaryCtaLabel, href: brand.hero.secondaryCtaHref }
82
+ : undefined
83
+ }
84
+ imageUrl={heroProduct?.image_url ?? heroProduct?.images?.[0] ?? HERO_FALLBACK_IMAGE}
85
+ imageAlt={heroProduct?.name ?? "Featured product"}
86
+ />
87
+
88
+ <TrustBar />
89
+
90
+ <Suspense fallback={<CategoryTilesSkeleton />}>
91
+ <CategoryTiles categories={categories} />
92
+ </Suspense>
93
+
94
+ <PromoBanner />
95
+
96
+ <section className="max-w-7xl mx-auto px-6 sm:px-8 py-14 sm:py-20">
97
+ <SectionHeading
98
+ eyebrow="Just dropped"
99
+ title="New this week."
100
+ description="Hand-picked launches and freshly restocked staples."
101
+ link={{ label: "Browse all", href: "/shop" }}
102
+ />
103
+ <Suspense fallback={<GridSkeleton count={4} />}>
104
+ <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3 sm:gap-4">
105
+ {newArrivals.slice(0, 4).map((p) => (
106
+ <StoreProductCard key={p.id} product={p} />
107
+ ))}
108
+ </div>
109
+ </Suspense>
110
+ </section>
111
+
112
+ <BrandMarquee />
113
+
114
+ {collections.map(({ collection, products }) => (
115
+ <Suspense
116
+ key={collection.id}
117
+ fallback={<StripSkeleton title={collection.name} />}
118
+ >
119
+ <CollectionStrip
120
+ collection={collection}
121
+ products={products}
122
+ collectionHref={`/collections/${collection.slug}`}
123
+ />
124
+ </Suspense>
125
+ ))}
126
+
127
+ <TradeInCta />
128
+
129
+ <section className="max-w-7xl mx-auto px-6 sm:px-8 py-14 sm:py-20">
130
+ <SectionHeading
131
+ eyebrow="Best sellers"
132
+ title="What everyone&apos;s buying."
133
+ link={{ label: "See more", href: "/shop" }}
134
+ />
135
+ <Suspense fallback={<GridSkeleton count={4} />}>
136
+ <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3 sm:gap-4">
137
+ {newArrivals.slice(4, 8).map((p) => (
138
+ <StoreProductCard key={p.id} product={p} />
139
+ ))}
140
+ </div>
141
+ </Suspense>
142
+ </section>
143
+
144
+ <Newsletter />
145
+ </>
146
+ );
147
+ }
148
+
149
+ function CategoryTilesSkeleton() {
150
+ return (
151
+ <section className="max-w-7xl mx-auto px-6 sm:px-8 py-14 sm:py-20">
152
+ <div className="h-8 w-64 bg-muted rounded mb-8 animate-pulse" />
153
+ <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4">
154
+ {Array.from({ length: 5 }).map((_, i) => (
155
+ <div key={i} className="h-40 bg-muted rounded-2xl animate-pulse" />
156
+ ))}
157
+ </div>
158
+ </section>
159
+ );
160
+ }
161
+
162
+ function GridSkeleton({ count }: { count: number }) {
163
+ return (
164
+ <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3 sm:gap-4">
165
+ {Array.from({ length: count }).map((_, i) => (
166
+ <div key={i} className="aspect-[4/3] bg-muted rounded-2xl animate-pulse" />
167
+ ))}
168
+ </div>
169
+ );
170
+ }
171
+
172
+ function StripSkeleton({ title }: { title: string }) {
173
+ return (
174
+ <section className="max-w-7xl mx-auto px-6 sm:px-8 py-12">
175
+ <h2 className="text-[26px] font-semibold m-0 mb-5 -tracking-[0.02em]">{title}</h2>
176
+ <div className="grid grid-flow-col auto-cols-[minmax(220px,1fr)] gap-4 overflow-x-auto pb-2">
177
+ {Array.from({ length: 5 }).map((_, i) => (
178
+ <div key={i} className="aspect-square bg-muted rounded-2xl animate-pulse" />
179
+ ))}
180
+ </div>
181
+ </section>
182
+ );
183
+ }
@@ -0,0 +1,44 @@
1
+ import type { Metadata } from "next";
2
+ import { brand } from "@/lib/brand";
3
+
4
+ export const metadata: Metadata = {
5
+ title: `Privacy Policy — ${brand.name}`,
6
+ description: `How ${brand.name} collects, uses, and protects your personal data.`,
7
+ };
8
+
9
+ export default function PrivacyPage() {
10
+ const p = brand.privacy;
11
+ return (
12
+ <article className="max-w-3xl mx-auto px-8 py-16 prose prose-lg max-w-none">
13
+ <p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary mb-2 not-prose">
14
+ {p.eyebrow}
15
+ </p>
16
+ <h1 className="text-[clamp(2.25rem,5vw,3.5rem)] font-bold mb-2 -tracking-[0.025em]">
17
+ {p.title}
18
+ </h1>
19
+ <p className="text-sm text-muted-foreground not-prose mb-10">
20
+ Last updated: {p.lastUpdated}
21
+ </p>
22
+
23
+ <section className="space-y-5 leading-relaxed text-foreground/90">
24
+ {p.sections.map((s) => (
25
+ <div key={s.heading}>
26
+ <h2 className="text-2xl font-semibold mt-0 -tracking-[0.02em]">{s.heading}</h2>
27
+ {typeof s.body === "string" ? (
28
+ <p>{s.body}</p>
29
+ ) : (
30
+ <>
31
+ <p>{s.body.intro}</p>
32
+ <ul className="list-disc pl-6 space-y-2">
33
+ {s.body.bullets.map((b) => (
34
+ <li key={b}>{b}</li>
35
+ ))}
36
+ </ul>
37
+ </>
38
+ )}
39
+ </div>
40
+ ))}
41
+ </section>
42
+ </article>
43
+ );
44
+ }