@cimplify/sdk 0.40.1 → 0.42.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 (352) hide show
  1. package/dist/cli/commands/deploy.mjs +561 -0
  2. package/dist/cli/commands/dev.mjs +434 -0
  3. package/dist/cli/commands/domains.mjs +479 -0
  4. package/dist/cli/commands/env.mjs +610 -0
  5. package/dist/cli/commands/link.mjs +325 -0
  6. package/dist/cli/commands/login.mjs +515 -0
  7. package/dist/cli/commands/logout.mjs +54 -0
  8. package/dist/cli/commands/logs.mjs +358 -0
  9. package/dist/cli/commands/projects.mjs +327 -0
  10. package/dist/cli/commands/rollback.mjs +477 -0
  11. package/dist/cli/commands/status.mjs +380 -0
  12. package/dist/cli/commands/unlink.mjs +58 -0
  13. package/dist/cli/commands/whoami.mjs +234 -0
  14. package/dist/dispatcher.mjs +94 -2
  15. package/dist/styles.css +1 -1
  16. package/package.json +1 -1
  17. package/templates/storefront-bakery/.env.example +5 -0
  18. package/templates/storefront-bakery/AGENTS.md +57 -0
  19. package/templates/storefront-bakery/app/about/page.tsx +21 -44
  20. package/templates/storefront-bakery/app/accessibility/page.tsx +11 -0
  21. package/templates/storefront-bakery/app/account/addresses/page.tsx +21 -0
  22. package/templates/storefront-bakery/app/account/orders/page.tsx +21 -0
  23. package/templates/storefront-bakery/app/account/page.tsx +22 -0
  24. package/templates/storefront-bakery/app/account/settings/page.tsx +21 -0
  25. package/templates/storefront-bakery/app/categories/[slug]/page.tsx +2 -1
  26. package/templates/storefront-bakery/app/collections/[slug]/page.tsx +2 -1
  27. package/templates/storefront-bakery/app/contact/contact-form.tsx +109 -0
  28. package/templates/storefront-bakery/app/contact/page.tsx +54 -0
  29. package/templates/storefront-bakery/app/error.tsx +60 -0
  30. package/templates/storefront-bakery/app/faq/page.tsx +13 -89
  31. package/templates/storefront-bakery/app/layout.tsx +37 -2
  32. package/templates/storefront-bakery/app/llms.txt/route.ts +94 -0
  33. package/templates/storefront-bakery/app/login/page.tsx +17 -0
  34. package/templates/storefront-bakery/app/not-found.tsx +39 -0
  35. package/templates/storefront-bakery/app/opensearch.xml/route.ts +37 -0
  36. package/templates/storefront-bakery/app/page.tsx +6 -6
  37. package/templates/storefront-bakery/app/privacy/page.tsx +24 -68
  38. package/templates/storefront-bakery/app/returns/page.tsx +11 -0
  39. package/templates/storefront-bakery/app/robots.ts +18 -0
  40. package/templates/storefront-bakery/app/search/page.tsx +38 -0
  41. package/templates/storefront-bakery/app/search/search-client.tsx +7 -0
  42. package/templates/storefront-bakery/app/shipping/page.tsx +16 -0
  43. package/templates/storefront-bakery/app/shop/page.tsx +3 -2
  44. package/templates/storefront-bakery/app/signup/page.tsx +17 -0
  45. package/templates/storefront-bakery/app/sitemap-page/page.tsx +167 -0
  46. package/templates/storefront-bakery/app/sitemap.ts +62 -0
  47. package/templates/storefront-bakery/app/terms/page.tsx +24 -82
  48. package/templates/storefront-bakery/app/track-order/page.tsx +24 -0
  49. package/templates/storefront-bakery/app/track-order/track-order-form.tsx +69 -0
  50. package/templates/storefront-bakery/components/account-iframe.tsx +13 -0
  51. package/templates/storefront-bakery/components/footer.tsx +88 -130
  52. package/templates/storefront-bakery/components/header.tsx +8 -16
  53. package/templates/storefront-bakery/components/policy-page.tsx +49 -0
  54. package/templates/storefront-bakery/lib/brand.ts +568 -0
  55. package/templates/storefront-fashion/.env.example +16 -0
  56. package/templates/storefront-fashion/AGENTS.md +52 -0
  57. package/templates/storefront-fashion/README.md +77 -0
  58. package/templates/storefront-fashion/app/about/page.tsx +41 -0
  59. package/templates/storefront-fashion/app/accessibility/page.tsx +11 -0
  60. package/templates/storefront-fashion/app/account/addresses/page.tsx +21 -0
  61. package/templates/storefront-fashion/app/account/orders/page.tsx +21 -0
  62. package/templates/storefront-fashion/app/account/page.tsx +22 -0
  63. package/templates/storefront-fashion/app/account/settings/page.tsx +21 -0
  64. package/templates/storefront-fashion/app/cart/page.tsx +9 -0
  65. package/templates/storefront-fashion/app/categories/[slug]/listing-client.tsx +19 -0
  66. package/templates/storefront-fashion/app/categories/[slug]/page.tsx +130 -0
  67. package/templates/storefront-fashion/app/checkout/page.tsx +17 -0
  68. package/templates/storefront-fashion/app/collections/[slug]/listing-client.tsx +20 -0
  69. package/templates/storefront-fashion/app/collections/[slug]/page.tsx +130 -0
  70. package/templates/storefront-fashion/app/contact/contact-form.tsx +109 -0
  71. package/templates/storefront-fashion/app/contact/page.tsx +54 -0
  72. package/templates/storefront-fashion/app/error.tsx +61 -0
  73. package/templates/storefront-fashion/app/faq/page.tsx +46 -0
  74. package/templates/storefront-fashion/app/globals.css +46 -0
  75. package/templates/storefront-fashion/app/layout.tsx +76 -0
  76. package/templates/storefront-fashion/app/llms.txt/route.ts +94 -0
  77. package/templates/storefront-fashion/app/login/page.tsx +17 -0
  78. package/templates/storefront-fashion/app/lookbook/page.tsx +132 -0
  79. package/templates/storefront-fashion/app/not-found.tsx +39 -0
  80. package/templates/storefront-fashion/app/opensearch.xml/route.ts +37 -0
  81. package/templates/storefront-fashion/app/orders/[id]/page.tsx +24 -0
  82. package/templates/storefront-fashion/app/page.tsx +183 -0
  83. package/templates/storefront-fashion/app/privacy/page.tsx +44 -0
  84. package/templates/storefront-fashion/app/products/[slug]/page.tsx +165 -0
  85. package/templates/storefront-fashion/app/products/[slug]/product-detail.tsx +71 -0
  86. package/templates/storefront-fashion/app/returns/page.tsx +11 -0
  87. package/templates/storefront-fashion/app/robots.ts +18 -0
  88. package/templates/storefront-fashion/app/search/page.tsx +38 -0
  89. package/templates/storefront-fashion/app/search/search-client.tsx +7 -0
  90. package/templates/storefront-fashion/app/shipping/page.tsx +16 -0
  91. package/templates/storefront-fashion/app/shop/page.tsx +63 -0
  92. package/templates/storefront-fashion/app/shop/shop-client.tsx +32 -0
  93. package/templates/storefront-fashion/app/signup/page.tsx +17 -0
  94. package/templates/storefront-fashion/app/sitemap-page/page.tsx +167 -0
  95. package/templates/storefront-fashion/app/sitemap.ts +59 -0
  96. package/templates/storefront-fashion/app/size-guide/page.tsx +155 -0
  97. package/templates/storefront-fashion/app/terms/page.tsx +44 -0
  98. package/templates/storefront-fashion/app/track-order/page.tsx +24 -0
  99. package/templates/storefront-fashion/app/track-order/track-order-form.tsx +69 -0
  100. package/templates/storefront-fashion/components/account-iframe.tsx +13 -0
  101. package/templates/storefront-fashion/components/brand-marquee.tsx +27 -0
  102. package/templates/storefront-fashion/components/cart-pill.tsx +32 -0
  103. package/templates/storefront-fashion/components/category-grid.tsx +28 -0
  104. package/templates/storefront-fashion/components/category-tiles.tsx +104 -0
  105. package/templates/storefront-fashion/components/collection-strip.tsx +45 -0
  106. package/templates/storefront-fashion/components/feature-hero.tsx +82 -0
  107. package/templates/storefront-fashion/components/footer.tsx +153 -0
  108. package/templates/storefront-fashion/components/header.tsx +43 -0
  109. package/templates/storefront-fashion/components/hero.tsx +28 -0
  110. package/templates/storefront-fashion/components/nav-link.tsx +20 -0
  111. package/templates/storefront-fashion/components/newsletter.tsx +50 -0
  112. package/templates/storefront-fashion/components/policy-page.tsx +49 -0
  113. package/templates/storefront-fashion/components/promo-banner.tsx +41 -0
  114. package/templates/storefront-fashion/components/providers.tsx +31 -0
  115. package/templates/storefront-fashion/components/section-heading.tsx +37 -0
  116. package/templates/storefront-fashion/components/store-product-card.tsx +83 -0
  117. package/templates/storefront-fashion/components/trade-in-cta.tsx +54 -0
  118. package/templates/storefront-fashion/components/trust-bar.tsx +66 -0
  119. package/templates/storefront-fashion/lib/brand.ts +516 -0
  120. package/templates/storefront-fashion/lib/cart.ts +27 -0
  121. package/templates/storefront-fashion/next.config.ts +40 -0
  122. package/templates/storefront-fashion/package.json +28 -0
  123. package/templates/storefront-fashion/postcss.config.mjs +7 -0
  124. package/templates/storefront-fashion/tsconfig.json +23 -0
  125. package/templates/storefront-grocery/.env.example +16 -0
  126. package/templates/storefront-grocery/AGENTS.md +39 -0
  127. package/templates/storefront-grocery/README.md +73 -0
  128. package/templates/storefront-grocery/app/about/page.tsx +38 -0
  129. package/templates/storefront-grocery/app/accessibility/page.tsx +11 -0
  130. package/templates/storefront-grocery/app/account/addresses/page.tsx +21 -0
  131. package/templates/storefront-grocery/app/account/orders/page.tsx +21 -0
  132. package/templates/storefront-grocery/app/account/page.tsx +22 -0
  133. package/templates/storefront-grocery/app/account/settings/page.tsx +21 -0
  134. package/templates/storefront-grocery/app/cart/page.tsx +9 -0
  135. package/templates/storefront-grocery/app/categories/[slug]/listing-client.tsx +19 -0
  136. package/templates/storefront-grocery/app/categories/[slug]/page.tsx +118 -0
  137. package/templates/storefront-grocery/app/checkout/page.tsx +17 -0
  138. package/templates/storefront-grocery/app/collections/[slug]/listing-client.tsx +20 -0
  139. package/templates/storefront-grocery/app/collections/[slug]/page.tsx +118 -0
  140. package/templates/storefront-grocery/app/contact/contact-form.tsx +109 -0
  141. package/templates/storefront-grocery/app/contact/page.tsx +54 -0
  142. package/templates/storefront-grocery/app/error.tsx +60 -0
  143. package/templates/storefront-grocery/app/faq/page.tsx +46 -0
  144. package/templates/storefront-grocery/app/globals.css +45 -0
  145. package/templates/storefront-grocery/app/layout.tsx +75 -0
  146. package/templates/storefront-grocery/app/llms.txt/route.ts +94 -0
  147. package/templates/storefront-grocery/app/login/page.tsx +17 -0
  148. package/templates/storefront-grocery/app/not-found.tsx +39 -0
  149. package/templates/storefront-grocery/app/opensearch.xml/route.ts +37 -0
  150. package/templates/storefront-grocery/app/orders/[id]/page.tsx +21 -0
  151. package/templates/storefront-grocery/app/page.tsx +97 -0
  152. package/templates/storefront-grocery/app/privacy/page.tsx +44 -0
  153. package/templates/storefront-grocery/app/returns/page.tsx +11 -0
  154. package/templates/storefront-grocery/app/robots.ts +18 -0
  155. package/templates/storefront-grocery/app/search/page.tsx +38 -0
  156. package/templates/storefront-grocery/app/search/search-client.tsx +7 -0
  157. package/templates/storefront-grocery/app/shipping/page.tsx +16 -0
  158. package/templates/storefront-grocery/app/shop/page.tsx +31 -0
  159. package/templates/storefront-grocery/app/shop/shop-client.tsx +27 -0
  160. package/templates/storefront-grocery/app/signup/page.tsx +17 -0
  161. package/templates/storefront-grocery/app/sitemap-page/page.tsx +167 -0
  162. package/templates/storefront-grocery/app/sitemap.ts +62 -0
  163. package/templates/storefront-grocery/app/terms/page.tsx +44 -0
  164. package/templates/storefront-grocery/app/track-order/page.tsx +24 -0
  165. package/templates/storefront-grocery/app/track-order/track-order-form.tsx +69 -0
  166. package/templates/storefront-grocery/components/account-iframe.tsx +13 -0
  167. package/templates/storefront-grocery/components/cart-pill.tsx +32 -0
  168. package/templates/storefront-grocery/components/category-grid.tsx +28 -0
  169. package/templates/storefront-grocery/components/collection-strip.tsx +45 -0
  170. package/templates/storefront-grocery/components/footer.tsx +148 -0
  171. package/templates/storefront-grocery/components/header.tsx +43 -0
  172. package/templates/storefront-grocery/components/hero.tsx +25 -0
  173. package/templates/storefront-grocery/components/nav-link.tsx +20 -0
  174. package/templates/storefront-grocery/components/policy-page.tsx +49 -0
  175. package/templates/storefront-grocery/components/providers.tsx +31 -0
  176. package/templates/storefront-grocery/components/store-product-card.tsx +83 -0
  177. package/templates/storefront-grocery/lib/brand.ts +373 -0
  178. package/templates/storefront-grocery/lib/cart.ts +27 -0
  179. package/templates/storefront-grocery/next.config.ts +40 -0
  180. package/templates/storefront-grocery/package.json +28 -0
  181. package/templates/storefront-grocery/postcss.config.mjs +7 -0
  182. package/templates/storefront-grocery/tsconfig.json +23 -0
  183. package/templates/storefront-restaurant/.env.example +16 -0
  184. package/templates/storefront-restaurant/AGENTS.md +39 -0
  185. package/templates/storefront-restaurant/README.md +73 -0
  186. package/templates/storefront-restaurant/app/about/page.tsx +38 -0
  187. package/templates/storefront-restaurant/app/accessibility/page.tsx +11 -0
  188. package/templates/storefront-restaurant/app/account/addresses/page.tsx +21 -0
  189. package/templates/storefront-restaurant/app/account/orders/page.tsx +21 -0
  190. package/templates/storefront-restaurant/app/account/page.tsx +22 -0
  191. package/templates/storefront-restaurant/app/account/settings/page.tsx +21 -0
  192. package/templates/storefront-restaurant/app/cart/page.tsx +9 -0
  193. package/templates/storefront-restaurant/app/categories/[slug]/listing-client.tsx +19 -0
  194. package/templates/storefront-restaurant/app/categories/[slug]/page.tsx +118 -0
  195. package/templates/storefront-restaurant/app/checkout/page.tsx +17 -0
  196. package/templates/storefront-restaurant/app/collections/[slug]/listing-client.tsx +20 -0
  197. package/templates/storefront-restaurant/app/collections/[slug]/page.tsx +118 -0
  198. package/templates/storefront-restaurant/app/contact/contact-form.tsx +109 -0
  199. package/templates/storefront-restaurant/app/contact/page.tsx +54 -0
  200. package/templates/storefront-restaurant/app/error.tsx +60 -0
  201. package/templates/storefront-restaurant/app/faq/page.tsx +46 -0
  202. package/templates/storefront-restaurant/app/globals.css +44 -0
  203. package/templates/storefront-restaurant/app/layout.tsx +80 -0
  204. package/templates/storefront-restaurant/app/llms.txt/route.ts +94 -0
  205. package/templates/storefront-restaurant/app/login/page.tsx +17 -0
  206. package/templates/storefront-restaurant/app/not-found.tsx +39 -0
  207. package/templates/storefront-restaurant/app/opensearch.xml/route.ts +37 -0
  208. package/templates/storefront-restaurant/app/orders/[id]/page.tsx +21 -0
  209. package/templates/storefront-restaurant/app/page.tsx +97 -0
  210. package/templates/storefront-restaurant/app/privacy/page.tsx +44 -0
  211. package/templates/storefront-restaurant/app/reservations/page.tsx +66 -0
  212. package/templates/storefront-restaurant/app/reservations/reservations-client.tsx +234 -0
  213. package/templates/storefront-restaurant/app/returns/page.tsx +11 -0
  214. package/templates/storefront-restaurant/app/robots.ts +18 -0
  215. package/templates/storefront-restaurant/app/search/page.tsx +38 -0
  216. package/templates/storefront-restaurant/app/search/search-client.tsx +7 -0
  217. package/templates/storefront-restaurant/app/shipping/page.tsx +16 -0
  218. package/templates/storefront-restaurant/app/shop/page.tsx +31 -0
  219. package/templates/storefront-restaurant/app/shop/shop-client.tsx +27 -0
  220. package/templates/storefront-restaurant/app/signup/page.tsx +17 -0
  221. package/templates/storefront-restaurant/app/sitemap-page/page.tsx +167 -0
  222. package/templates/storefront-restaurant/app/sitemap.ts +62 -0
  223. package/templates/storefront-restaurant/app/terms/page.tsx +44 -0
  224. package/templates/storefront-restaurant/app/track-order/page.tsx +24 -0
  225. package/templates/storefront-restaurant/app/track-order/track-order-form.tsx +69 -0
  226. package/templates/storefront-restaurant/components/account-iframe.tsx +13 -0
  227. package/templates/storefront-restaurant/components/cart-pill.tsx +32 -0
  228. package/templates/storefront-restaurant/components/category-grid.tsx +28 -0
  229. package/templates/storefront-restaurant/components/collection-strip.tsx +45 -0
  230. package/templates/storefront-restaurant/components/footer.tsx +148 -0
  231. package/templates/storefront-restaurant/components/header.tsx +43 -0
  232. package/templates/storefront-restaurant/components/hero.tsx +25 -0
  233. package/templates/storefront-restaurant/components/nav-link.tsx +20 -0
  234. package/templates/storefront-restaurant/components/policy-page.tsx +49 -0
  235. package/templates/storefront-restaurant/components/product-modal.tsx +105 -0
  236. package/templates/storefront-restaurant/components/providers.tsx +31 -0
  237. package/templates/storefront-restaurant/components/store-product-card.tsx +83 -0
  238. package/templates/storefront-restaurant/lib/brand.ts +375 -0
  239. package/templates/storefront-restaurant/lib/cart.ts +27 -0
  240. package/templates/storefront-restaurant/next.config.ts +40 -0
  241. package/templates/storefront-restaurant/package.json +28 -0
  242. package/templates/storefront-restaurant/postcss.config.mjs +7 -0
  243. package/templates/storefront-restaurant/tsconfig.json +23 -0
  244. package/templates/storefront-retail/.env.example +5 -0
  245. package/templates/storefront-retail/AGENTS.md +64 -0
  246. package/templates/storefront-retail/app/about/page.tsx +24 -54
  247. package/templates/storefront-retail/app/accessibility/page.tsx +11 -0
  248. package/templates/storefront-retail/app/account/addresses/page.tsx +21 -0
  249. package/templates/storefront-retail/app/account/orders/page.tsx +21 -0
  250. package/templates/storefront-retail/app/account/page.tsx +22 -0
  251. package/templates/storefront-retail/app/account/settings/page.tsx +21 -0
  252. package/templates/storefront-retail/app/categories/[slug]/page.tsx +2 -1
  253. package/templates/storefront-retail/app/collections/[slug]/page.tsx +2 -1
  254. package/templates/storefront-retail/app/contact/contact-form.tsx +109 -0
  255. package/templates/storefront-retail/app/contact/page.tsx +54 -0
  256. package/templates/storefront-retail/app/error.tsx +61 -0
  257. package/templates/storefront-retail/app/faq/page.tsx +11 -92
  258. package/templates/storefront-retail/app/layout.tsx +37 -8
  259. package/templates/storefront-retail/app/llms.txt/route.ts +94 -0
  260. package/templates/storefront-retail/app/login/page.tsx +17 -0
  261. package/templates/storefront-retail/app/not-found.tsx +39 -0
  262. package/templates/storefront-retail/app/opensearch.xml/route.ts +37 -0
  263. package/templates/storefront-retail/app/page.tsx +16 -73
  264. package/templates/storefront-retail/app/privacy/page.tsx +24 -81
  265. package/templates/storefront-retail/app/products/[slug]/page.tsx +165 -0
  266. package/templates/storefront-retail/app/products/[slug]/product-detail.tsx +71 -0
  267. package/templates/storefront-retail/app/returns/page.tsx +11 -0
  268. package/templates/storefront-retail/app/robots.ts +18 -0
  269. package/templates/storefront-retail/app/search/page.tsx +38 -0
  270. package/templates/storefront-retail/app/search/search-client.tsx +7 -0
  271. package/templates/storefront-retail/app/shipping/page.tsx +16 -0
  272. package/templates/storefront-retail/app/shop/page.tsx +3 -3
  273. package/templates/storefront-retail/app/signup/page.tsx +17 -0
  274. package/templates/storefront-retail/app/sitemap-page/page.tsx +167 -0
  275. package/templates/storefront-retail/app/sitemap.ts +59 -0
  276. package/templates/storefront-retail/app/terms/page.tsx +24 -97
  277. package/templates/storefront-retail/app/track-order/page.tsx +24 -0
  278. package/templates/storefront-retail/app/track-order/track-order-form.tsx +69 -0
  279. package/templates/storefront-retail/components/account-iframe.tsx +13 -0
  280. package/templates/storefront-retail/components/brand-marquee.tsx +6 -15
  281. package/templates/storefront-retail/components/feature-hero.tsx +2 -1
  282. package/templates/storefront-retail/components/footer.tsx +85 -120
  283. package/templates/storefront-retail/components/header.tsx +10 -12
  284. package/templates/storefront-retail/components/newsletter.tsx +7 -9
  285. package/templates/storefront-retail/components/policy-page.tsx +49 -0
  286. package/templates/storefront-retail/components/promo-banner.tsx +12 -15
  287. package/templates/storefront-retail/components/store-product-card.tsx +7 -7
  288. package/templates/storefront-retail/components/trade-in-cta.tsx +11 -17
  289. package/templates/storefront-retail/components/trust-bar.tsx +45 -5
  290. package/templates/storefront-retail/lib/brand.ts +663 -0
  291. package/templates/storefront-services/.env.example +16 -0
  292. package/templates/storefront-services/AGENTS.md +41 -0
  293. package/templates/storefront-services/README.md +73 -0
  294. package/templates/storefront-services/app/about/page.tsx +38 -0
  295. package/templates/storefront-services/app/accessibility/page.tsx +11 -0
  296. package/templates/storefront-services/app/account/addresses/page.tsx +21 -0
  297. package/templates/storefront-services/app/account/orders/page.tsx +21 -0
  298. package/templates/storefront-services/app/account/page.tsx +22 -0
  299. package/templates/storefront-services/app/account/settings/page.tsx +21 -0
  300. package/templates/storefront-services/app/book/book-client.tsx +195 -0
  301. package/templates/storefront-services/app/book/page.tsx +65 -0
  302. package/templates/storefront-services/app/cart/page.tsx +9 -0
  303. package/templates/storefront-services/app/categories/[slug]/listing-client.tsx +19 -0
  304. package/templates/storefront-services/app/categories/[slug]/page.tsx +118 -0
  305. package/templates/storefront-services/app/checkout/page.tsx +17 -0
  306. package/templates/storefront-services/app/collections/[slug]/listing-client.tsx +20 -0
  307. package/templates/storefront-services/app/collections/[slug]/page.tsx +118 -0
  308. package/templates/storefront-services/app/contact/contact-form.tsx +109 -0
  309. package/templates/storefront-services/app/contact/page.tsx +54 -0
  310. package/templates/storefront-services/app/error.tsx +60 -0
  311. package/templates/storefront-services/app/faq/page.tsx +46 -0
  312. package/templates/storefront-services/app/globals.css +45 -0
  313. package/templates/storefront-services/app/layout.tsx +80 -0
  314. package/templates/storefront-services/app/llms.txt/route.ts +94 -0
  315. package/templates/storefront-services/app/login/page.tsx +17 -0
  316. package/templates/storefront-services/app/not-found.tsx +39 -0
  317. package/templates/storefront-services/app/opensearch.xml/route.ts +37 -0
  318. package/templates/storefront-services/app/orders/[id]/page.tsx +21 -0
  319. package/templates/storefront-services/app/page.tsx +97 -0
  320. package/templates/storefront-services/app/privacy/page.tsx +44 -0
  321. package/templates/storefront-services/app/returns/page.tsx +11 -0
  322. package/templates/storefront-services/app/robots.ts +18 -0
  323. package/templates/storefront-services/app/search/page.tsx +38 -0
  324. package/templates/storefront-services/app/search/search-client.tsx +7 -0
  325. package/templates/storefront-services/app/shipping/page.tsx +16 -0
  326. package/templates/storefront-services/app/shop/page.tsx +31 -0
  327. package/templates/storefront-services/app/shop/shop-client.tsx +27 -0
  328. package/templates/storefront-services/app/signup/page.tsx +17 -0
  329. package/templates/storefront-services/app/sitemap-page/page.tsx +167 -0
  330. package/templates/storefront-services/app/sitemap.ts +62 -0
  331. package/templates/storefront-services/app/terms/page.tsx +44 -0
  332. package/templates/storefront-services/app/track-order/page.tsx +24 -0
  333. package/templates/storefront-services/app/track-order/track-order-form.tsx +69 -0
  334. package/templates/storefront-services/components/account-iframe.tsx +13 -0
  335. package/templates/storefront-services/components/cart-pill.tsx +32 -0
  336. package/templates/storefront-services/components/category-grid.tsx +28 -0
  337. package/templates/storefront-services/components/collection-strip.tsx +45 -0
  338. package/templates/storefront-services/components/footer.tsx +148 -0
  339. package/templates/storefront-services/components/header.tsx +43 -0
  340. package/templates/storefront-services/components/hero.tsx +25 -0
  341. package/templates/storefront-services/components/nav-link.tsx +20 -0
  342. package/templates/storefront-services/components/policy-page.tsx +49 -0
  343. package/templates/storefront-services/components/product-modal.tsx +105 -0
  344. package/templates/storefront-services/components/providers.tsx +31 -0
  345. package/templates/storefront-services/components/store-product-card.tsx +83 -0
  346. package/templates/storefront-services/lib/brand.ts +394 -0
  347. package/templates/storefront-services/lib/cart.ts +27 -0
  348. package/templates/storefront-services/next.config.ts +40 -0
  349. package/templates/storefront-services/package.json +28 -0
  350. package/templates/storefront-services/postcss.config.mjs +7 -0
  351. package/templates/storefront-services/tsconfig.json +23 -0
  352. /package/templates/{storefront-retail → storefront-grocery}/components/product-modal.tsx +0 -0
