@cimplify/sdk 0.40.0 → 0.41.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 (227) hide show
  1. package/dist/dispatcher.mjs +3 -2
  2. package/dist/mock/cli.mjs +30 -6
  3. package/dist/mock/library.js +30 -6
  4. package/dist/mock/library.mjs +30 -6
  5. package/dist/mock/msw.js +30 -6
  6. package/dist/mock/msw.mjs +30 -6
  7. package/dist/styles.css +1 -1
  8. package/package.json +1 -1
  9. package/templates/storefront-bakery/.env.example +5 -0
  10. package/templates/storefront-bakery/AGENTS.md +57 -0
  11. package/templates/storefront-bakery/app/about/page.tsx +21 -44
  12. package/templates/storefront-bakery/app/categories/[slug]/page.tsx +2 -1
  13. package/templates/storefront-bakery/app/collections/[slug]/page.tsx +2 -1
  14. package/templates/storefront-bakery/app/error.tsx +60 -0
  15. package/templates/storefront-bakery/app/faq/page.tsx +13 -89
  16. package/templates/storefront-bakery/app/layout.tsx +37 -2
  17. package/templates/storefront-bakery/app/llms.txt/route.ts +94 -0
  18. package/templates/storefront-bakery/app/not-found.tsx +39 -0
  19. package/templates/storefront-bakery/app/page.tsx +6 -6
  20. package/templates/storefront-bakery/app/privacy/page.tsx +24 -68
  21. package/templates/storefront-bakery/app/robots.ts +18 -0
  22. package/templates/storefront-bakery/app/shop/page.tsx +3 -2
  23. package/templates/storefront-bakery/app/sitemap.ts +62 -0
  24. package/templates/storefront-bakery/app/terms/page.tsx +24 -82
  25. package/templates/storefront-bakery/components/footer.tsx +88 -130
  26. package/templates/storefront-bakery/components/header.tsx +8 -16
  27. package/templates/storefront-bakery/lib/brand.ts +453 -0
  28. package/templates/storefront-fashion/.env.example +16 -0
  29. package/templates/storefront-fashion/AGENTS.md +52 -0
  30. package/templates/storefront-fashion/README.md +77 -0
  31. package/templates/storefront-fashion/app/about/page.tsx +41 -0
  32. package/templates/storefront-fashion/app/cart/page.tsx +9 -0
  33. package/templates/storefront-fashion/app/categories/[slug]/listing-client.tsx +19 -0
  34. package/templates/storefront-fashion/app/categories/[slug]/page.tsx +130 -0
  35. package/templates/storefront-fashion/app/checkout/page.tsx +17 -0
  36. package/templates/storefront-fashion/app/collections/[slug]/listing-client.tsx +20 -0
  37. package/templates/storefront-fashion/app/collections/[slug]/page.tsx +130 -0
  38. package/templates/storefront-fashion/app/error.tsx +61 -0
  39. package/templates/storefront-fashion/app/faq/page.tsx +46 -0
  40. package/templates/storefront-fashion/app/globals.css +46 -0
  41. package/templates/storefront-fashion/app/layout.tsx +76 -0
  42. package/templates/storefront-fashion/app/llms.txt/route.ts +94 -0
  43. package/templates/storefront-fashion/app/not-found.tsx +39 -0
  44. package/templates/storefront-fashion/app/orders/[id]/page.tsx +24 -0
  45. package/templates/storefront-fashion/app/page.tsx +183 -0
  46. package/templates/storefront-fashion/app/privacy/page.tsx +44 -0
  47. package/templates/storefront-fashion/app/products/[slug]/page.tsx +165 -0
  48. package/templates/storefront-fashion/app/products/[slug]/product-detail.tsx +71 -0
  49. package/templates/storefront-fashion/app/robots.ts +18 -0
  50. package/templates/storefront-fashion/app/shop/page.tsx +63 -0
  51. package/templates/storefront-fashion/app/shop/shop-client.tsx +32 -0
  52. package/templates/storefront-fashion/app/sitemap.ts +59 -0
  53. package/templates/storefront-fashion/app/terms/page.tsx +44 -0
  54. package/templates/storefront-fashion/components/brand-marquee.tsx +27 -0
  55. package/templates/storefront-fashion/components/cart-pill.tsx +32 -0
  56. package/templates/storefront-fashion/components/category-grid.tsx +28 -0
  57. package/templates/storefront-fashion/components/category-tiles.tsx +104 -0
  58. package/templates/storefront-fashion/components/collection-strip.tsx +45 -0
  59. package/templates/storefront-fashion/components/feature-hero.tsx +82 -0
  60. package/templates/storefront-fashion/components/footer.tsx +153 -0
  61. package/templates/storefront-fashion/components/header.tsx +43 -0
  62. package/templates/storefront-fashion/components/hero.tsx +28 -0
  63. package/templates/storefront-fashion/components/nav-link.tsx +20 -0
  64. package/templates/storefront-fashion/components/newsletter.tsx +50 -0
  65. package/templates/storefront-fashion/components/promo-banner.tsx +41 -0
  66. package/templates/storefront-fashion/components/providers.tsx +31 -0
  67. package/templates/storefront-fashion/components/section-heading.tsx +37 -0
  68. package/templates/storefront-fashion/components/store-product-card.tsx +83 -0
  69. package/templates/storefront-fashion/components/trade-in-cta.tsx +54 -0
  70. package/templates/storefront-fashion/components/trust-bar.tsx +66 -0
  71. package/templates/storefront-fashion/lib/brand.ts +421 -0
  72. package/templates/storefront-fashion/lib/cart.ts +27 -0
  73. package/templates/storefront-fashion/next.config.ts +40 -0
  74. package/templates/storefront-fashion/package.json +28 -0
  75. package/templates/storefront-fashion/postcss.config.mjs +7 -0
  76. package/templates/storefront-fashion/tsconfig.json +23 -0
  77. package/templates/storefront-grocery/.env.example +16 -0
  78. package/templates/storefront-grocery/AGENTS.md +39 -0
  79. package/templates/storefront-grocery/README.md +73 -0
  80. package/templates/storefront-grocery/app/about/page.tsx +38 -0
  81. package/templates/storefront-grocery/app/cart/page.tsx +9 -0
  82. package/templates/storefront-grocery/app/categories/[slug]/listing-client.tsx +19 -0
  83. package/templates/storefront-grocery/app/categories/[slug]/page.tsx +118 -0
  84. package/templates/storefront-grocery/app/checkout/page.tsx +17 -0
  85. package/templates/storefront-grocery/app/collections/[slug]/listing-client.tsx +20 -0
  86. package/templates/storefront-grocery/app/collections/[slug]/page.tsx +118 -0
  87. package/templates/storefront-grocery/app/error.tsx +60 -0
  88. package/templates/storefront-grocery/app/faq/page.tsx +46 -0
  89. package/templates/storefront-grocery/app/globals.css +45 -0
  90. package/templates/storefront-grocery/app/layout.tsx +75 -0
  91. package/templates/storefront-grocery/app/llms.txt/route.ts +94 -0
  92. package/templates/storefront-grocery/app/not-found.tsx +39 -0
  93. package/templates/storefront-grocery/app/orders/[id]/page.tsx +21 -0
  94. package/templates/storefront-grocery/app/page.tsx +97 -0
  95. package/templates/storefront-grocery/app/privacy/page.tsx +44 -0
  96. package/templates/storefront-grocery/app/robots.ts +18 -0
  97. package/templates/storefront-grocery/app/shop/page.tsx +31 -0
  98. package/templates/storefront-grocery/app/shop/shop-client.tsx +27 -0
  99. package/templates/storefront-grocery/app/sitemap.ts +62 -0
  100. package/templates/storefront-grocery/app/terms/page.tsx +44 -0
  101. package/templates/storefront-grocery/components/cart-pill.tsx +32 -0
  102. package/templates/storefront-grocery/components/category-grid.tsx +28 -0
  103. package/templates/storefront-grocery/components/collection-strip.tsx +45 -0
  104. package/templates/storefront-grocery/components/footer.tsx +148 -0
  105. package/templates/storefront-grocery/components/header.tsx +43 -0
  106. package/templates/storefront-grocery/components/hero.tsx +25 -0
  107. package/templates/storefront-grocery/components/nav-link.tsx +20 -0
  108. package/templates/storefront-grocery/components/providers.tsx +31 -0
  109. package/templates/storefront-grocery/components/store-product-card.tsx +83 -0
  110. package/templates/storefront-grocery/lib/brand.ts +284 -0
  111. package/templates/storefront-grocery/lib/cart.ts +27 -0
  112. package/templates/storefront-grocery/next.config.ts +40 -0
  113. package/templates/storefront-grocery/package.json +28 -0
  114. package/templates/storefront-grocery/postcss.config.mjs +7 -0
  115. package/templates/storefront-grocery/tsconfig.json +23 -0
  116. package/templates/storefront-restaurant/.env.example +16 -0
  117. package/templates/storefront-restaurant/AGENTS.md +39 -0
  118. package/templates/storefront-restaurant/README.md +73 -0
  119. package/templates/storefront-restaurant/app/about/page.tsx +38 -0
  120. package/templates/storefront-restaurant/app/cart/page.tsx +9 -0
  121. package/templates/storefront-restaurant/app/categories/[slug]/listing-client.tsx +19 -0
  122. package/templates/storefront-restaurant/app/categories/[slug]/page.tsx +118 -0
  123. package/templates/storefront-restaurant/app/checkout/page.tsx +17 -0
  124. package/templates/storefront-restaurant/app/collections/[slug]/listing-client.tsx +20 -0
  125. package/templates/storefront-restaurant/app/collections/[slug]/page.tsx +118 -0
  126. package/templates/storefront-restaurant/app/error.tsx +60 -0
  127. package/templates/storefront-restaurant/app/faq/page.tsx +46 -0
  128. package/templates/storefront-restaurant/app/globals.css +44 -0
  129. package/templates/storefront-restaurant/app/layout.tsx +80 -0
  130. package/templates/storefront-restaurant/app/llms.txt/route.ts +94 -0
  131. package/templates/storefront-restaurant/app/not-found.tsx +39 -0
  132. package/templates/storefront-restaurant/app/orders/[id]/page.tsx +21 -0
  133. package/templates/storefront-restaurant/app/page.tsx +97 -0
  134. package/templates/storefront-restaurant/app/privacy/page.tsx +44 -0
  135. package/templates/storefront-restaurant/app/robots.ts +18 -0
  136. package/templates/storefront-restaurant/app/shop/page.tsx +31 -0
  137. package/templates/storefront-restaurant/app/shop/shop-client.tsx +27 -0
  138. package/templates/storefront-restaurant/app/sitemap.ts +62 -0
  139. package/templates/storefront-restaurant/app/terms/page.tsx +44 -0
  140. package/templates/storefront-restaurant/components/cart-pill.tsx +32 -0
  141. package/templates/storefront-restaurant/components/category-grid.tsx +28 -0
  142. package/templates/storefront-restaurant/components/collection-strip.tsx +45 -0
  143. package/templates/storefront-restaurant/components/footer.tsx +148 -0
  144. package/templates/storefront-restaurant/components/header.tsx +43 -0
  145. package/templates/storefront-restaurant/components/hero.tsx +25 -0
  146. package/templates/storefront-restaurant/components/nav-link.tsx +20 -0
  147. package/templates/storefront-restaurant/components/product-modal.tsx +105 -0
  148. package/templates/storefront-restaurant/components/providers.tsx +31 -0
  149. package/templates/storefront-restaurant/components/store-product-card.tsx +83 -0
  150. package/templates/storefront-restaurant/lib/brand.ts +287 -0
  151. package/templates/storefront-restaurant/lib/cart.ts +27 -0
  152. package/templates/storefront-restaurant/next.config.ts +40 -0
  153. package/templates/storefront-restaurant/package.json +28 -0
  154. package/templates/storefront-restaurant/postcss.config.mjs +7 -0
  155. package/templates/storefront-restaurant/tsconfig.json +23 -0
  156. package/templates/storefront-retail/.env.example +5 -0
  157. package/templates/storefront-retail/AGENTS.md +64 -0
  158. package/templates/storefront-retail/app/about/page.tsx +24 -54
  159. package/templates/storefront-retail/app/categories/[slug]/page.tsx +50 -37
  160. package/templates/storefront-retail/app/collections/[slug]/page.tsx +50 -37
  161. package/templates/storefront-retail/app/error.tsx +61 -0
  162. package/templates/storefront-retail/app/faq/page.tsx +11 -92
  163. package/templates/storefront-retail/app/layout.tsx +37 -8
  164. package/templates/storefront-retail/app/llms.txt/route.ts +94 -0
  165. package/templates/storefront-retail/app/not-found.tsx +39 -0
  166. package/templates/storefront-retail/app/page.tsx +111 -26
  167. package/templates/storefront-retail/app/privacy/page.tsx +24 -81
  168. package/templates/storefront-retail/app/products/[slug]/page.tsx +165 -0
  169. package/templates/storefront-retail/app/products/[slug]/product-detail.tsx +71 -0
  170. package/templates/storefront-retail/app/robots.ts +18 -0
  171. package/templates/storefront-retail/app/shop/page.tsx +36 -3
  172. package/templates/storefront-retail/app/shop/shop-client.tsx +6 -1
  173. package/templates/storefront-retail/app/sitemap.ts +59 -0
  174. package/templates/storefront-retail/app/terms/page.tsx +24 -97
  175. package/templates/storefront-retail/components/brand-marquee.tsx +27 -0
  176. package/templates/storefront-retail/components/category-tiles.tsx +104 -0
  177. package/templates/storefront-retail/components/feature-hero.tsx +84 -0
  178. package/templates/storefront-retail/components/footer.tsx +85 -120
  179. package/templates/storefront-retail/components/header.tsx +10 -12
  180. package/templates/storefront-retail/components/newsletter.tsx +50 -0
  181. package/templates/storefront-retail/components/promo-banner.tsx +41 -0
  182. package/templates/storefront-retail/components/section-heading.tsx +37 -0
  183. package/templates/storefront-retail/components/store-product-card.tsx +7 -7
  184. package/templates/storefront-retail/components/trade-in-cta.tsx +54 -0
  185. package/templates/storefront-retail/components/trust-bar.tsx +66 -0
  186. package/templates/storefront-retail/lib/brand.ts +567 -0
  187. package/templates/storefront-services/.env.example +16 -0
  188. package/templates/storefront-services/AGENTS.md +41 -0
  189. package/templates/storefront-services/README.md +73 -0
  190. package/templates/storefront-services/app/about/page.tsx +38 -0
  191. package/templates/storefront-services/app/cart/page.tsx +9 -0
  192. package/templates/storefront-services/app/categories/[slug]/listing-client.tsx +19 -0
  193. package/templates/storefront-services/app/categories/[slug]/page.tsx +118 -0
  194. package/templates/storefront-services/app/checkout/page.tsx +17 -0
  195. package/templates/storefront-services/app/collections/[slug]/listing-client.tsx +20 -0
  196. package/templates/storefront-services/app/collections/[slug]/page.tsx +118 -0
  197. package/templates/storefront-services/app/error.tsx +60 -0
  198. package/templates/storefront-services/app/faq/page.tsx +46 -0
  199. package/templates/storefront-services/app/globals.css +45 -0
  200. package/templates/storefront-services/app/layout.tsx +80 -0
  201. package/templates/storefront-services/app/llms.txt/route.ts +94 -0
  202. package/templates/storefront-services/app/not-found.tsx +39 -0
  203. package/templates/storefront-services/app/orders/[id]/page.tsx +21 -0
  204. package/templates/storefront-services/app/page.tsx +97 -0
  205. package/templates/storefront-services/app/privacy/page.tsx +44 -0
  206. package/templates/storefront-services/app/robots.ts +18 -0
  207. package/templates/storefront-services/app/shop/page.tsx +31 -0
  208. package/templates/storefront-services/app/shop/shop-client.tsx +27 -0
  209. package/templates/storefront-services/app/sitemap.ts +62 -0
  210. package/templates/storefront-services/app/terms/page.tsx +44 -0
  211. package/templates/storefront-services/components/cart-pill.tsx +32 -0
  212. package/templates/storefront-services/components/category-grid.tsx +28 -0
  213. package/templates/storefront-services/components/collection-strip.tsx +45 -0
  214. package/templates/storefront-services/components/footer.tsx +148 -0
  215. package/templates/storefront-services/components/header.tsx +43 -0
  216. package/templates/storefront-services/components/hero.tsx +25 -0
  217. package/templates/storefront-services/components/nav-link.tsx +20 -0
  218. package/templates/storefront-services/components/product-modal.tsx +105 -0
  219. package/templates/storefront-services/components/providers.tsx +31 -0
  220. package/templates/storefront-services/components/store-product-card.tsx +83 -0
  221. package/templates/storefront-services/lib/brand.ts +303 -0
  222. package/templates/storefront-services/lib/cart.ts +27 -0
  223. package/templates/storefront-services/next.config.ts +40 -0
  224. package/templates/storefront-services/package.json +28 -0
  225. package/templates/storefront-services/postcss.config.mjs +7 -0
  226. package/templates/storefront-services/tsconfig.json +23 -0
  227. /package/templates/{storefront-retail → storefront-grocery}/components/product-modal.tsx +0 -0