@@ -0,0 +1,69 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { useRouter } from "next/navigation";
5
+
6
+ /**
7
+ * Guest order tracker. Routes /orders/<id> with the entered id; the
8
+ * post-checkout confirmation page already lives at /orders/[id] so this
9
+ * just sends the visitor there. Replace the redirect with a real lookup
10
+ * (e.g. Cimplify orders API + email-match guard) for production.
11
+ */
12
+ export function TrackOrderForm() {
13
+ const router = useRouter();
14
+ const [orderId, setOrderId] = useState("");
15
+ const [email, setEmail] = useState("");
16
+
17
+ return (
18
+ <form
19
+ onSubmit={(e) => {
20
+ e.preventDefault();
21
+ if (!orderId.trim()) return;
22
+ router.push(`/orders/${encodeURIComponent(orderId.trim())}`);
23
+ }}
24
+ className="space-y-4 rounded-2xl border border-border bg-card p-6"
25
+ >
26
+ <div>
27
+ <label
28
+ htmlFor="orderId"
29
+ className="text-xs font-semibold uppercase tracking-wider text-muted-foreground block mb-1.5"
30
+ >
31
+ Order number
32
+ </label>
33
+ <input
34
+ id="orderId"
35
+ name="orderId"
36
+ required
37
+ value={orderId}
38
+ onChange={(e) => setOrderId(e.target.value)}
39
+ placeholder="ord_abc123…"
40
+ className="w-full px-4 py-3 rounded-md bg-background border border-border focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none text-sm"
41
+ />
42
+ </div>
43
+ <div>
44
+ <label
45
+ htmlFor="email"
46
+ className="text-xs font-semibold uppercase tracking-wider text-muted-foreground block mb-1.5"
47
+ >
48
+ Order email
49
+ </label>
50
+ <input
51
+ id="email"
52
+ name="email"
53
+ type="email"
54
+ required
55
+ value={email}
56
+ onChange={(e) => setEmail(e.target.value)}
57
+ placeholder="you@email.com"
58
+ className="w-full px-4 py-3 rounded-md bg-background border border-border focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none text-sm"
59
+ />
60
+ </div>
61
+ <button
62
+ type="submit"
63
+ className="w-full inline-flex items-center justify-center px-5 py-3 rounded-md bg-primary text-primary-foreground font-semibold text-sm hover:bg-primary/90 transition-colors"
64
+ >
65
+ Track order
66
+ </button>
67
+ </form>
68
+ );
69
+ }
@@ -0,0 +1,13 @@
1
+ "use client";
2
+
3
+ import { CimplifyAccount } from "@cimplify/sdk/react";
4
+
5
+ /**
6
+ * Cimplify Account portal — iframe-mounted UI hosted by Cimplify Link.
7
+ * Handles sign-in, sign-up, OTP, addresses, payment methods, sessions,
8
+ * and order history. The iframe owns auth state; we just choose which
9
+ * `section` to land on.
10
+ */
11
+ export function AccountIframe({ section }: { section?: string }) {
12
+ return <CimplifyAccount section={section} />;
13
+ }
@@ -1,127 +1,84 @@
1
1
  import Link from "next/link";