@@ -1,84 +1,51 @@
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/currentselectronics",
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: "X",
17
- href: "https://x.com/currentselectronics",
18
- svg: (
19
- <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
20
- <path d="M18 2h3l-7.5 8.6L22 22h-6.6l-5-6.5L4 22H1l8-9.2L1.4 2H8l4.6 6 5.4-6z" />
21
- </svg>
22
- ),
23
- },
24
- {
25
- label: "YouTube",
26
- href: "https://youtube.com/@currentselectronics",
27
- svg: (
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
- },
33
- {
34
- label: "WhatsApp",
35
- href: "https://wa.me/233244000000",
36
- svg: (
37
- <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
38
- <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" />
39
- </svg>
40
- ),
41
- },
42
- ];
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
+ };
43
43
 
44
- const SITEMAP: { title: string; links: { label: string; href: string }[] }[] = [
45
- {
46
- title: "Shop",
47
- links: [
48
- { label: "All products", href: "/shop" },
49
- { label: "Laptops", href: "/categories/laptops" },
50
- { label: "Phones", href: "/categories/phones" },
51
- { label: "Audio", href: "/categories/audio" },
52
- { label: "Accessories", href: "/categories/accessories" },
53
- { label: "Deals", href: "/categories/deals" },
54
- ],
55
- },
56
- {
57
- title: "Support",
58
- links: [
59
- { label: "Contact", href: "mailto:hello@currentselectronics.test" },
60
- { label: "Warranty", href: "/faq#warranty--repairs" },
61
- { label: "Returns", href: "/faq#payment--returns" },
62
- { label: "Shipping", href: "/faq#ordering--delivery" },
63
- ],
64
- },
65
- {
66
- title: "Company",
67
- links: [
68
- { label: "About", href: "/about" },
69
- { label: "Trade-in", href: "/about" },
70
- { label: "Business sales", href: "mailto:business@currentselectronics.test" },
71
- { label: "Careers", href: "/about" },
72
- ],
73
- },
74
- {
75
- title: "Legal",
76
- links: [
77
- { label: "Terms of Service", href: "/terms" },
78
- { label: "Privacy Policy", href: "/privacy" },
79
- ],
80
- },
81
- ];
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
+ );
82
49
 