2
+ import { brand } from "@/lib/brand";
2
3
 
3
- const SOCIALS: { label: string; href: string; svg: React.ReactNode }[] = [
4
- {
5
- label: "Instagram",
6
- href: "https://instagram.com/akuasbakery",
7
- svg: (
8
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden className="w-5 h-5">
9
- <rect x="3" y="3" width="18" height="18" rx="5" />
10
- <circle cx="12" cy="12" r="4" />
11
- <circle cx="17.5" cy="6.5" r="0.75" fill="currentColor" />
12
- </svg>
13
- ),
14
- },
15
- {
16
- label: "TikTok",
17
- href: "https://tiktok.com/@akuasbakery",
18
- svg: (
19
- <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
20
- <path d="M16 3v3.5a4.5 4.5 0 0 0 4.5 4.5V14a7.5 7.5 0 0 1-4.5-1.5V16a5 5 0 1 1-5-5v3a2 2 0 1 0 2 2V3z" />
21
- </svg>
22
- ),
23
- },
24
- {
25
- label: "X",
26
- href: "https://x.com/akuasbakery",
27
- svg: (
28
- <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
29
- <path d="M18 2h3l-7.5 8.6L22 22h-6.6l-5-6.5L4 22H1l8-9.2L1.4 2H8l4.6 6 5.4-6z" />
30
- </svg>
31
- ),
32
- },
33
- {
34
- label: "Facebook",
35
- href: "https://facebook.com/akuasbakery",
36
- svg: (
37
- <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
38
- <path d="M14 9V7a1 1 0 0 1 1-1h2V3h-3a4 4 0 0 0-4 4v2H8v3h2v9h3v-9h2.5l.5-3H13z" />
39
- </svg>
40
- ),
41
- },
42
- {
43
- label: "WhatsApp",
44
- href: "https://wa.me/233244000000",
45
- svg: (
46
- <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
47
- <path d="M12 2a10 10 0 0 0-8.6 15l-1.4 5 5.2-1.4A10 10 0 1 0 12 2zm5 14.2c-.2.6-1.2 1.2-1.7 1.2-.5.1-1.1.1-1.7-.1-.4-.1-.9-.3-1.5-.6a8.4 8.4 0 0 1-3.7-3.4c-.7-1-1-1.8-1-2.5 0-.7.4-1.1.6-1.3.2-.2.4-.2.5-.2h.4c.1 0 .3 0 .4.3l.6 1.4c.1.2 0 .3 0 .4l-.3.4-.3.3c-.1.1-.2.2-.1.4.2.4.7 1.1 1.4 1.8.9.8 1.7 1.1 1.9 1.2.2.1.3.1.5-.1l.6-.7c.2-.2.3-.2.5-.1l1.4.7c.2.1.3.2.4.3.1.2.1.6 0 1z" />
48
- </svg>
49
- ),
50
- },
51
- ];
4
+ const ICONS: Record<string, React.ReactNode> = {
5
+ instagram: (
6
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden className="w-5 h-5">
7
+ <rect x="3" y="3" width="18" height="18" rx="5" />
8
+ <circle cx="12" cy="12" r="4" />
9
+ <circle cx="17.5" cy="6.5" r="0.75" fill="currentColor" />
10
+ </svg>
11
+ ),
12
+ x: (
13
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
14
+ <path d="M18 2h3l-7.5 8.6L22 22h-6.6l-5-6.5L4 22H1l8-9.2L1.4 2H8l4.6 6 5.4-6z" />
15
+ </svg>
16
+ ),
17
+ tiktok: (
18
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
19
+ <path d="M16 3v3.5a4.5 4.5 0 0 0 4.5 4.5V14a7.5 7.5 0 0 1-4.5-1.5V16a5 5 0 1 1-5-5v3a2 2 0 1 0 2 2V3z" />
20
+ </svg>
21
+ ),
22
+ facebook: (
23
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
24
+ <path d="M14 9V7a1 1 0 0 1 1-1h2V3h-3a4 4 0 0 0-4 4v2H8v3h2v9h3v-9h2.5l.5-3H13z" />
25
+ </svg>
26
+ ),
27
+ youtube: (
28
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
29
+ <path d="M22.5 6.5a2.6 2.6 0 0 0-1.8-1.8C19 4.2 12 4.2 12 4.2s-7 0-8.7.5A2.6 2.6 0 0 0 1.5 6.5C1 8.2 1 12 1 12s0 3.8.5 5.5a2.6 2.6 0 0 0 1.8 1.8C5 19.8 12 19.8 12 19.8s7 0 8.7-.5a2.6 2.6 0 0 0 1.8-1.8c.5-1.7.5-5.5.5-5.5s0-3.8-.5-5.5zM10 15.5v-7l6 3.5-6 3.5z" />
30
+ </svg>
31
+ ),
32
+ linkedin: (
33
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
34
+ <path d="M4 4h4v16H4zM6 2.5a2 2 0 1 0 0 4 2 2 0 0 0 0-4zM10 8h4v2.5h.1c.6-1.1 2-2.5 4-2.5 4 0 4.9 2.6 4.9 6V20h-4v-5c0-1.5-.5-3-2.3-3-1.7 0-2.5 1.3-2.5 3v5h-4z" />
35
+ </svg>
36
+ ),
37
+ whatsapp: (
38
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
39
+ <path d="M12 2a10 10 0 0 0-8.6 15l-1.4 5 5.2-1.4A10 10 0 1 0 12 2zm5 14.2c-.2.6-1.2 1.2-1.7 1.2-.5.1-1.1.1-1.7-.1-.4-.1-.9-.3-1.5-.6a8.4 8.4 0 0 1-3.7-3.4c-.7-1-1-1.8-1-2.5 0-.7.4-1.1.6-1.3.2-.2.4-.2.5-.2h.4c.1 0 .3 0 .4.3l.6 1.4c.1.2 0 .3 0 .4l-.3.4-.3.3c-.1.1-.2.2-.1.4.2.4.7 1.1 1.4 1.8.9.8 1.7 1.1 1.9 1.2.2.1.3.1.5-.1l.6-.7c.2-.2.3-.2.5-.1l1.4.7c.2.1.3.2.4.3.1.2.1.6 0 1z" />
40
+ </svg>
41
+ ),
42
+ };
52
43
 