83
50
  export async function Footer() {
84
51
  "use cache";
@@ -90,36 +57,35 @@ export async function Footer() {
90
57
  <div>
91
58
  <div className="flex items-center gap-2.5 mb-4">
92
59
  <span className="grid place-items-center w-8 h-8 rounded-md bg-primary text-primary-foreground text-[13px] font-bold font-mono">
93
- C
60
+ {brand.shortName.charAt(0).toUpperCase()}
94
61
  </span>
95
62
  <span className="text-background text-lg font-bold -tracking-[0.025em]">
96
- Currents Electronics
63
+ {brand.name}
97
64
  </span>
98
65
  </div>
99
- <p className="leading-relaxed mb-4 max-w-sm">
100
- Authorised dealer for Apple, Samsung, Sony, Bose. Same-day
101
- delivery in Accra; nationwide via partner courier. Two-year
102
- warranty on every product.
103
- </p>
66
+ <p className="leading-relaxed mb-4 max-w-sm">{brand.footer.blurb}</p>
104
67
  <address className="not-italic space-y-1">
105
- <p className="m-0">Atomic Junction, East Legon, Accra</p>
68
+ <p className="m-0">{brand.contact.address}</p>
106
69
  <p className="m-0">
107
- <a href="tel:+233244000000" className="hover:text-background transition-colors">
108
- +233 244 000 000
70
+ <a
71
+ href={`tel:${brand.contact.phoneTel}`}
72
+ className="hover:text-background transition-colors"
73
+ >
74
+ {brand.contact.phone}
109
75
  </a>
110
76
  </p>
111
77
  <p className="m-0">
112
78
  <a
113
- href="mailto:hello@currentselectronics.test"
79
+ href={`mailto:${brand.contact.email}`}
114
80
  className="hover:text-background transition-colors"
115
81
  >
116
- hello@currentselectronics.test
82
+ {brand.contact.email}
117
83
  </a>
118
84
  </p>
119
- <p className="m-0 text-xs">Mon–Sat · 9am–8pm</p>
85
+ <p className="m-0 text-xs">{brand.contact.hours}</p>
120
86
  </address>
121
87
  <div className="flex items-center gap-3 mt-5">
122
- {SOCIALS.map((s) => (
88
+ {brand.socials.map((s) => (
123
89
  <a
124
90
  key={s.label}
125
91
  href={s.href}
@@ -128,12 +94,12 @@ export async function Footer() {
128
94
  rel="noopener noreferrer"
129
95
  className="inline-flex items-center justify-center w-9 h-9 rounded-md border border-background/20 hover:bg-primary hover:border-primary transition-colors"
130
96
  >
131
- {s.svg}
97
+ {(s.icon && ICONS[s.icon]) ?? FALLBACK_ICON}
132
98
  </a>
133
99
  ))}
134
100
  </div>
135
101
  </div>
136
- {SITEMAP.map((section) => (
102
+ {brand.footer.sitemap.map((section) => (
137
103
  <nav key={section.title} aria-labelledby={`footer-${section.title}`}>
138
104
  <p
139
105
  id={`footer-${section.title}`}
@@ -144,10 +110,7 @@ export async function Footer() {
144
110
  <ul className="space-y-2 m-0 p-0 list-none">
145
111
  {section.links.map((link) => (
146
112
  <li key={link.label}>
147
- <Link
148
- href={link.href}
149
- className="hover:text-background transition-colors"
150
- >
113
+ <Link href={link.href} className="hover:text-background transition-colors">
151
114
  {link.label}
152
115
  </Link>
153
116
  </li>
@@ -158,29 +121,31 @@ export async function Footer() {
158
121
  </div>
159
122
 
160
123
  <div className="mt-12 pt-6 border-t border-background/15 flex flex-col sm:flex-row items-center justify-between gap-3 text-xs">
161
- <p className="m-0">© {year} Currents Electronics. All rights reserved.</p>
162
- <p className="m-0 inline-flex items-center gap-1.5">
163
- <span className="opacity-70">Powered by</span>
164
- <a
165
- href="https://app.cimplify.io"
166
- target="_blank"
167
- rel="noopener noreferrer"
168
- aria-label="Cimplify"
169
- className="inline-flex items-center gap-1 text-background hover:text-primary transition-colors"
170
- >
171
- <span className="font-semibold tracking-tight">Cimplify</span>
172
- <svg
173
- viewBox="0 0 12 12"
174
- aria-hidden
175
- className="w-3 h-3 opacity-70"
176
- fill="none"
177
- stroke="currentColor"
178
- strokeWidth="1.5"
124
+ <p className="m-0">© {year} {brand.name}. All rights reserved.</p>
125
+ {brand.footer.poweredBy && (
126
+ <p className="m-0 inline-flex items-center gap-1.5">
127
+ <span className="opacity-70">Powered by</span>
128
+ <a
129
+ href={brand.footer.poweredBy.href}
130
+ target="_blank"
131
+ rel="noopener noreferrer"
132
+ aria-label={brand.footer.poweredBy.label}
133
+ className="inline-flex items-center gap-1 text-background hover:text-primary transition-colors"
179
134
  >
180
- <path d="M3 9L9 3M9 3H4M9 3v5" strokeLinecap="round" strokeLinejoin="round" />
181
- </svg>
182
- </a>
183
- </p>
135
+ <span className="font-semibold tracking-tight">{brand.footer.poweredBy.label}</span>
136
+ <svg
137
+ viewBox="0 0 12 12"
138
+ aria-hidden
139
+ className="w-3 h-3 opacity-70"
140
+ fill="none"
141
+ stroke="currentColor"
142
+ strokeWidth="1.5"
143
+ >
144
+ <path d="M3 9L9 3M9 3H4M9 3v5" strokeLinecap="round" strokeLinejoin="round" />
145
+ </svg>
146
+ </a>
147
+ </p>
148
+ )}
184
149
  </div>
185
150
  </div>
186
151
  </footer>
@@ -2,6 +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
+ import { brand } from "@/lib/brand";
5
6
 
6
7
  /**
7
8
  * Server-rendered header chrome. Brand mark + nav layout streams from the
@@ -9,27 +10,24 @@ import { CartPill, CartPillSkeleton } from "./cart-pill";
9
10
  * mounted in their own Suspense boundaries so the chrome never blocks.
10
11
  */
11
12
  export function Header() {
13
+ const initial = brand.shortName.charAt(0).toUpperCase();
12
14
  return (
13
15
  <header className="sticky top-0 z-30 flex items-center justify-between px-6 sm:px-8 py-3.5 border-b border-border bg-background/90 backdrop-blur-md">
14
16
  <Link href="/" className="flex items-center gap-2.5 group">
15
17
  <span className="grid place-items-center w-8 h-8 rounded-md bg-foreground text-background text-[13px] font-bold font-mono group-hover:bg-primary transition-colors">
16
- C
18
+ {initial}
17
19
  </span>
18
- <span className="text-[18px] font-bold -tracking-[0.025em]">Currents</span>
20
+ <span className="text-[18px] font-bold -tracking-[0.025em]">{brand.shortName}</span>
19
21
  <span className="hidden sm:inline text-[10px] font-mono uppercase tracking-[0.16em] text-muted-foreground border border-border rounded px-1.5 py-0.5">
20
- ELECTRONICS
22
+ {brand.microTag}
21
23
  </span>
22
24
  </Link>
23
25
  <nav className="flex items-center gap-5 sm:gap-6">
24
- <Suspense fallback={<NavLinkFallback>Shop</NavLinkFallback>}>
25
- <NavLink href="/shop">Shop</NavLink>
26
- </Suspense>
27
- <Suspense fallback={<NavLinkFallback>Deals</NavLinkFallback>}>
28
- <NavLink href="/categories/deals">Deals</NavLink>
29
- </Suspense>
30
- <Suspense fallback={<NavLinkFallback>Support</NavLinkFallback>}>
31
- <NavLink href="/faq">Support</NavLink>
32
- </Suspense>
26
+ {brand.header.nav.map((link) => (
27
+ <Suspense key={link.href} fallback={<NavLinkFallback>{link.label}</NavLinkFallback>}>
28
+ <NavLink href={link.href}>{link.label}</NavLink>
29
+ </Suspense>
30
+ ))}
33
31
  <Suspense fallback={<CartPillSkeleton />}>
34
32
  <CartPill />
35
33
  </Suspense>
@@ -0,0 +1,50 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { brand } from "@/lib/brand";
5
+
6
+ export function Newsletter() {
7
+ const n = brand.newsletter;
8
+ const [email, setEmail] = useState("");
9
+ const [submitted, setSubmitted] = useState(false);
10
+
11
+ return (
12
+ <section className="max-w-7xl mx-auto px-6 sm:px-8 py-14 sm:py-20">
13
+ <div className="rounded-3xl border border-border bg-card p-8 sm:p-12 grid grid-cols-1 lg:grid-cols-2 gap-8 items-center">
14
+ <div>
15
+ <p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary mb-2">
16
+ {n.eyebrow}
17
+ </p>
18
+ <h2 className="text-[clamp(1.5rem,3vw,2rem)] font-bold m-0 mb-3 -tracking-[0.025em]">
19
+ {n.title}
20
+ </h2>
21
+ <p className="text-muted-foreground leading-relaxed">{n.body}</p>
22
+ </div>
23
+ <form
24
+ onSubmit={(e) => {
25
+ e.preventDefault();
26
+ setSubmitted(true);
27
+ }}
28
+ className="flex flex-col sm:flex-row gap-2"
29
+ >
30
+ <input
31
+ type="email"
32
+ required
33
+ value={email}
34
+ onChange={(e) => setEmail(e.target.value)}
35
+ placeholder={n.placeholder}
36
+ disabled={submitted}
37
+ className="flex-1 px-4 py-3 rounded-md bg-background border border-border focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-shadow text-sm disabled:opacity-50"
38
+ />
39
+ <button
40
+ type="submit"
41
+ disabled={submitted}
42
+ className="inline-flex items-center justify-center gap-2 px-5 py-3 rounded-md bg-foreground text-background font-semibold text-sm hover:bg-primary transition-colors disabled:opacity-50"
43
+ >
44
+ {submitted ? n.successLabel : n.submitLabel}
45
+ </button>
46
+ </form>
47
+ </div>
48
+ </section>
49
+ );
50
+ }
@@ -0,0 +1,41 @@
1
+ import Link from "next/link";
2
+ import { brand } from "@/lib/brand";
3
+
4
+ /**
5
+ * Full-width promo banner — reads brand.promo. Renders nothing if the
6
+ * brand doesn't define a promo, so this component is safe to drop in
7
+ * across templates that may or may not run a campaign.
8
+ */
9
+ export function PromoBanner() {
10
+ const promo = brand.promo;
11
+ if (!promo) return null;
12
+ return (
13
+ <section className="max-w-7xl mx-auto px-6 sm:px-8 py-6">
14
+ <div className="relative overflow-hidden rounded-3xl bg-gradient-to-br from-primary via-primary to-foreground text-primary-foreground p-8 sm:p-12 lg:p-16">
15
+ <div className="absolute -top-20 -right-20 w-72 h-72 rounded-full bg-background/10 blur-3xl pointer-events-none" />
16
+ <div className="absolute -bottom-32 -left-20 w-96 h-96 rounded-full bg-foreground/30 blur-3xl pointer-events-none" />
17
+ <div className="relative grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-8 items-center">
18
+ <div className="max-w-2xl">
19
+ <span className="inline-flex items-center gap-2 mb-4 px-3 py-1 rounded-full bg-background/15 border border-background/25 text-[11px] font-mono uppercase tracking-[0.16em]">
20
+ <span className="w-1.5 h-1.5 rounded-full bg-background animate-pulse" />
21
+ {promo.badge}
22
+ </span>
23
+ <h2 className="text-[clamp(1.75rem,3.5vw,2.75rem)] font-bold m-0 mb-3 -tracking-[0.025em] leading-[1.1]">
24
+ {promo.title}
25
+ </h2>
26
+ <p className="text-base sm:text-lg opacity-90 leading-relaxed">{promo.body}</p>
27
+ </div>
28
+ <Link
29
+ href={promo.ctaHref}
30
+ className="inline-flex items-center gap-2 px-5 py-3 rounded-md bg-background text-foreground font-semibold text-sm hover:bg-background/90 transition-colors whitespace-nowrap"
31
+ >
32
+ {promo.ctaLabel}
33
+ <svg viewBox="0 0 12 12" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
34
+ <path d="M3 6h7m0 0L7 3m3 3L7 9" strokeLinecap="round" strokeLinejoin="round" />
35
+ </svg>
36
+ </Link>
37
+ </div>
38
+ </div>
39
+ </section>
40
+ );
41
+ }
@@ -0,0 +1,37 @@
1
+ import Link from "next/link";
2
+
3
+ interface SectionHeadingProps {
4
+ eyebrow: string;
5
+ title: string;
6
+ description?: string;
7
+ link?: { label: string; href: string };
8
+ }
9
+
10
+ export function SectionHeading({ eyebrow, title, description, link }: SectionHeadingProps) {
11
+ return (
12
+ <div className="flex items-end justify-between gap-6 mb-8">
13
+ <div className="max-w-2xl">
14
+ <p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary mb-2">
15
+ {eyebrow}
16
+ </p>
17
+ <h2 className="text-[clamp(1.75rem,3vw,2.25rem)] font-bold m-0 -tracking-[0.025em]">
18
+ {title}
19
+ </h2>
20
+ {description && (
21
+ <p className="mt-2 text-muted-foreground">{description}</p>
22
+ )}
23
+ </div>
24
+ {link && (
25
+ <Link
26
+ href={link.href}
27
+ className="text-sm font-semibold text-primary hover:underline whitespace-nowrap hidden sm:inline-flex items-center gap-1"
28
+ >
29
+ {link.label}
30
+ <svg viewBox="0 0 12 12" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
31
+ <path d="M3 6h7m0 0L7 3m3 3L7 9" strokeLinecap="round" strokeLinejoin="round" />
32
+ </svg>
33
+ </Link>
34
+ )}
35
+ </div>
36
+ );
37
+ }
@@ -59,22 +59,22 @@ interface Props {
59
59
  }
60
60
 
61
61
  /**
62
- * Variant-aware product card that opens the URL-driven product modal on
63
- * click. Uses `next/link` with `?product=<slug>` so the link is statically
64
- * pre-renderable — no `useSearchParams` dependency means cards don't
65
- * become dynamic islands. The modal (which already reads `useSearchParams`
66
- * inside a Suspense boundary in the root layout) handles the rest.
62
+ * Variant-aware product card that links to the dedicated product page at
63
+ * `/products/<slug>`. Statically pre-renderable (no `useSearchParams`),
64
+ * with `prefetch` enabled so hover → instant nav. Full product page
65
+ * (vs a modal) is the right pattern for retail: spec sheets, multi-image
66
+ * galleries, reviews, comparison rails all need vertical real estate.
67
67
  */
68
68
  export function StoreProductCard({ product, variant }: Props) {
69
69
  const slug = product.slug || product.id;
70
70
  const Card = VARIANT_CARDS[variant ?? resolveVariant(product)];
71
- const href = `?product=${encodeURIComponent(slug)}`;
71
+ const href = `/products/${encodeURIComponent(slug)}`;
72
72
 
73
73
  return (
74
74
  <Card
75
75
  product={product}
76
76
  renderLink={({ className, children }) => (
77
- <Link href={href} scroll={false} prefetch={false} className={className}>
77
+ <Link href={href} className={className}>
78
78
  {children}
79
79
  </Link>
80
80
  )}
@@ -0,0 +1,54 @@
1
+ import Link from "next/link";
2
+ import { brand } from "@/lib/brand";
3
+
4
+ export function TradeInCta() {
5
+ const t = brand.tradeIn;
6
+ if (!t) return null;
7
+ return (
8
+ <section className="max-w-7xl mx-auto px-6 sm:px-8 py-14 sm:py-20">
9
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-8 items-center bg-foreground text-background rounded-3xl p-8 sm:p-12 lg:p-14 overflow-hidden relative">
10
+ <div className="absolute top-0 right-0 w-1/2 h-full opacity-[0.04] [background-image:linear-gradient(135deg,white_1px,transparent_1px)] [background-size:24px_24px] pointer-events-none" />
11
+ <div>
12
+ <p className="text-[11px] font-mono uppercase tracking-[0.16em] text-primary-foreground/70 mb-3">
13
+ {t.eyebrow}
14
+ </p>
15
+ <h2 className="text-[clamp(1.75rem,3.5vw,2.5rem)] font-bold m-0 mb-4 -tracking-[0.025em] leading-[1.1]">
16
+ {t.title}
17
+ </h2>
18
+ <p className="text-background/75 leading-relaxed mb-6">{t.body}</p>
19
+ <div className="flex flex-wrap items-center gap-3">
20
+ <Link
21
+ href={t.primaryCtaHref}
22
+ 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"
23
+ >
24
+ {t.primaryCtaLabel}
25
+ <svg viewBox="0 0 12 12" className="w-3 h-3" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
26
+ <path d="M3 6h7m0 0L7 3m3 3L7 9" strokeLinecap="round" strokeLinejoin="round" />
27
+ </svg>
28
+ </Link>
29
+ <Link
30
+ href={t.secondaryCtaHref}
31
+ className="inline-flex items-center gap-2 px-5 py-2.5 rounded-md border border-background/25 hover:bg-background/10 transition-colors text-sm font-medium"
32
+ >
33
+ {t.secondaryCtaLabel}
34
+ </Link>
35
+ </div>
36
+ </div>
37
+ <div className="grid grid-cols-3 gap-3">
38
+ {t.steps.map((s) => (
39
+ <div
40
+ key={s.step}
41
+ className="rounded-2xl p-4 sm:p-5 bg-background/5 border border-background/10"
42
+ >
43
+ <p className="text-[10px] font-mono text-primary tabular-nums mb-3">{s.step}</p>
44
+ <p className="text-[13px] sm:text-sm font-semibold mb-1.5 -tracking-[0.015em]">
45
+ {s.title}
46
+ </p>
47
+ <p className="text-[11px] sm:text-xs text-background/65 leading-snug">{s.body}</p>
48
+ </div>
49
+ ))}
50
+ </div>
51
+ </div>
52
+ </section>
53
+ );
54
+ }
@@ -0,0 +1,66 @@
1
+ import { brand } from "@/lib/brand";
2
+
3
+ const ICONS: Record<string, React.ReactNode> = {
4
+ delivery: (
5
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" className="w-5 h-5" aria-hidden>
6
+ <path d="M3 7h12v8H3zM15 10h4l3 3v2h-7z" strokeLinejoin="round" />
7
+ <circle cx="7" cy="17" r="1.5" />
8
+ <circle cx="18" cy="17" r="1.5" />
9
+ </svg>
10
+ ),
11
+ warranty: (
12
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" className="w-5 h-5" aria-hidden>
13
+ <path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3z" strokeLinejoin="round" />
14
+ <path d="M9 12l2 2 4-4" strokeLinecap="round" strokeLinejoin="round" />
15
+ </svg>
16
+ ),
17
+ payment: (
18
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" className="w-5 h-5" aria-hidden>
19
+ <rect x="3" y="6" width="18" height="12" rx="2" />
20
+ <line x1="3" y1="10" x2="21" y2="10" />
21
+ </svg>
22
+ ),
23
+ verified: (
24
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" className="w-5 h-5" aria-hidden>
25
+ <circle cx="12" cy="12" r="9" />
26
+ <path d="M8 12l3 3 5-6" strokeLinecap="round" strokeLinejoin="round" />
27
+ </svg>
28
+ ),
29
+ support: (
30
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" className="w-5 h-5" aria-hidden>
31
+ <path d="M18 18a8 8 0 1 0-12 0" />
32
+ <path d="M3 18h4v3H3zM17 18h4v3h-4z" strokeLinejoin="round" />
33
+ </svg>
34
+ ),
35
+ };
36
+
37
+ const FALLBACK_ICON = (
38
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" className="w-5 h-5" aria-hidden>
39
+ <circle cx="12" cy="12" r="9" />
40
+ </svg>
41
+ );
42
+
43
+ export function TrustBar() {
44
+ const items = brand.trustItems;
45
+ if (!items || items.length === 0) return null;
46
+ return (
47
+ <section className="border-y border-border bg-card">
48
+ <div className="max-w-7xl mx-auto px-6 sm:px-8 py-10 grid grid-cols-2 md:grid-cols-4 gap-x-6 gap-y-8">
49
+ {items.map((it) => (
50
+ <div key={it.label} className="flex items-start gap-3">
51
+ <div className="grid place-items-center w-10 h-10 rounded-lg bg-primary/10 text-primary shrink-0">
52
+ {ICONS[it.iconKey] ?? FALLBACK_ICON}
53
+ </div>
54
+ <div className="min-w-0">
55
+ <p className="text-[10px] font-mono uppercase tracking-[0.16em] text-muted-foreground mb-0.5">
56
+ {it.label}
57
+ </p>
58
+ <p className="text-base font-semibold -tracking-[0.015em] mb-0.5">{it.value}</p>
59
+ <p className="text-xs text-muted-foreground leading-snug">{it.description}</p>
60
+ </div>
61
+ </div>
62
+ ))}
63
+ </div>
64
+ </section>
65
+ );
66
+ }