53
- const SITEMAP: { title: string; links: { label: string; href: string }[] }[] = [
54
- {
55
- title: "Shop",
56
- links: [
57
- { label: "All products", href: "/shop" },
58
- { label: "Breads", href: "/categories/breads" },
59
- { label: "Pastries", href: "/categories/pastries" },
60
- { label: "Cakes", href: "/categories/cakes" },
61
- { label: "Drinks", href: "/categories/drinks" },
62
- { label: "Merch & More", href: "/categories/merch" },
63
- { label: "Classes & Stays", href: "/categories/classes" },
64
- ],
65
- },
66
- {
67
- title: "Bakery",
68
- links: [
69
- { label: "Our story", href: "/about" },
70
- { label: "FAQ", href: "/faq" },
71
- { label: "Visit us", href: "/about#visit" },
72
- { label: "Wholesale", href: "/categories/merch" },
73
- ],
74
- },
75
- {
76
- title: "Help",
77
- links: [
78
- { label: "Contact", href: "mailto:hello@akuasbakery.test" },
79
- { label: "Custom cakes", href: "/faq#custom-cakes--celebrations" },
80
- { label: "Allergens", href: "/faq#allergens--ingredients" },
81
- { label: "Delivery", href: "/faq#ordering--delivery" },
82
- ],
83
- },
84
- {
85
- title: "Legal",
86
- links: [
87
- { label: "Terms of Service", href: "/terms" },
88
- { label: "Privacy Policy", href: "/privacy" },
89
- ],
90
- },
91
- ];
44
+ const FALLBACK_ICON = (
45
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden className="w-5 h-5">
46
+ <circle cx="12" cy="12" r="9" />
47
+ </svg>
48
+ );
92
49
 
93
50
  export async function Footer() {
94
51
  "use cache";
95
52
  const year = new Date().getFullYear();
96
53
  return (
97
- <footer className="mt-16 border-t border-border bg-card text-sm">
98
- <div className="max-w-7xl mx-auto px-8 pt-12 pb-8">
54
+ <footer className="mt-12 px-8 py-10 text-xs text-muted-foreground border-t border-border bg-card">
55
+ <div className="max-w-7xl mx-auto">
99
56
  <div className="grid gap-10 md:grid-cols-[1.4fr_repeat(4,1fr)]">
100
57
  <div>
101
- <p className="font-serif text-2xl text-foreground m-0 mb-2">Akua&apos;s Bakery</p>
102
- <p className="text-muted-foreground leading-relaxed mb-4 max-w-sm">
103
- Family-run bakery in East Legon. Sourdough, croissants, layered
104
- cakes — handcrafted since 2018, delivered across Accra.
105
- </p>
106
- <address className="not-italic text-muted-foreground space-y-1">
107
- <p className="m-0">12 Independence Ave, Accra</p>
58
+ <p className="font-serif text-2xl text-foreground m-0 mb-2">{brand.name}</p>
59
+ <p className="leading-relaxed mb-4 max-w-sm">{brand.footer.blurb}</p>
60
+ <address className="not-italic space-y-1">
61
+ <p className="m-0">{brand.contact.address}</p>
108
62
  <p className="m-0">
109
- <a href="tel:+233244000000" className="hover:text-foreground transition-colors">
110
- +233 244 000 000
63
+ <a
64
+ href={`tel:${brand.contact.phoneTel}`}
65
+ className="hover:text-foreground transition-colors"
66
+ >
67
+ {brand.contact.phone}
111
68
  </a>
112
69
  </p>
113
70
  <p className="m-0">
114
71
  <a
115
- href="mailto:hello@akuasbakery.test"
72
+ href={`mailto:${brand.contact.email}`}
116
73
  className="hover:text-foreground transition-colors"
117
74
  >
118
- hello@akuasbakery.test
75
+ {brand.contact.email}
119
76
  </a>
120
77
  </p>
121
- <p className="m-0 text-xs">Tue–Sun · 8am–8pm · closed Mondays</p>
78
+ <p className="m-0">{brand.contact.hours}</p>
122
79
  </address>
123
80
  <div className="flex items-center gap-3 mt-5">
124
- {SOCIALS.map((s) => (
81
+ {brand.socials.map((s) => (
125
82
  <a
126
83
  key={s.label}
127
84
  href={s.href}
@@ -130,12 +87,12 @@ export async function Footer() {
130
87
  rel="noopener noreferrer"
131
88
  className="inline-flex items-center justify-center w-9 h-9 rounded-full border border-border text-muted-foreground hover:text-foreground hover:border-foreground transition-colors"
132
89
  >
133
- {s.svg}
90
+ {(s.icon && ICONS[s.icon]) ?? FALLBACK_ICON}
134
91
  </a>
135
92
  ))}
136
93
  </div>
137
94
  </div>
138
- {SITEMAP.map((section) => (
95
+ {brand.footer.sitemap.map((section) => (
139
96
  <nav key={section.title} aria-labelledby={`footer-${section.title}`}>
140
97
  <p
141
98
  id={`footer-${section.title}`}
@@ -148,7 +105,7 @@ export async function Footer() {
148
105
  <li key={link.label}>
149
106
  <Link
150
107
  href={link.href}
151
- className="text-muted-foreground hover:text-foreground transition-colors"
108
+ className="hover:text-foreground transition-colors"
152
109
  >
153
110
  {link.label}
154
111
  </Link>
@@ -158,31 +115,32 @@ export async function Footer() {
158
115
  </nav>
159
116
  ))}
160
117
  </div>
161
-
162
- <div className="mt-12 pt-6 border-t border-border flex flex-col sm:flex-row items-center justify-between gap-3 text-xs text-muted-foreground">
163
- <p className="m-0">© {year} Akua&apos;s Bakery. All rights reserved.</p>
164
- <p className="m-0 inline-flex items-center gap-1.5">
165
- <span className="text-muted-foreground/80">Powered by</span>
166
- <a
167
- href="https://app.cimplify.io"
168
- target="_blank"
169
- rel="noopener noreferrer"
170
- aria-label="Cimplify"
171
- className="inline-flex items-center gap-1 font-serif text-foreground hover:text-primary transition-colors"
172
- >
173
- <span className="font-semibold tracking-tight">Cimplify</span>
174
- <svg
175
- viewBox="0 0 12 12"
176
- aria-hidden
177
- className="w-3 h-3 opacity-70"
178
- fill="none"
179
- stroke="currentColor"
180
- strokeWidth="1.5"
118
+ <div className="mt-12 pt-6 border-t border-border flex flex-col sm:flex-row items-center justify-between gap-3">
119
+ <p className="m-0">© {year} {brand.name}. All rights reserved.</p>
120
+ {brand.footer.poweredBy && (
121
+ <p className="m-0 inline-flex items-center gap-1.5">
122
+ <span className="text-muted-foreground/80">Powered by</span>
123
+ <a
124
+ href={brand.footer.poweredBy.href}
125
+ target="_blank"
126
+ rel="noopener noreferrer"
127
+ aria-label={brand.footer.poweredBy.label}
128
+ className="inline-flex items-center gap-1 font-serif text-foreground hover:text-primary transition-colors"
181
129
  >
182
- <path d="M3 9L9 3M9 3H4M9 3v5" strokeLinecap="round" strokeLinejoin="round" />
183
- </svg>
184
- </a>
185
- </p>
130
+ <span className="font-semibold tracking-tight">{brand.footer.poweredBy.label}</span>
131
+ <svg
132
+ viewBox="0 0 12 12"
133
+ aria-hidden
134
+ className="w-3 h-3 opacity-70"
135
+ fill="none"
136
+ stroke="currentColor"
137
+ strokeWidth="1.5"
138
+ >
139
+ <path d="M3 9L9 3M9 3H4M9 3v5" strokeLinecap="round" strokeLinejoin="round" />
140
+ </svg>
141
+ </a>
142
+ </p>
143
+ )}
186
144
  </div>
187
145
  </div>
188
146
  </footer>
@@ -2,8 +2,7 @@ import Link from "next/link";
2
2
  import { Suspense } from "react";
3
3
  import { NavLink } from "./nav-link";
4
4
  import { CartPill, CartPillSkeleton } from "./cart-pill";
5
-
6
- const TAGLINE = "ACCRA · SINCE 2018";
5
+ import { brand } from "@/lib/brand";
7
6
 
8
7
  /**
9
8
  * Server-rendered header chrome. Brand mark + nav layout streams from the
@@ -15,25 +14,18 @@ export function Header() {
15
14
  <header className="sticky top-0 z-30 flex items-center justify-between px-8 py-4 border-b border-border bg-background/90 backdrop-blur-md">
16
15
  <Link href="/" className="flex items-baseline gap-2">
17
16
  <span className="font-serif text-[22px] font-semibold -tracking-[0.02em]">
18
- Akua&apos;s Bakery
17
+ {brand.shortName}
19
18
  </span>
20
19
  <span className="text-[11px] font-medium uppercase tracking-[0.12em] text-muted-foreground">
21
- {TAGLINE}
20
+ {brand.microTag}
22
21
  </span>
23
22
  </Link>
24
23
  <nav className="flex items-center gap-6">
25
- <Suspense fallback={<NavLinkFallback>Home</NavLinkFallback>}>
26
- <NavLink href="/">Home</NavLink>
27
- </Suspense>
28
- <Suspense fallback={<NavLinkFallback>Shop</NavLinkFallback>}>
29
- <NavLink href="/shop">Shop</NavLink>
30
- </Suspense>
31
- <Suspense fallback={<NavLinkFallback>About</NavLinkFallback>}>
32
- <NavLink href="/about">About</NavLink>
33
- </Suspense>
34
- <Suspense fallback={<NavLinkFallback>FAQ</NavLinkFallback>}>
35
- <NavLink href="/faq">FAQ</NavLink>
36
- </Suspense>
24
+ {brand.header.nav.map((link) => (
25
+ <Suspense key={link.href} fallback={<NavLinkFallback>{link.label}</NavLinkFallback>}>
26
+ <NavLink href={link.href}>{link.label}</NavLink>
27
+ </Suspense>
28
+ ))}
37
29
  <Suspense fallback={<CartPillSkeleton />}>
38
30
  <CartPill />
39
31
  </Suspense>
@@ -0,0 +1,49 @@
1
+ import type { BrandPolicySection } from "@/lib/brand";
2
+
3
+ interface PolicyShape {
4
+ eyebrow: string;
5
+ title: string;
6
+ lastUpdated?: string;
7
+ sections: BrandPolicySection[];
8
+ }
9
+
10
+ /**
11
+ * Shared layout for shipping / returns / accessibility / terms / privacy.
12
+ * Reads a `{ eyebrow, title, lastUpdated, sections[] }` block from brand.
13
+ */
14
+ export function PolicyPage({ policy }: { policy: PolicyShape }) {
15
+ return (
16
+ <article className="max-w-3xl mx-auto px-8 py-16 prose prose-lg max-w-none">
17
+ <p className="text-[11px] font-semibold uppercase tracking-[0.16em] text-primary mb-2 not-prose">
18
+ {policy.eyebrow}
19
+ </p>
20
+ <h1 className="text-[clamp(2.25rem,5vw,3.5rem)] font-semibold mb-2 -tracking-[0.02em]">
21
+ {policy.title}
22
+ </h1>
23
+ {policy.lastUpdated && (
24
+ <p className="text-sm text-muted-foreground not-prose mb-10">
25
+ Last updated: {policy.lastUpdated}
26
+ </p>
27
+ )}
28
+ <section className="space-y-5 leading-relaxed text-foreground/90">
29
+ {policy.sections.map((s) => (
30
+ <div key={s.heading}>
31
+ <h2 className="text-2xl font-semibold mt-0">{s.heading}</h2>
32
+ {typeof s.body === "string" ? (
33
+ <p>{s.body}</p>
34
+ ) : (
35
+ <>
36
+ <p>{s.body.intro}</p>
37
+ <ul className="list-disc pl-6 space-y-2">
38
+ {s.body.bullets.map((b) => (
39
+ <li key={b}>{b}</li>
40
+ ))}
41
+ </ul>
42
+ </>
43
+ )}
44
+ </div>
45
+ ))}
46
+ </section>
47
+ </article>
48
+ );
49
+ }