@cogenta/starters 0.3.0 → 0.4.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 (371) hide show
  1. package/dist/blueprints/assets/photos/association/coat-bank.jpg +0 -0
  2. package/dist/blueprints/assets/photos/association/food-bank.jpg +0 -0
  3. package/dist/blueprints/assets/photos/association/garden-corner.jpg +0 -0
  4. package/dist/blueprints/assets/photos/association/garden-planting.jpg +0 -0
  5. package/dist/blueprints/assets/photos/association/hall.jpg +0 -0
  6. package/dist/blueprints/assets/photos/association/hero.jpg +0 -0
  7. package/dist/blueprints/assets/photos/association/homework-club.jpg +0 -0
  8. package/dist/blueprints/assets/photos/association/orientation.jpg +0 -0
  9. package/dist/blueprints/assets/photos/association/partner-fr-college.png +0 -0
  10. package/dist/blueprints/assets/photos/association/partner-fr-delcourt.png +0 -0
  11. package/dist/blueprints/assets/photos/association/partner-fr-fondation.png +0 -0
  12. package/dist/blueprints/assets/photos/association/partner-fr-habitat.png +0 -0
  13. package/dist/blueprints/assets/photos/association/partner-fr-mairie.png +0 -0
  14. package/dist/blueprints/assets/photos/association/partner-fr-pharmacie.png +0 -0
  15. package/dist/blueprints/assets/photos/association/supper.jpg +0 -0
  16. package/dist/blueprints/assets/photos/blog/desk-setup.jpg +0 -0
  17. package/dist/blueprints/assets/photos/blog/library.jpg +0 -0
  18. package/dist/blueprints/assets/photos/blog/notebook-and-coffee.jpg +0 -0
  19. package/dist/blueprints/assets/photos/blog/notebooks.jpg +0 -0
  20. package/dist/blueprints/assets/photos/blog/platform.jpg +0 -0
  21. package/dist/blueprints/assets/photos/blog/pour-over.jpg +0 -0
  22. package/dist/blueprints/assets/photos/blog/typing.jpg +0 -0
  23. package/dist/blueprints/assets/photos/documentation/delivery-flow-en.png +0 -0
  24. package/dist/blueprints/assets/photos/documentation/delivery-flow-fr.png +0 -0
  25. package/dist/blueprints/assets/photos/magazine/allotments.jpg +0 -0
  26. package/dist/blueprints/assets/photos/magazine/archive-stacks.jpg +0 -0
  27. package/dist/blueprints/assets/photos/magazine/baguettes.jpg +0 -0
  28. package/dist/blueprints/assets/photos/magazine/dining-room.jpg +0 -0
  29. package/dist/blueprints/assets/photos/magazine/empty-tram-stop.jpg +0 -0
  30. package/dist/blueprints/assets/photos/magazine/gallery.jpg +0 -0
  31. package/dist/blueprints/assets/photos/magazine/office-block-dusk.jpg +0 -0
  32. package/dist/blueprints/assets/photos/magazine/reading-room.jpg +0 -0
  33. package/dist/blueprints/assets/photos/magazine/reception-hall.jpg +0 -0
  34. package/dist/blueprints/assets/photos/magazine/theatre.jpg +0 -0
  35. package/dist/blueprints/assets/photos/magazine/town-hall.jpg +0 -0
  36. package/dist/blueprints/assets/photos/magazine/tram-stop.jpg +0 -0
  37. package/dist/blueprints/assets/photos/portfolio/coast-boats.jpg +0 -0
  38. package/dist/blueprints/assets/photos/portfolio/coast-cover.jpg +0 -0
  39. package/dist/blueprints/assets/photos/portfolio/coast-ridge.jpg +0 -0
  40. package/dist/blueprints/assets/photos/portfolio/coast-water.jpg +0 -0
  41. package/dist/blueprints/assets/photos/portfolio/forest-beech.jpg +0 -0
  42. package/dist/blueprints/assets/photos/portfolio/forest-birch.jpg +0 -0
  43. package/dist/blueprints/assets/photos/portfolio/forest-branches.jpg +0 -0
  44. package/dist/blueprints/assets/photos/portfolio/forest-cover.jpg +0 -0
  45. package/dist/blueprints/assets/photos/portfolio/glacier-cave.jpg +0 -0
  46. package/dist/blueprints/assets/photos/portfolio/glacier-cover.jpg +0 -0
  47. package/dist/blueprints/assets/photos/portfolio/glacier-melt.jpg +0 -0
  48. package/dist/blueprints/assets/photos/portfolio/glacier-tongue.jpg +0 -0
  49. package/dist/blueprints/assets/photos/portfolio/lagoon-cover.jpg +0 -0
  50. package/dist/blueprints/assets/photos/portfolio/lagoon-egret.jpg +0 -0
  51. package/dist/blueprints/assets/photos/portfolio/lagoon-shore.jpg +0 -0
  52. package/dist/blueprints/assets/photos/portfolio/lagoon-storm.jpg +0 -0
  53. package/dist/blueprints/assets/photos/portfolio/port-cover.jpg +0 -0
  54. package/dist/blueprints/assets/photos/portfolio/port-dusk.jpg +0 -0
  55. package/dist/blueprints/assets/photos/portfolio/port-marina.jpg +0 -0
  56. package/dist/blueprints/assets/photos/portfolio/port-quay.jpg +0 -0
  57. package/dist/blueprints/assets/photos/portfolio/towers-cover.jpg +0 -0
  58. package/dist/blueprints/assets/photos/portfolio/towers-green.jpg +0 -0
  59. package/dist/blueprints/assets/photos/portfolio/towers-single.jpg +0 -0
  60. package/dist/blueprints/assets/photos/portfolio/towers-valley.jpg +0 -0
  61. package/dist/blueprints/assets/photos/portfolio/vines-cover.jpg +0 -0
  62. package/dist/blueprints/assets/photos/portfolio/vines-grapes.jpg +0 -0
  63. package/dist/blueprints/assets/photos/portfolio/vines-shed.jpg +0 -0
  64. package/dist/blueprints/assets/photos/portfolio/vines-tree.jpg +0 -0
  65. package/dist/blueprints/assets/photos/restaurant/beetroot-carpaccio.jpg +0 -0
  66. package/dist/blueprints/assets/photos/restaurant/chocolate-tart.jpg +0 -0
  67. package/dist/blueprints/assets/photos/restaurant/cod-vin-jaune.jpg +0 -0
  68. package/dist/blueprints/assets/photos/restaurant/duck-confit.jpg +0 -0
  69. package/dist/blueprints/assets/photos/restaurant/grilled-octopus.jpg +0 -0
  70. package/dist/blueprints/assets/photos/restaurant/hero.jpg +0 -0
  71. package/dist/blueprints/assets/photos/restaurant/market-stall.jpg +0 -0
  72. package/dist/blueprints/assets/photos/restaurant/mushroom-risotto.jpg +0 -0
  73. package/dist/blueprints/assets/photos/restaurant/pike-quenelle.jpg +0 -0
  74. package/dist/blueprints/assets/photos/restaurant/poached-pear.jpg +0 -0
  75. package/dist/blueprints/assets/photos/restaurant/praline-cake.jpg +0 -0
  76. package/dist/blueprints/assets/photos/restaurant/pumpkin-soup.jpg +0 -0
  77. package/dist/blueprints/assets/photos/restaurant/street-burdeau.jpg +0 -0
  78. package/dist/blueprints/assets/photos/saas/api-webhooks-en.png +0 -0
  79. package/dist/blueprints/assets/photos/saas/api-webhooks-fr.png +0 -0
  80. package/dist/blueprints/assets/photos/saas/approvals-queue-en.png +0 -0
  81. package/dist/blueprints/assets/photos/saas/approvals-queue-fr.png +0 -0
  82. package/dist/blueprints/assets/photos/saas/audit-log-en.png +0 -0
  83. package/dist/blueprints/assets/photos/saas/audit-log-fr.png +0 -0
  84. package/dist/blueprints/assets/photos/saas/erp-sync-en.png +0 -0
  85. package/dist/blueprints/assets/photos/saas/erp-sync-fr.png +0 -0
  86. package/dist/blueprints/assets/photos/saas/logo-castellan-alimentaire.png +0 -0
  87. package/dist/blueprints/assets/photos/saas/logo-cliniques-du-vivier.png +0 -0
  88. package/dist/blueprints/assets/photos/saas/logo-marenne-logistique.png +0 -0
  89. package/dist/blueprints/assets/photos/saas/logo-nordgate-habitat.png +0 -0
  90. package/dist/blueprints/assets/photos/saas/logo-tessaly-energies.png +0 -0
  91. package/dist/blueprints/assets/photos/saas/office-london.jpg +0 -0
  92. package/dist/blueprints/assets/photos/saas/office-montreal.jpg +0 -0
  93. package/dist/blueprints/assets/photos/saas/office-paris.jpg +0 -0
  94. package/dist/blueprints/assets/photos/saas/office-toronto.jpg +0 -0
  95. package/dist/blueprints/assets/photos/saas/policy-editor-en.png +0 -0
  96. package/dist/blueprints/assets/photos/saas/policy-editor-fr.png +0 -0
  97. package/dist/blueprints/assets/photos/saas/security-racks.jpg +0 -0
  98. package/dist/blueprints/assets/photos/saas/spend-reporting-en.png +0 -0
  99. package/dist/blueprints/assets/photos/saas/spend-reporting-fr.png +0 -0
  100. package/dist/blueprints/assets/photos/saas/sso-scim-en.png +0 -0
  101. package/dist/blueprints/assets/photos/saas/sso-scim-fr.png +0 -0
  102. package/dist/blueprints/assets/photos/store/aleppo-soap.jpg +0 -0
  103. package/dist/blueprints/assets/photos/store/copper-pan.jpg +0 -0
  104. package/dist/blueprints/assets/photos/store/crochet-throw.jpg +0 -0
  105. package/dist/blueprints/assets/photos/store/enamel-mug.jpg +0 -0
  106. package/dist/blueprints/assets/photos/store/hero.jpg +0 -0
  107. package/dist/blueprints/assets/photos/store/knit-sweater.jpg +0 -0
  108. package/dist/blueprints/assets/photos/store/leather-boots.jpg +0 -0
  109. package/dist/blueprints/assets/photos/store/leather-duffel.jpg +0 -0
  110. package/dist/blueprints/assets/photos/store/leather-wallet.jpg +0 -0
  111. package/dist/blueprints/assets/photos/store/moka-pot.jpg +0 -0
  112. package/dist/blueprints/assets/photos/store/skillet.jpg +0 -0
  113. package/dist/blueprints/assets/photos/store/stoneware-bottles.jpg +0 -0
  114. package/dist/blueprints/assets/photos/store/story.jpg +0 -0
  115. package/dist/blueprints/assets/photos/store/turned-bowl.jpg +0 -0
  116. package/dist/blueprints/association-copy-en.d.ts +3 -0
  117. package/dist/blueprints/association-copy-en.d.ts.map +1 -0
  118. package/dist/blueprints/association-copy-en.js +834 -0
  119. package/dist/blueprints/association-copy-en.js.map +1 -0
  120. package/dist/blueprints/association-copy-fr.d.ts +3 -0
  121. package/dist/blueprints/association-copy-fr.d.ts.map +1 -0
  122. package/dist/blueprints/association-copy-fr.js +841 -0
  123. package/dist/blueprints/association-copy-fr.js.map +1 -0
  124. package/dist/blueprints/association-copy.d.ts +301 -0
  125. package/dist/blueprints/association-copy.d.ts.map +1 -0
  126. package/dist/blueprints/association-copy.js +17 -0
  127. package/dist/blueprints/association-copy.js.map +1 -0
  128. package/dist/blueprints/association-credits.d.ts +16 -0
  129. package/dist/blueprints/association-credits.d.ts.map +1 -0
  130. package/dist/blueprints/association-credits.js +80 -0
  131. package/dist/blueprints/association-credits.js.map +1 -0
  132. package/dist/blueprints/association-typography.d.ts +23 -0
  133. package/dist/blueprints/association-typography.d.ts.map +1 -0
  134. package/dist/blueprints/association-typography.js +55 -0
  135. package/dist/blueprints/association-typography.js.map +1 -0
  136. package/dist/blueprints/association.d.ts +86 -287
  137. package/dist/blueprints/association.d.ts.map +1 -1
  138. package/dist/blueprints/association.js +503 -1078
  139. package/dist/blueprints/association.js.map +1 -1
  140. package/dist/blueprints/blog-copy-en.d.ts +4 -0
  141. package/dist/blueprints/blog-copy-en.d.ts.map +1 -0
  142. package/dist/blueprints/blog-copy-en.js +701 -0
  143. package/dist/blueprints/blog-copy-en.js.map +1 -0
  144. package/dist/blueprints/blog-copy-fr.d.ts +12 -0
  145. package/dist/blueprints/blog-copy-fr.d.ts.map +1 -0
  146. package/dist/blueprints/blog-copy-fr.js +722 -0
  147. package/dist/blueprints/blog-copy-fr.js.map +1 -0
  148. package/dist/blueprints/blog-copy.d.ts +157 -0
  149. package/dist/blueprints/blog-copy.d.ts.map +1 -0
  150. package/dist/blueprints/blog-copy.js +2 -0
  151. package/dist/blueprints/blog-copy.js.map +1 -0
  152. package/dist/blueprints/blog-credits.d.ts +28 -0
  153. package/dist/blueprints/blog-credits.d.ts.map +1 -0
  154. package/dist/blueprints/blog-credits.js +73 -0
  155. package/dist/blueprints/blog-credits.js.map +1 -0
  156. package/dist/blueprints/blog-rich.d.ts +19 -0
  157. package/dist/blueprints/blog-rich.d.ts.map +1 -0
  158. package/dist/blueprints/blog-rich.js +51 -0
  159. package/dist/blueprints/blog-rich.js.map +1 -0
  160. package/dist/blueprints/blog.d.ts +51 -176
  161. package/dist/blueprints/blog.d.ts.map +1 -1
  162. package/dist/blueprints/blog.js +358 -947
  163. package/dist/blueprints/blog.js.map +1 -1
  164. package/dist/blueprints/content-pack.d.ts.map +1 -1
  165. package/dist/blueprints/content-pack.js +11 -16
  166. package/dist/blueprints/content-pack.js.map +1 -1
  167. package/dist/blueprints/content-packs.d.ts +2 -4
  168. package/dist/blueprints/content-packs.d.ts.map +1 -1
  169. package/dist/blueprints/content-packs.js +27 -15
  170. package/dist/blueprints/content-packs.js.map +1 -1
  171. package/dist/blueprints/documentation-copy-en.d.ts +3 -0
  172. package/dist/blueprints/documentation-copy-en.d.ts.map +1 -0
  173. package/dist/blueprints/documentation-copy-en.js +883 -0
  174. package/dist/blueprints/documentation-copy-en.js.map +1 -0
  175. package/dist/blueprints/documentation-copy-fr.d.ts +3 -0
  176. package/dist/blueprints/documentation-copy-fr.d.ts.map +1 -0
  177. package/dist/blueprints/documentation-copy-fr.js +939 -0
  178. package/dist/blueprints/documentation-copy-fr.js.map +1 -0
  179. package/dist/blueprints/documentation-copy.d.ts +52 -0
  180. package/dist/blueprints/documentation-copy.d.ts.map +1 -0
  181. package/dist/blueprints/documentation-copy.js +2 -0
  182. package/dist/blueprints/documentation-copy.js.map +1 -0
  183. package/dist/blueprints/documentation-writer.d.ts +67 -0
  184. package/dist/blueprints/documentation-writer.d.ts.map +1 -0
  185. package/dist/blueprints/documentation-writer.js +190 -0
  186. package/dist/blueprints/documentation-writer.js.map +1 -0
  187. package/dist/blueprints/documentation.d.ts +26 -29
  188. package/dist/blueprints/documentation.d.ts.map +1 -1
  189. package/dist/blueprints/documentation.js +106 -1064
  190. package/dist/blueprints/documentation.js.map +1 -1
  191. package/dist/blueprints/magazine-copy-en.d.ts +13 -0
  192. package/dist/blueprints/magazine-copy-en.d.ts.map +1 -0
  193. package/dist/blueprints/magazine-copy-en.js +553 -0
  194. package/dist/blueprints/magazine-copy-en.js.map +1 -0
  195. package/dist/blueprints/magazine-copy-fr.d.ts +14 -0
  196. package/dist/blueprints/magazine-copy-fr.d.ts.map +1 -0
  197. package/dist/blueprints/magazine-copy-fr.js +568 -0
  198. package/dist/blueprints/magazine-copy-fr.js.map +1 -0
  199. package/dist/blueprints/magazine-copy.d.ts +166 -0
  200. package/dist/blueprints/magazine-copy.d.ts.map +1 -0
  201. package/dist/blueprints/magazine-copy.js +58 -0
  202. package/dist/blueprints/magazine-copy.js.map +1 -0
  203. package/dist/blueprints/magazine-credits.d.ts +19 -0
  204. package/dist/blueprints/magazine-credits.d.ts.map +1 -0
  205. package/dist/blueprints/magazine-credits.js +109 -0
  206. package/dist/blueprints/magazine-credits.js.map +1 -0
  207. package/dist/blueprints/magazine.d.ts +30 -78
  208. package/dist/blueprints/magazine.d.ts.map +1 -1
  209. package/dist/blueprints/magazine.js +269 -690
  210. package/dist/blueprints/magazine.js.map +1 -1
  211. package/dist/blueprints/portfolio-copy-en.d.ts +4 -0
  212. package/dist/blueprints/portfolio-copy-en.d.ts.map +1 -0
  213. package/dist/blueprints/portfolio-copy-en.js +745 -0
  214. package/dist/blueprints/portfolio-copy-en.js.map +1 -0
  215. package/dist/blueprints/portfolio-copy-fr.d.ts +9 -0
  216. package/dist/blueprints/portfolio-copy-fr.d.ts.map +1 -0
  217. package/dist/blueprints/portfolio-copy-fr.js +737 -0
  218. package/dist/blueprints/portfolio-copy-fr.js.map +1 -0
  219. package/dist/blueprints/portfolio-copy.d.ts +204 -0
  220. package/dist/blueprints/portfolio-copy.d.ts.map +1 -0
  221. package/dist/blueprints/portfolio-copy.js +15 -0
  222. package/dist/blueprints/portfolio-copy.js.map +1 -0
  223. package/dist/blueprints/portfolio-credits.d.ts +18 -0
  224. package/dist/blueprints/portfolio-credits.d.ts.map +1 -0
  225. package/dist/blueprints/portfolio-credits.js +239 -0
  226. package/dist/blueprints/portfolio-credits.js.map +1 -0
  227. package/dist/blueprints/portfolio-typography.d.ts +19 -0
  228. package/dist/blueprints/portfolio-typography.d.ts.map +1 -0
  229. package/dist/blueprints/portfolio-typography.js +41 -0
  230. package/dist/blueprints/portfolio-typography.js.map +1 -0
  231. package/dist/blueprints/portfolio.d.ts +68 -157
  232. package/dist/blueprints/portfolio.d.ts.map +1 -1
  233. package/dist/blueprints/portfolio.js +475 -727
  234. package/dist/blueprints/portfolio.js.map +1 -1
  235. package/dist/blueprints/restaurant-copy-en.d.ts +3 -0
  236. package/dist/blueprints/restaurant-copy-en.d.ts.map +1 -0
  237. package/dist/blueprints/restaurant-copy-en.js +641 -0
  238. package/dist/blueprints/restaurant-copy-en.js.map +1 -0
  239. package/dist/blueprints/restaurant-copy-fr.d.ts +3 -0
  240. package/dist/blueprints/restaurant-copy-fr.d.ts.map +1 -0
  241. package/dist/blueprints/restaurant-copy-fr.js +665 -0
  242. package/dist/blueprints/restaurant-copy-fr.js.map +1 -0
  243. package/dist/blueprints/restaurant-copy.d.ts +234 -0
  244. package/dist/blueprints/restaurant-copy.d.ts.map +1 -0
  245. package/dist/blueprints/restaurant-copy.js +15 -0
  246. package/dist/blueprints/restaurant-copy.js.map +1 -0
  247. package/dist/blueprints/restaurant-credits.d.ts +18 -0
  248. package/dist/blueprints/restaurant-credits.d.ts.map +1 -0
  249. package/dist/blueprints/restaurant-credits.js +121 -0
  250. package/dist/blueprints/restaurant-credits.js.map +1 -0
  251. package/dist/blueprints/restaurant.d.ts +55 -128
  252. package/dist/blueprints/restaurant.d.ts.map +1 -1
  253. package/dist/blueprints/restaurant.js +425 -770
  254. package/dist/blueprints/restaurant.js.map +1 -1
  255. package/dist/blueprints/saas-copy-en.d.ts +3 -0
  256. package/dist/blueprints/saas-copy-en.d.ts.map +1 -0
  257. package/dist/blueprints/saas-copy-en.js +901 -0
  258. package/dist/blueprints/saas-copy-en.js.map +1 -0
  259. package/dist/blueprints/saas-copy-fr.d.ts +3 -0
  260. package/dist/blueprints/saas-copy-fr.d.ts.map +1 -0
  261. package/dist/blueprints/saas-copy-fr.js +912 -0
  262. package/dist/blueprints/saas-copy-fr.js.map +1 -0
  263. package/dist/blueprints/saas-copy.d.ts +266 -0
  264. package/dist/blueprints/saas-copy.d.ts.map +1 -0
  265. package/dist/blueprints/saas-copy.js +18 -0
  266. package/dist/blueprints/saas-copy.js.map +1 -0
  267. package/dist/blueprints/saas-credits.d.ts +22 -0
  268. package/dist/blueprints/saas-credits.d.ts.map +1 -0
  269. package/dist/blueprints/saas-credits.js +44 -0
  270. package/dist/blueprints/saas-credits.js.map +1 -0
  271. package/dist/blueprints/saas.d.ts +59 -203
  272. package/dist/blueprints/saas.d.ts.map +1 -1
  273. package/dist/blueprints/saas.js +505 -1108
  274. package/dist/blueprints/saas.js.map +1 -1
  275. package/dist/blueprints/store-copy-en.d.ts +4 -0
  276. package/dist/blueprints/store-copy-en.d.ts.map +1 -0
  277. package/dist/blueprints/store-copy-en.js +521 -0
  278. package/dist/blueprints/store-copy-en.js.map +1 -0
  279. package/dist/blueprints/store-copy-fr.d.ts +4 -0
  280. package/dist/blueprints/store-copy-fr.d.ts.map +1 -0
  281. package/dist/blueprints/store-copy-fr.js +521 -0
  282. package/dist/blueprints/store-copy-fr.js.map +1 -0
  283. package/dist/blueprints/store-copy.d.ts +219 -0
  284. package/dist/blueprints/store-copy.d.ts.map +1 -0
  285. package/dist/blueprints/store-copy.js +16 -0
  286. package/dist/blueprints/store-copy.js.map +1 -0
  287. package/dist/blueprints/store-credits.d.ts +3 -0
  288. package/dist/blueprints/store-credits.d.ts.map +1 -0
  289. package/dist/blueprints/store-credits.js +117 -0
  290. package/dist/blueprints/store-credits.js.map +1 -0
  291. package/dist/blueprints/store.d.ts +43 -231
  292. package/dist/blueprints/store.d.ts.map +1 -1
  293. package/dist/blueprints/store.js +466 -789
  294. package/dist/blueprints/store.js.map +1 -1
  295. package/dist/blueprints/vitrine-copy-en.d.ts.map +1 -1
  296. package/dist/blueprints/vitrine-copy-en.js +1 -0
  297. package/dist/blueprints/vitrine-copy-en.js.map +1 -1
  298. package/dist/blueprints/vitrine-copy-fr.d.ts.map +1 -1
  299. package/dist/blueprints/vitrine-copy-fr.js +1 -0
  300. package/dist/blueprints/vitrine-copy-fr.js.map +1 -1
  301. package/dist/blueprints/vitrine-copy.d.ts +1 -0
  302. package/dist/blueprints/vitrine-copy.d.ts.map +1 -1
  303. package/dist/blueprints/vitrine.d.ts +1 -0
  304. package/dist/blueprints/vitrine.d.ts.map +1 -1
  305. package/dist/blueprints/vitrine.js +24 -3
  306. package/dist/blueprints/vitrine.js.map +1 -1
  307. package/package.json +10 -10
  308. package/dist/blueprints/assets/photos/association/fundraising-dinner.jpg +0 -0
  309. package/dist/blueprints/assets/photos/association/volunteer-orientation.jpg +0 -0
  310. package/dist/blueprints/assets/photos/association/volunteer-portrait.jpg +0 -0
  311. package/dist/blueprints/assets/photos/association/winter-coat-collection.jpg +0 -0
  312. package/dist/blueprints/assets/photos/documentation/delivery-flow.png +0 -0
  313. package/dist/blueprints/assets/photos/magazine/archive-room.jpg +0 -0
  314. package/dist/blueprints/assets/photos/magazine/banquet-hall.jpg +0 -0
  315. package/dist/blueprints/assets/photos/magazine/city-hall.jpg +0 -0
  316. package/dist/blueprints/assets/photos/magazine/downtown-towers.jpg +0 -0
  317. package/dist/blueprints/assets/photos/magazine/gallery-opening.jpg +0 -0
  318. package/dist/blueprints/assets/photos/magazine/garden-volunteers.jpg +0 -0
  319. package/dist/blueprints/assets/photos/magazine/station-platform.jpg +0 -0
  320. package/dist/blueprints/assets/photos/magazine/theater-stage.jpg +0 -0
  321. package/dist/blueprints/assets/photos/portfolio/fenmore-branch.jpg +0 -0
  322. package/dist/blueprints/assets/photos/portfolio/fenmore-cover.jpg +0 -0
  323. package/dist/blueprints/assets/photos/portfolio/fenmore-stationery.jpg +0 -0
  324. package/dist/blueprints/assets/photos/portfolio/gannet-cover.jpg +0 -0
  325. package/dist/blueprints/assets/photos/portfolio/gannet-sardines.jpg +0 -0
  326. package/dist/blueprints/assets/photos/portfolio/gannet-shelf.jpg +0 -0
  327. package/dist/blueprints/assets/photos/portfolio/hollis-crane-cover.jpg +0 -0
  328. package/dist/blueprints/assets/photos/portfolio/hollis-crane-grid.jpg +0 -0
  329. package/dist/blueprints/assets/photos/portfolio/hollis-crane-salt-year.jpg +0 -0
  330. package/dist/blueprints/assets/photos/portfolio/hollis-crane-spines.jpg +0 -0
  331. package/dist/blueprints/assets/photos/portfolio/rookery-hall-brochure.jpg +0 -0
  332. package/dist/blueprints/assets/photos/portfolio/rookery-hall-cover.jpg +0 -0
  333. package/dist/blueprints/assets/photos/portfolio/rookery-hall-poster-carnival.jpg +0 -0
  334. package/dist/blueprints/assets/photos/portfolio/rookery-hall-poster-sibelius.jpg +0 -0
  335. package/dist/blueprints/assets/photos/portfolio/rookery-hall-series.jpg +0 -0
  336. package/dist/blueprints/assets/photos/portfolio/saltmarsh-quay-cover.jpg +0 -0
  337. package/dist/blueprints/assets/photos/portfolio/saltmarsh-quay-gate.jpg +0 -0
  338. package/dist/blueprints/assets/photos/portfolio/saltmarsh-quay-pictograms.jpg +0 -0
  339. package/dist/blueprints/assets/photos/portfolio/saltmarsh-quay-totem.jpg +0 -0
  340. package/dist/blueprints/assets/photos/portfolio/tidewater-cover.jpg +0 -0
  341. package/dist/blueprints/assets/photos/portfolio/tidewater-data.jpg +0 -0
  342. package/dist/blueprints/assets/photos/portfolio/tidewater-report-cover.jpg +0 -0
  343. package/dist/blueprints/assets/photos/portfolio/warp-and-weft-cover.jpg +0 -0
  344. package/dist/blueprints/assets/photos/portfolio/warp-and-weft-room.jpg +0 -0
  345. package/dist/blueprints/assets/photos/portfolio/westmoor-rail-components.jpg +0 -0
  346. package/dist/blueprints/assets/photos/portfolio/westmoor-rail-cover.jpg +0 -0
  347. package/dist/blueprints/assets/photos/portfolio/westmoor-rail-departures.jpg +0 -0
  348. package/dist/blueprints/assets/photos/restaurant/beetroot-goats-curd.jpg +0 -0
  349. package/dist/blueprints/assets/photos/restaurant/ceps-risotto.jpg +0 -0
  350. package/dist/blueprints/assets/photos/restaurant/duck-leg-red-cabbage.jpg +0 -0
  351. package/dist/blueprints/assets/photos/restaurant/hake-green-peppercorns.jpg +0 -0
  352. package/dist/blueprints/assets/photos/restaurant/vegetable-broth.jpg +0 -0
  353. package/dist/blueprints/assets/photos/saas/adrian-tan.jpg +0 -0
  354. package/dist/blueprints/assets/photos/saas/api-webhooks.png +0 -0
  355. package/dist/blueprints/assets/photos/saas/approvals-queue.png +0 -0
  356. package/dist/blueprints/assets/photos/saas/audit-log.png +0 -0
  357. package/dist/blueprints/assets/photos/saas/erp-sync.png +0 -0
  358. package/dist/blueprints/assets/photos/saas/policy-editor.png +0 -0
  359. package/dist/blueprints/assets/photos/saas/spend-reporting.png +0 -0
  360. package/dist/blueprints/assets/photos/saas/sso-scim.png +0 -0
  361. package/dist/blueprints/assets/photos/store/brushed-cotton-overshirt.jpg +0 -0
  362. package/dist/blueprints/assets/photos/store/cable-knit-beanie.jpg +0 -0
  363. package/dist/blueprints/assets/photos/store/canvas-shoulder-bag.jpg +0 -0
  364. package/dist/blueprints/assets/photos/store/canvas-tote.jpg +0 -0
  365. package/dist/blueprints/assets/photos/store/cast-iron-skillet.jpg +0 -0
  366. package/dist/blueprints/assets/photos/store/field-jacket.jpg +0 -0
  367. package/dist/blueprints/assets/photos/store/heavyweight-t-shirt.jpg +0 -0
  368. package/dist/blueprints/assets/photos/store/leather-card-holder.jpg +0 -0
  369. package/dist/blueprints/assets/photos/store/linen-table-runner.jpg +0 -0
  370. package/dist/blueprints/assets/photos/store/porcelain-pour-over-set.jpg +0 -0
  371. package/dist/blueprints/assets/photos/store/striped-wool-blanket.jpg +0 -0
@@ -3,13 +3,22 @@ import { createContentStore, defineCollection, f, validateCollectionSet, } from
3
3
  import { coverArt, heroArt, productArt } from '../demo-art/compositions.js';
4
4
  import { definePageCollection, SEO_FIELDS, toBlockZoneEntry, } from './content-pack.js';
5
5
  import { STARTING_SKINS } from './starting-skins.js';
6
+ import { STORE_COPY_EN } from './store-copy-en.js';
7
+ import { STORE_COPY_FR } from './store-copy-fr.js';
8
+ import { STORE_PHOTO_CREDITS } from './store-credits.js';
6
9
  /**
7
- * The `store` blueprint (L27, `@cogenta/theme-ecommerce`): a small brand of
8
- * durable everyday goods with a shop and a repair bench in Lisbon, twelve
9
- * products from the workshops it buys from, four categories, and the pages a
10
- * real shop needs before it takes an order (how to order, delivery and
10
+ * The `store` blueprint (L27, `@cogenta/theme-ecommerce`): a small shop in
11
+ * Lyon of durable everyday goods with a repair bench behind the counter,
12
+ * twelve products from the workshops it buys from, three departments, and the
13
+ * pages a real shop needs before it takes an order (how to order, delivery and
11
14
  * returns, repairs, contact, terms).
12
15
  *
16
+ * Written in French and in English, not translated at render time: the
17
+ * installer picks the copy for the site's default locale, and with it the
18
+ * addresses (`/boutique/…` in French, `/shop/…` in English), the names the
19
+ * administration shows and every word of demo content. Every photograph is a
20
+ * real one under an open licence, credited on its own page.
21
+ *
13
22
  * **Contract A only, and no checkout.** A blueprint writes
14
23
  * `cogenta.schema.mjs` and seeds content; it cannot provision
15
24
  * `@cogenta/commerce`'s tables (contract E, ADR-0024), and contract B has no
@@ -27,7 +36,10 @@ import { STARTING_SKINS } from './starting-skins.js';
27
36
  * list filters on and what the product page prints.
28
37
  */
29
38
  export const DEFAULT_SHOP_NAME = 'Atelier Goods';
30
- const CATEGORY_NAMES = ['Wear', 'Carry', 'Kitchen', 'Living'];
39
+ /** The copy for a site's default locale: French for any `fr*` locale, English otherwise. */
40
+ export function storeCopyFor(locale) {
41
+ return locale.toLowerCase().startsWith('fr') ? STORE_COPY_FR : STORE_COPY_EN;
42
+ }
31
43
  const CURRENCIES = ['EUR', 'GBP', 'CHF', 'DKK', 'SEK', 'USD'];
32
44
  const PERMISSIONS = {
33
45
  read: ['public'],
@@ -36,65 +48,65 @@ const PERMISSIONS = {
36
48
  delete: ['admin'],
37
49
  publish: ['admin'],
38
50
  };
39
- export const product = defineCollection({
40
- name: 'product',
41
- labels: { singular: 'Product', plural: 'Products' },
42
- routing: { pattern: '/shop/:slug' },
43
- fields: {
44
- name: f.text({ required: true, max: 120 }),
45
- slug: f.slug({ from: 'name', unique: true }),
46
- description: f.text({
47
- max: 300,
48
- multiline: true,
49
- admin: { label: 'Short description', help: 'Shown beside the price on the product page.' },
50
- }),
51
- price: f.number({ required: true, min: 0 }),
52
- currency: f.select({ options: [...CURRENCIES], default: 'EUR' }),
53
- category: f.select({ options: [...CATEGORY_NAMES], required: true }),
54
- inStock: f.boolean({ default: true, admin: { label: 'In stock' } }),
55
- material: f.text({ max: 200 }),
56
- dimensions: f.text({ max: 200 }),
57
- weight: f.text({ max: 60 }),
58
- capacity: f.text({ max: 60 }),
59
- origin: f.text({ max: 160, admin: { label: 'Made in' } }),
60
- care: f.text({ max: 300, multiline: true }),
61
- delivery: f.text({
62
- max: 300,
63
- multiline: true,
64
- admin: { label: 'Delivery note', help: 'One or two sentences under the order button.' },
65
- }),
66
- orderLink: f.text({
67
- max: 400,
68
- admin: {
69
- label: 'Where to order',
70
- help: 'An email link (mailto:), a payment link or a marketplace page. The product page shows it as the order button.',
71
- },
72
- }),
73
- photo: f.media({ accept: ['image'] }),
74
- blocks: f.blocks(),
75
- ...SEO_FIELDS,
76
- },
77
- indexes: [['slug'], ['category']],
78
- permissions: PERMISSIONS,
79
- });
80
- export const category = defineCollection({
81
- name: 'category',
82
- labels: { singular: 'Category', plural: 'Categories' },
83
- routing: { pattern: '/category/:slug' },
84
- fields: {
85
- name: f.text({ required: true, max: 80 }),
86
- slug: f.slug({ from: 'name', unique: true }),
87
- summary: f.text({ max: 240, multiline: true }),
88
- photo: f.media({ accept: ['image'] }),
89
- blocks: f.blocks(),
90
- ...SEO_FIELDS,
91
- },
92
- indexes: [['slug']],
93
- permissions: PERMISSIONS,
94
- });
95
- export const page = definePageCollection('/:slug');
96
- export const STORE_COLLECTIONS = [product, category, page];
97
- validateCollectionSet(STORE_COLLECTIONS);
51
+ /** The content model, named and routed in the copy's language. */
52
+ export function storeSchema(copy) {
53
+ const product = defineCollection({
54
+ name: 'product',
55
+ versioning: { drafts: true, history: true },
56
+ labels: copy.schema.labels.product,
57
+ routing: { pattern: copy.schema.routes.product },
58
+ fields: {
59
+ name: f.text({ required: true, max: 120 }),
60
+ slug: f.slug({ from: 'name', unique: true }),
61
+ description: f.text({ max: 300, multiline: true }),
62
+ price: f.number({ required: true, min: 0 }),
63
+ currency: f.select({ options: [...CURRENCIES], default: 'EUR' }),
64
+ category: f.select({
65
+ options: copy.categories.map((entry) => entry.name),
66
+ required: true,
67
+ }),
68
+ inStock: f.boolean({ default: true }),
69
+ material: f.text({ max: 200 }),
70
+ dimensions: f.text({ max: 200 }),
71
+ weight: f.text({ max: 60 }),
72
+ capacity: f.text({ max: 60 }),
73
+ origin: f.text({ max: 160 }),
74
+ care: f.text({ max: 300, multiline: true }),
75
+ delivery: f.text({ max: 300, multiline: true }),
76
+ orderLink: f.text({ max: 400 }),
77
+ photo: f.media({ accept: ['image'] }),
78
+ blocks: f.blocks(),
79
+ ...SEO_FIELDS,
80
+ },
81
+ indexes: [['slug'], ['category']],
82
+ permissions: PERMISSIONS,
83
+ });
84
+ const category = defineCollection({
85
+ name: 'category',
86
+ versioning: { drafts: true, history: true },
87
+ labels: copy.schema.labels.category,
88
+ routing: { pattern: copy.schema.routes.category },
89
+ fields: {
90
+ name: f.text({ required: true, max: 80 }),
91
+ slug: f.slug({ from: 'name', unique: true }),
92
+ summary: f.text({ max: 240, multiline: true }),
93
+ photo: f.media({ accept: ['image'] }),
94
+ blocks: f.blocks(),
95
+ ...SEO_FIELDS,
96
+ },
97
+ indexes: [['slug']],
98
+ permissions: PERMISSIONS,
99
+ });
100
+ const page = definePageCollection('/:slug');
101
+ const collections = [product, category, page];
102
+ validateCollectionSet(collections);
103
+ return { product, category, page, collections };
104
+ }
105
+ const ENGLISH_SCHEMA = storeSchema(STORE_COPY_EN);
106
+ export const product = ENGLISH_SCHEMA.product;
107
+ export const category = ENGLISH_SCHEMA.category;
108
+ export const page = ENGLISH_SCHEMA.page;
109
+ export const STORE_COLLECTIONS = ENGLISH_SCHEMA.collections;
98
110
  const BLOCK_VERSION = '1.0.0';
99
111
  // ---------------------------------------------------------------------------
100
112
  // Copy helpers
@@ -112,6 +124,16 @@ function nameOf(siteName) {
112
124
  const trimmed = siteName?.trim();
113
125
  return trimmed === undefined || trimmed === '' ? DEFAULT_SHOP_NAME : trimmed;
114
126
  }
127
+ function factsOf(siteName) {
128
+ const name = nameOf(siteName);
129
+ return {
130
+ name,
131
+ hello: shopEmail(name),
132
+ orders: shopEmail(name, 'orders'),
133
+ repairs: shopEmail(name, 'repairs'),
134
+ letters: shopEmail(name, 'letters'),
135
+ };
136
+ }
115
137
  /**
116
138
  * A paragraph where `[words](href)` becomes a link. Nothing else is
117
139
  * interpreted: the copy stays plain text a person can read in this file.
@@ -156,270 +178,17 @@ function questions(key, items) {
156
178
  answer: answer(`${key}-${index}-a`, text),
157
179
  }));
158
180
  }
159
- const SHIPS = 'Ships from Lisbon within two working days. Free returns within 30 days.';
160
- /**
161
- * Twelve products, three per category and two sold out, written oldest
162
- * first: the newest four (the jacket, the shoulder bag, the pour-over set and
163
- * the blanket) open the home page's grid. Each photograph is the product it
164
- * names, and every material, size and origin matches what the picture shows.
165
- */
166
- export const STORE_DEMO_PRODUCTS = [
167
- {
168
- name: 'Linen table runner',
169
- slug: 'linen-table-runner',
170
- category: 'Living',
171
- price: 68,
172
- inStock: false,
173
- description: 'A long runner in washed white linen with knotted fringes, woven narrow enough to leave room for plates on either side.',
174
- material: 'Linen, stone washed.',
175
- dimensions: '45 × 200 cm, fringes included.',
176
- origin: 'Guimarães, Portugal',
177
- care: 'Wash at 40 °C and line dry. Linen looks best a little creased.',
178
- delivery: 'The next weaving is due in April. Write to us and we will keep one aside for you.',
179
- story: [
180
- 'Woven in Guimarães from flax grown in Normandy and spun in the north of Portugal. The ends are left to fray for a few centimetres and then knotted by hand, so there is no hem to pucker in the wash.',
181
- 'Stone washing softens the cloth before it reaches you. It turns whiter and more supple each time it is washed, and red wine comes out with cold water if you get to it the same evening.',
182
- ],
183
- },
184
- {
185
- name: 'Enamel mug',
186
- slug: 'enamel-mug',
187
- category: 'Kitchen',
188
- price: 24,
189
- inStock: true,
190
- description: 'A 350 ml mug in forest green enamel over steel, with a rolled stainless rim. Light enough for a rucksack and good enough for the table.',
191
- material: 'Enamelled steel, stainless steel rim.',
192
- capacity: '350 ml',
193
- dimensions: '8.5 cm across, 8 cm high.',
194
- origin: 'Olkusz, Poland',
195
- care: 'Dishwasher safe. A chip in the enamel does not spread, so keep using it.',
196
- delivery: SHIPS,
197
- story: [
198
- 'Pressed and enamelled in Olkusz, a town that has made enamelware since the beginning of the last century. Each mug is dipped twice and fired at 800 °C, which gives the green its depth and a surface that coffee will not stain.',
199
- 'It can go on a camping stove and in the oven. We drink from these at the shop counter every morning, and some of ours have been in daily use for six years.',
200
- ],
201
- },
202
- {
203
- name: 'Cable-knit beanie',
204
- slug: 'cable-knit-beanie',
205
- category: 'Wear',
206
- price: 42,
207
- inStock: true,
208
- description: 'A deep, loose beanie in charcoal lambswool with a wide turn-up. Knitted on hand-flat machines and finished by hand.',
209
- material: 'Lambswool, charcoal melange.',
210
- dimensions: 'One size, 28 cm high unfolded.',
211
- origin: 'Covilhã, Portugal',
212
- care: 'Hand wash cold with wool soap and dry flat on a towel.',
213
- delivery: SHIPS,
214
- story: [
215
- 'Knitted in Covilhã, a town that once ran on its wool mills and still has a handful of knitters working hand-flat machines. The cable is set loose, so the hat rests on the head instead of gripping it.',
216
- 'Lambswool pills a little in the first weeks of wear. A wool comb takes it off, and the hat stays soft for years afterwards.',
217
- ],
218
- },
219
- {
220
- name: 'Canvas tote',
221
- slug: 'canvas-tote',
222
- category: 'Carry',
223
- price: 48,
224
- inStock: true,
225
- description: 'An undyed cotton canvas tote with handles long enough to wear over a coat. It stands up on its own and carries a week of shopping.',
226
- material: 'Cotton canvas, 14 oz, undyed.',
227
- dimensions: '38 × 42 × 12 cm. Handles 62 cm.',
228
- origin: 'Lisbon, Portugal',
229
- care: 'Machine wash cold, reshape while damp and dry flat. It softens and shrinks slightly.',
230
- delivery: SHIPS,
231
- story: [
232
- 'The first thing we ever made, and still the thing we sell most of. The body is one piece of canvas folded at the base, so there is no seam along the bottom to split, and the handles run down both sides to carry the weight.',
233
- 'It arrives undyed and a little stiff. After a few months it creases where you hold it and takes the shape of what you carry.',
234
- ],
235
- },
236
- {
237
- name: 'Brushed cotton overshirt',
238
- slug: 'brushed-cotton-overshirt',
239
- category: 'Wear',
240
- price: 98,
241
- inStock: false,
242
- description: 'A grey overshirt in brushed cotton flannel with a button-down collar and one chest pocket. Heavy enough to wear as a light jacket in spring.',
243
- material: 'Cotton flannel, 220 g/m², brushed on both sides. Mother-of-pearl buttons.',
244
- dimensions: 'Sizes S to XL. Size M: 76 cm back length, 57 cm across the chest.',
245
- origin: 'Guimarães, Portugal',
246
- care: 'Wash at 30 °C and line dry. Iron on low heat.',
247
- delivery: 'The next batch is being cut and should reach the shop in March.',
248
- story: [
249
- 'The flannel is brushed on both faces at a finishing mill outside Guimarães, which gives it a soft, slightly dusty surface and traps enough air to feel warm on a cold morning. We make it in one grey, a mix of undyed and black cotton.',
250
- 'This batch sold out in six weeks. Write to us and we will tell you when the next one arrives. Nothing is charged until it does.',
251
- ],
252
- },
253
- {
254
- name: 'Cast-iron skillet',
255
- slug: 'cast-iron-skillet',
256
- category: 'Kitchen',
257
- price: 89,
258
- inStock: true,
259
- description: 'A 26 cm skillet cast in one piece, with a pouring lip on each side. Seasoned with linseed oil and ready to cook with.',
260
- material: 'Cast iron, seasoned with three coats of linseed oil.',
261
- dimensions: '26 cm across, 5 cm deep, 45 cm with the handle.',
262
- weight: '2.6 kg',
263
- origin: 'Aveiro, Portugal',
264
- care: 'Rinse with hot water and a brush, dry on the hob, wipe with a drop of oil. Keep it out of the dishwasher.',
265
- delivery: 'Ships from Lisbon within two working days by tracked courier. Free returns within 30 days.',
266
- story: [
267
- 'Cast in sand moulds at a foundry near Aveiro that otherwise makes parts for water pumps. The cooking surface is machined smoother than most cast iron, so the seasoning builds quickly and eggs release after a few weeks of use.',
268
- 'It works on gas, electric and induction hobs, in the oven and over a fire. A skillet that has rusted or lost its seasoning can be saved: we strip and reseason them at the shop for the price of the oil.',
269
- ],
270
- },
271
- {
272
- name: 'Leather card holder',
273
- slug: 'leather-card-holder',
274
- category: 'Carry',
275
- price: 55,
276
- inStock: true,
277
- description: 'A slim holder for four to six cards in vegetable-tanned leather, stitched with waxed thread. It darkens and shines where your hand holds it.',
278
- material: 'Vegetable-tanned cowhide, 1.4 mm. Waxed linen thread.',
279
- dimensions: '10.5 × 7.5 cm. Two outer pockets and a centre slot.',
280
- origin: 'Lisbon, Portugal',
281
- care: 'Keep it dry. A little neutral leather balm once a year.',
282
- delivery: SHIPS,
283
- story: [
284
- 'Cut from the offcuts of our bag handles, so none of the hide is wasted. Each holder is saddle stitched by hand at the workshop with two needles and one waxed thread, a stitch that holds even if a single loop is cut.',
285
- 'The leather is tanned with tree bark over several weeks, which leaves it firm and pale at first. Within a few months it takes on the colour of your pocket.',
286
- ],
287
- },
288
- {
289
- name: 'Heavyweight T-shirt',
290
- slug: 'heavyweight-t-shirt',
291
- category: 'Wear',
292
- price: 38,
293
- inStock: true,
294
- description: 'A white T-shirt in dense organic cotton jersey with a narrow ribbed collar that keeps its shape. Straight cut, slightly longer at the back.',
295
- material: 'Organic cotton jersey, 240 g/m².',
296
- dimensions: 'Sizes XS to XXL. Size M: 71 cm back length, 54 cm across the chest.',
297
- origin: 'Barcelos, Portugal',
298
- care: 'Wash at 40 °C and dry flat or on a line. Allow 3% shrinkage on the first wash.',
299
- delivery: SHIPS,
300
- story: [
301
- 'Knitted and sewn by a family firm in Barcelos that has made T-shirts for other labels for three generations. The jersey is heavier than most, which keeps a white T-shirt from turning sheer and lets the collar lie flat after hundreds of washes.',
302
- 'We make it in white only, because white is the one we wear. The body is cut straight, so take a size up for a looser fit.',
303
- ],
304
- },
305
- {
306
- name: 'Striped wool blanket',
307
- slug: 'striped-wool-blanket',
308
- category: 'Living',
309
- price: 190,
310
- inStock: true,
311
- description: 'A heavy blanket in undyed wool with indigo stripes and hand-knotted fringes. Large enough for the foot of a double bed or the back of a sofa.',
312
- material: 'Serra da Estrela wool, undyed, with indigo-dyed stripes.',
313
- dimensions: '130 × 190 cm, plus 8 cm of fringe at each end.',
314
- weight: '1.6 kg',
315
- origin: 'Manteigas, Portugal',
316
- care: 'Air it outside rather than washing it. Hand wash cold with wool soap if needed and dry flat.',
317
- delivery: SHIPS,
318
- story: [
319
- 'Woven on a shuttle loom in Manteigas, a mountain town where wool has been washed in the river Zêzere for five hundred years. The mill buys fleece from shepherds in the Serra da Estrela and spins it without bleaching, so the cream of the blanket is the colour of the sheep.',
320
- 'The stripes are dyed with indigo in small lots, and the fringes are knotted by hand as each blanket comes off the loom. Wool this dense keeps out a draught and seldom needs washing: a dry day on a line is enough.',
321
- ],
322
- },
323
- {
324
- name: 'Porcelain pour-over set',
325
- slug: 'porcelain-pour-over-set',
326
- category: 'Kitchen',
327
- price: 72,
328
- inStock: true,
329
- description: 'A porcelain dripper and a 600 ml glass carafe with a cork collar, for two large cups at a time. The dripper takes size 2 paper filters.',
330
- material: 'Porcelain, borosilicate glass, natural cork.',
331
- capacity: '600 ml, two large cups.',
332
- dimensions: 'Carafe 19 cm high. Dripper 11.5 cm across.',
333
- origin: 'Porcelain from Ílhavo, Portugal. Glass from Bohemia, Czech Republic.',
334
- care: 'Dishwasher safe once the cork collar is lifted off. Wipe the cork dry.',
335
- delivery: 'Ships from Lisbon within two working days, packed in recycled paper. Free returns within 30 days.',
336
- story: [
337
- 'The dripper is made at a porcelain works in Ílhavo that has supplied restaurants in Porto since the 1950s. Its ribs are cut deep enough that the paper never seals against the wall, so the water runs through evenly and a pour takes about three minutes.',
338
- 'The carafe is mouth-blown borosilicate glass and can sit on a gas flame at low heat to keep coffee warm. The cork collar lets you hold it by the neck without a cloth.',
339
- ],
340
- },
341
- {
342
- name: 'Canvas shoulder bag',
343
- slug: 'canvas-shoulder-bag',
344
- category: 'Carry',
345
- price: 165,
346
- inStock: true,
347
- description: 'A roomy bag in tan cotton canvas with bridle leather handles and a detachable strap. Wide enough for a laptop and a change of clothes.',
348
- material: 'Cotton canvas, 18 oz. Vegetable-tanned bridle leather. Steel hooks.',
349
- dimensions: '40 × 34 × 14 cm. The strap adjusts from 90 to 130 cm.',
350
- weight: '1.1 kg',
351
- origin: 'Lisbon, Portugal',
352
- care: 'Brush off dust and spot clean with cold water. Condition the leather once a year.',
353
- delivery: SHIPS,
354
- story: [
355
- 'We cut and sew this bag in our own workshop behind the shop, twelve at a time. The canvas is a heavy cotton duck that holds its shape when the bag is empty and relaxes as it fills, and each handle is one length of bridle leather riveted through both layers.',
356
- 'Every seam that carries weight is stitched twice. The strap clips off with two steel hooks, so the bag goes by hand on a train and over the shoulder on a bicycle. We keep spare straps and hooks at the workshop for as long as we make the bag.',
357
- ],
358
- },
359
- {
360
- name: 'Field jacket',
361
- slug: 'field-jacket',
362
- category: 'Wear',
363
- price: 245,
364
- inStock: true,
365
- description: 'A four-pocket jacket in olive cotton drill, cut long enough to cover a sweater and loose enough to wear over one. Corozo buttons and a stand collar.',
366
- material: 'Cotton drill, 280 g/m², garment washed. Corozo nut buttons.',
367
- dimensions: 'Sizes XS to XL. Size M: 74 cm back length, 58 cm across the chest.',
368
- origin: 'Guimarães, Portugal',
369
- care: 'Wash at 30 °C inside out, line dry, iron warm.',
370
- delivery: SHIPS,
371
- story: [
372
- 'The pattern comes from a work jacket that one of our tailors in Guimarães wore for twenty years. We kept its proportions, raised the chest pockets two centimetres so they clear a bag strap, and chose corozo buttons, which survive a hot wash and can be sewn back on at the shop.',
373
- 'The drill is woven for us in runs of four hundred metres and washed once before cutting, so the jacket will not shrink after it reaches you. It softens and fades along the seams over a few years of wear. When a pocket tears or a cuff frays, send it back and we will mend it.',
374
- ],
375
- },
376
- ];
377
- export const STORE_DEMO_CATEGORIES = [
378
- {
379
- name: 'Wear',
380
- slug: 'wear',
381
- summary: 'Jackets, shirts and knitwear cut in Guimarães, Barcelos and Covilhã, and mended at the shop when they tear.',
382
- photoOf: 'cable-knit-beanie',
383
- relatedTitle: 'More to wear',
384
- makers: [
385
- 'Our clothes come from three workshops in the north of Portugal, each of which has sewn or knitted for larger labels for decades. We choose cloth with them, agree a pattern, and order in runs small enough to sell within a season.',
386
- 'Every garment is sold with the promise we make for everything in the shop: if a seam opens, a pocket tears or a button goes, bring it or send it back and we will repair it for as long as we sell the piece.',
387
- ],
388
- },
389
- {
390
- name: 'Carry',
391
- slug: 'carry',
392
- summary: 'Bags and small leather goods, most of them cut and sewn at our own workshop behind the shop in Lisbon.',
393
- photoOf: 'leather-card-holder',
394
- relatedTitle: 'More to carry',
395
- makers: [
396
- 'Canvas comes from a mill in Guimarães and leather from a vegetable tannery in Alcanena. Both are cut on the long table at the back of the shop, and anyone buying a bag can watch the next one being sewn.',
397
- 'We keep spare straps, hooks and rivets for everything we have made, so a bag can be put right long after the batch it came from has sold out.',
398
- ],
399
- },
400
- {
401
- name: 'Kitchen',
402
- slug: 'kitchen',
403
- summary: 'Cookware and tableware from a foundry, a porcelain works and an enamel maker, for use every day.',
404
- photoOf: 'cast-iron-skillet',
405
- relatedTitle: 'More for the kitchen',
406
- makers: [
407
- 'Nothing in the kitchen range is coated, and nothing needs to be handled gently. Cast iron, porcelain, glass and enamelled steel all last for decades when they are used every day, which is the only way we test them.',
408
- 'We cook with every piece at the shop before we sell it, and we reseason skillets for customers for the price of the oil.',
409
- ],
410
- },
411
- {
412
- name: 'Living',
413
- slug: 'living',
414
- summary: 'Blankets and table linen woven on old looms in Manteigas and Guimarães, from wool and flax left undyed.',
415
- photoOf: 'linen-table-runner',
416
- relatedTitle: 'More for the house',
417
- makers: [
418
- 'Our blankets and linens come from two weaving mills that still run shuttle looms, slower than modern machines and able to weave a denser cloth with a finished edge.',
419
- 'The mills weave for us twice a year, in spring and in autumn, so a piece that sells out comes back with the next season.',
420
- ],
421
- },
422
- ];
181
+ function categoryOf(copy, id) {
182
+ const found = copy.categories.find((entry) => entry.id === id);
183
+ if (found === undefined) {
184
+ throw new CogentaError({
185
+ code: 'BLUEPRINT_REGISTRY_CORRUPT',
186
+ message: `The store copy names no "${id}" category.`,
187
+ hint: 'Every product of the store copy must name one of its categories.',
188
+ });
189
+ }
190
+ return found;
191
+ }
423
192
  function productsGrid(key, options) {
424
193
  return {
425
194
  _key: key,
@@ -433,39 +202,27 @@ function productsGrid(key, options) {
433
202
  layout: 'grid',
434
203
  };
435
204
  }
436
- const COMMITMENTS = {
437
- _key: 'commitments',
438
- _type: 'featureGrid',
439
- _version: BLOCK_VERSION,
440
- items: [
441
- {
442
- _key: 'commitment-delivery',
443
- title: 'Delivery across the EU in 2 to 5 working days',
444
- link: { href: '/delivery-and-returns' },
445
- },
446
- {
447
- _key: 'commitment-returns',
448
- title: '30 days to return anything unworn',
449
- link: { href: '/delivery-and-returns' },
450
- },
451
- {
452
- _key: 'commitment-repairs',
453
- title: 'Repairs for as long as we sell the piece',
454
- link: { href: '/repairs' },
455
- },
456
- ],
457
- };
458
- function withKey(block, key) {
459
- return { ...block, _key: key };
205
+ function commitments(copy, facts, key) {
206
+ const words = copy.pages(facts).home;
207
+ return {
208
+ _key: key,
209
+ _type: 'featureGrid',
210
+ _version: BLOCK_VERSION,
211
+ items: words.commitments.map((item, index) => ({
212
+ _key: `${key}-${index}`,
213
+ title: item.title,
214
+ link: { href: `/${copy.pageSlugs[item.page]}` },
215
+ })),
216
+ };
460
217
  }
461
218
  /** The body of one product's page: how it is made, then more from its category. */
462
- export function storeProductBlocks(demo) {
463
- const group = STORE_DEMO_CATEGORIES.find((candidate) => candidate.name === demo.category);
219
+ export function storeProductBlocks(copy, demo) {
220
+ const group = categoryOf(copy, demo.category);
464
221
  return [
465
222
  prose(`product-${demo.slug}-story`, [...demo.story]),
466
223
  productsGrid(`product-${demo.slug}-more`, {
467
- title: group?.relatedTitle ?? 'More from the shop',
468
- category: demo.category,
224
+ title: group.relatedTitle,
225
+ category: group.name,
469
226
  limit: 5,
470
227
  }),
471
228
  ];
@@ -478,18 +235,25 @@ export function storeCategoryBlocks(demo) {
478
235
  ];
479
236
  }
480
237
  export function buildStoreHomeBlocks(options = {}) {
238
+ const copy = storeCopyFor(options.locale ?? 'en');
481
239
  const media = options.media ?? {};
482
- const siteName = nameOf(options.siteName);
483
- const letters = shopEmail(siteName, 'letters');
240
+ const facts = factsOf(options.siteName);
241
+ const words = copy.pages(facts).home;
484
242
  return [
485
243
  {
486
244
  _key: 'home-banner',
487
245
  _type: 'hero',
488
246
  _version: BLOCK_VERSION,
489
- title: 'Things for every day, made to last and to be mended',
490
- subtitle: 'Clothing, bags and kitchenware from eleven small workshops in Portugal and beyond, sold from our shop in Lisbon and sent across Europe.',
247
+ title: words.heroTitle,
248
+ subtitle: words.heroSubtitle,
491
249
  ...(media.hero === undefined ? {} : { media: media.hero }),
492
- actions: [{ label: 'Shop the collection', target: { href: '/shop' }, emphasis: 'primary' }],
250
+ actions: [
251
+ {
252
+ label: words.heroAction,
253
+ target: { href: `/${copy.pageSlugs.shop}` },
254
+ emphasis: 'primary',
255
+ },
256
+ ],
493
257
  },
494
258
  {
495
259
  _key: 'home-categories',
@@ -500,8 +264,8 @@ export function buildStoreHomeBlocks(options = {}) {
500
264
  limit: 4,
501
265
  layout: 'grid',
502
266
  },
503
- productsGrid('home-new', { title: 'New this season', limit: 4 }),
504
- withKey(COMMITMENTS, 'home-commitments'),
267
+ productsGrid('home-new', { title: words.newTitle, limit: 4 }),
268
+ commitments(copy, facts, 'home-commitments'),
505
269
  ...(media.story === undefined
506
270
  ? []
507
271
  : [
@@ -510,54 +274,36 @@ export function buildStoreHomeBlocks(options = {}) {
510
274
  _type: 'mediaFigure',
511
275
  _version: BLOCK_VERSION,
512
276
  media: media.story,
513
- ratio: '1:1',
277
+ ratio: '4:3',
514
278
  align: 'start',
515
- caption: `${siteName} opened in 2014 as a repair bench at the back of a haberdashery on Rua da Boavista. We still mend what we sell, and we only sell what our workshops make to be mended.`,
516
- credit: 'Enamel mug, made in Olkusz',
279
+ caption: words.storyCaption,
517
280
  },
518
281
  ]),
519
282
  {
520
283
  _key: 'home-letter',
521
284
  _type: 'testimonial',
522
285
  _version: BLOCK_VERSION,
523
- quote: answer('home-letter-quote', 'I bought the field jacket in 2016 and sent it back last winter with a torn pocket and two buttons missing. It came home three weeks later with both put right and a note saying who had sewn them.'),
524
- attribution: { name: 'Helena Duarte', role: 'Field jacket, bought in 2016' },
286
+ quote: answer('home-letter-quote', words.letter.quote),
287
+ attribution: { name: words.letter.name, role: words.letter.role },
525
288
  },
526
289
  {
527
290
  _key: 'home-faq',
528
291
  _type: 'faq',
529
292
  _version: BLOCK_VERSION,
530
- title: 'Before you order',
531
- items: questions('home-faq', [
532
- [
533
- 'How do I place an order?',
534
- 'Use the order button on a product page to write to us, or come to the shop. We reply within one working day with the total, delivery included, and a secure payment link. Nothing is charged until you confirm.',
535
- ],
536
- [
537
- 'How long does delivery take?',
538
- 'Two to three working days in mainland Portugal and three to five across the rest of the European Union. Orders confirmed before noon leave Lisbon the same day.',
539
- ],
540
- [
541
- 'Can I collect my order from the shop?',
542
- 'Yes. Ask for collection when you write, and your order will be waiting at Rua da Boavista 84 from the next day, Tuesday to Saturday.',
543
- ],
544
- [
545
- 'What if something does not fit?',
546
- 'Send it back unworn within 30 days for a refund or another size. Returns are free within Portugal, and from elsewhere in the EU we refund the cost of the cheapest tracked service.',
547
- ],
548
- ]),
293
+ title: words.faqTitle,
294
+ items: questions('home-faq', words.faq),
549
295
  },
550
296
  {
551
297
  _key: 'home-letters',
552
298
  _type: 'cta',
553
299
  _version: BLOCK_VERSION,
554
- title: 'Letters from the workshop',
555
- text: 'Four letters a year about new batches, repairs and the people who make our goods. Write to us and we will add you to the list.',
300
+ title: words.lettersTitle,
301
+ text: words.lettersText,
556
302
  actions: [
557
303
  {
558
- label: 'Ask for the letters',
304
+ label: words.lettersAction,
559
305
  target: {
560
- href: `mailto:${letters}?subject=${encodeURIComponent('Letters from the workshop')}`,
306
+ href: `mailto:${facts.letters}?subject=${encodeURIComponent(words.lettersSubject)}`,
561
307
  },
562
308
  emphasis: 'secondary',
563
309
  },
@@ -566,224 +312,145 @@ export function buildStoreHomeBlocks(options = {}) {
566
312
  ];
567
313
  }
568
314
  /**
569
- * `home`, `shop` (every product), `about`, `how-to-order`,
570
- * `delivery-and-returns`, `repairs`, `contact` and `terms`: every page the
571
- * menus and the copy link to.
315
+ * `home`, `shop` (every product), `about`, how to order, delivery and
316
+ * returns, repairs, contact, terms and the photo credits: every page the
317
+ * menus and the copy link to, in the copy's language.
572
318
  */
573
319
  export function buildStoreDemoPages(options = {}) {
320
+ const copy = storeCopyFor(options.locale ?? 'en');
574
321
  const media = options.media ?? {};
575
- const siteName = nameOf(options.siteName);
576
- const hello = shopEmail(siteName);
577
- const orders = shopEmail(siteName, 'orders');
578
- const repairs = shopEmail(siteName, 'repairs');
579
- const letters = shopEmail(siteName, 'letters');
322
+ const facts = factsOf(options.siteName);
323
+ const words = copy.pages(facts);
324
+ const slug = copy.pageSlugs;
325
+ const entry = (key, blocks) => ({
326
+ title: words.titles[key],
327
+ slug: slug[key],
328
+ blocks,
329
+ });
580
330
  return [
581
- { title: 'Home', slug: 'home', blocks: buildStoreHomeBlocks({ siteName, media }) },
582
- {
583
- title: 'Shop',
584
- slug: 'shop',
585
- blocks: [productsGrid('shop-all', { limit: 48 }), withKey(COMMITMENTS, 'shop-commitments')],
586
- },
587
- {
588
- title: 'About',
589
- slug: 'about',
590
- blocks: [
591
- prose('about-intro', [
592
- `${siteName} began in 2014 as a repair bench at the back of a haberdashery on Rua da Boavista in Lisbon. People brought in coats with broken zips and bags with torn straps, and after a year of mending other people's things we started to make our own, built so that they could be mended too.`,
593
- 'Today the shop sells about sixty pieces from eleven workshops. Most of them are in the north of Portugal, within a day of each other by train: a tailoring firm in Guimarães, a knitter in Covilhã, a weaving mill in Manteigas, a foundry near Aveiro. We visit each of them at least twice a year, and we buy in runs small enough to sell through before the next season.',
594
- '## How we choose what to sell',
595
- 'A piece comes into the shop when we have used it long enough to know how it wears, and when the person who made it can supply the parts to repair it. That rules out most things with glued soles, coated pans and zips we cannot replace. It also means the range changes slowly and some pieces sell out for months at a time.',
596
- 'We pay our workshops before the goods are delivered and publish the price we paid on request. Nothing is made in a quantity we cannot sell, so nothing is ever put on sale to clear a warehouse.',
597
- ]),
598
- ...(media.hero === undefined
599
- ? []
600
- : [
601
- {
602
- _key: 'about-figure',
603
- _type: 'mediaFigure',
604
- _version: BLOCK_VERSION,
605
- media: media.hero,
606
- ratio: '21:9',
607
- align: 'wide',
608
- caption: 'A canvas tote, a lambswool beanie and a card holder, all made within a day of Lisbon.',
609
- },
610
- ]),
611
- {
612
- _key: 'about-figures',
613
- _type: 'stats',
614
- _version: BLOCK_VERSION,
615
- title: 'The shop in numbers',
616
- items: [
617
- {
618
- _key: 'about-figure-workshops',
619
- value: '11',
620
- label: 'workshops we buy from, nine of them in Portugal',
621
- },
622
- {
623
- _key: 'about-figure-repairs',
624
- value: '1,380',
625
- label: 'repairs done at the bench last year',
626
- },
627
- {
628
- _key: 'about-figure-opened',
629
- value: '2014',
630
- label: 'the year we opened on Rua da Boavista',
631
- },
632
- ],
633
- },
634
- {
635
- _key: 'about-visit',
636
- _type: 'cta',
637
- _version: BLOCK_VERSION,
638
- title: 'Visit the shop and the repair bench',
639
- text: 'Rua da Boavista 84, Lisbon. Open Tuesday to Saturday, 11:00 to 19:00.',
640
- actions: [
641
- {
642
- label: 'Opening hours and directions',
643
- target: { href: '/contact' },
644
- emphasis: 'secondary',
645
- },
646
- ],
647
- },
648
- ],
649
- },
650
- {
651
- title: 'How to order',
652
- slug: 'how-to-order',
653
- blocks: [
654
- prose('order-intro', [
655
- 'We sell through the shop and by email, so that every order is read by the person who will pack it. It takes a little longer than a checkout and it means we can answer a question about size or delivery before you pay.',
656
- '## Ordering by email',
657
- `Use the order button on any product page, or write to [${orders}](mailto:${orders}) with the pieces, the sizes and the delivery address. We reply within one working day, Tuesday to Saturday, with the total including delivery and a secure payment link by card or MB WAY. Your order leaves Lisbon as soon as the payment arrives.`,
658
- '## Ordering at the shop',
659
- 'Everything on the site is in the shop at Rua da Boavista 84, and most sizes can be tried on. We can also keep an item aside for a week if you tell us when you plan to come.',
660
- ]),
661
- {
662
- _key: 'order-notes',
663
- _type: 'accordion',
664
- _version: BLOCK_VERSION,
665
- title: 'Payment and delivery',
666
- items: questions('order-notes', [
667
- [
668
- 'Which payment methods do you accept?',
669
- 'Visa, Mastercard and MB WAY through a payment link, bank transfer to our account in Lisbon, and cash or card at the shop. Prices include Portuguese VAT.',
670
- ],
671
- [
672
- 'What does delivery cost?',
673
- 'Delivery is €5 in mainland Portugal and €12 to the rest of the EU, free on orders over €150. Blankets and skillets travel by tracked courier at the same price.',
674
- ],
675
- [
676
- 'Do you send orders outside the European Union?',
677
- 'We send to the United Kingdom, Switzerland and Norway at cost. Import duties and taxes are paid by the recipient on arrival, and we tell you the estimate before you pay.',
678
- ],
679
- [
680
- 'Can you wrap a gift?',
681
- 'Yes, in brown paper and cotton string, with a card written by hand if you send us the words. It costs nothing.',
682
- ],
683
- ]),
684
- },
685
- ],
686
- },
687
- {
688
- title: 'Delivery and returns',
689
- slug: 'delivery-and-returns',
690
- blocks: [
691
- prose('delivery-intro', [
692
- 'Orders leave the shop in Lisbon every working day at 14:00, packed in recycled paper and card with no plastic. You receive a tracking number by email when the parcel is collected.',
693
- ]),
694
- {
695
- _key: 'delivery-faq',
696
- _type: 'faq',
697
- _version: BLOCK_VERSION,
698
- title: 'Delivery and returns',
699
- items: questions('delivery-faq', [
700
- [
701
- 'How long does delivery take?',
702
- 'Two to three working days in mainland Portugal, three to five working days to the rest of the European Union, and five to eight to the United Kingdom, Switzerland and Norway.',
703
- ],
704
- [
705
- 'How do I return something?',
706
- `Write to [${orders}](mailto:${orders}) within 30 days of delivery with your order number. We send a prepaid label for returns within Portugal, and an address for returns from elsewhere.`,
707
- ],
708
- [
709
- 'When will I be refunded?',
710
- 'Within five working days of the parcel reaching us, to the card or account you paid from. Delivery costs are refunded when the whole order is returned.',
711
- ],
712
- [
713
- 'Can I exchange a size?',
714
- 'Yes. Tell us the size you need when you write, and we send it as soon as the first piece is on its way back to us.',
715
- ],
716
- [
717
- 'What cannot be returned?',
718
- 'Pieces that have been worn, washed or altered, and anything we have repaired or made to order for you.',
719
- ],
720
- ]),
721
- },
722
- ],
723
- },
724
- {
725
- title: 'Repairs',
726
- slug: 'repairs',
727
- blocks: [
728
- prose('repairs-intro', [
729
- 'We repair everything we sell for as long as we sell it, and most things long after. The bench is at the back of the shop, and two of us work at it every afternoon.',
730
- '## What we mend',
731
- 'Seams, pockets, cuffs and buttons on clothing. Straps, hooks, rivets and stitching on bags and leather. Rust and lost seasoning on cast iron. Moth holes in knitwear, if they are small enough to darn.',
732
- '## What it costs',
733
- 'Repairs to anything bought from us in the last two years are free. After that we charge for the materials and nothing for the time, which comes to between €5 and €25 for most repairs. We tell you the price before we start.',
734
- '## How to send something in',
735
- `Bring it to the shop, or write to [${repairs}](mailto:${repairs}) with a photograph of the damage. We reply with the price, the time it will take (usually two to three weeks) and the address to post it to.`,
736
- ]),
737
- {
738
- _key: 'repairs-figures',
739
- _type: 'statCounter',
740
- _version: BLOCK_VERSION,
741
- title: 'Last year at the bench',
742
- stats: [
743
- { _key: 'repairs-figure-total', value: '1,380', label: 'repairs completed' },
744
- { _key: 'repairs-figure-free', value: '62%', label: 'done free of charge' },
745
- {
746
- _key: 'repairs-figure-days',
747
- value: '16',
748
- label: 'days on average from arrival to return',
749
- },
750
- ],
751
- },
752
- ],
753
- },
754
- {
755
- title: 'Contact',
756
- slug: 'contact',
757
- blocks: [
758
- prose('contact-details', [
759
- '## The shop',
760
- 'Rua da Boavista 84, 1200-066 Lisboa, Portugal. Five minutes on foot from Cais do Sodré station and the 28 tram.',
761
- 'Tuesday to Saturday, 11:00 to 19:00. Closed on Sundays, Mondays and public holidays.',
762
- '## Writing to us',
763
- `For orders, [${orders}](mailto:${orders}). For repairs, [${repairs}](mailto:${repairs}). For our letters from the workshop, four a year, [${letters}](mailto:${letters}). For anything else, including workshops that would like to work with us, [${hello}](mailto:${hello}).`,
764
- 'Telephone +351 213 460 218, Tuesday to Saturday during opening hours.',
765
- ]),
766
- ],
767
- },
768
- {
769
- title: 'Terms and privacy',
770
- slug: 'terms',
771
- blocks: [
772
- prose('terms', [
773
- `These terms apply to every order placed with ${siteName}, Lda., Rua da Boavista 84, 1200-066 Lisboa, registered in Portugal under NIPC 516 204 873.`,
774
- '## Orders and prices',
775
- 'An order is confirmed when we have received payment and replied to say so. Prices are in euros and include VAT at the Portuguese rate. Delivery costs are stated before payment.',
776
- '## Your right to cancel',
777
- 'You may cancel an order within 14 days of receiving it without giving a reason, as the law of the European Union provides, and our own returns period of 30 days extends that right. Refunds are made within 14 days of the goods reaching us.',
778
- '## Guarantee',
779
- 'Every piece carries the legal guarantee of conformity of three years. Our repair service is offered in addition to it and does not replace it.',
780
- '## Privacy',
781
- `We keep your name, address and email for as long as it takes to deliver, return or repair an order, and for the ten years Portuguese tax law requires us to keep invoices. We never sell or share them except with the carrier delivering your parcel. Write to [${hello}](mailto:${hello}) to see or delete what we hold. This site sets no advertising or tracking cookies.`,
331
+ entry('home', buildStoreHomeBlocks(options)),
332
+ entry('shop', [
333
+ productsGrid('shop-all', { limit: 48 }),
334
+ commitments(copy, facts, 'shop-commitments'),
335
+ ]),
336
+ entry('about', [
337
+ prose('about-intro', words.about.intro),
338
+ ...(media.hero === undefined
339
+ ? []
340
+ : [
341
+ {
342
+ _key: 'about-figure',
343
+ _type: 'mediaFigure',
344
+ _version: BLOCK_VERSION,
345
+ media: media.hero,
346
+ ratio: '21:9',
347
+ align: 'wide',
348
+ caption: words.about.figureCaption,
349
+ },
782
350
  ]),
783
- ],
784
- },
351
+ {
352
+ _key: 'about-figures',
353
+ _type: 'stats',
354
+ _version: BLOCK_VERSION,
355
+ title: words.about.figuresTitle,
356
+ items: words.about.figures.map((item, index) => ({
357
+ _key: `about-figure-${index}`,
358
+ ...item,
359
+ })),
360
+ },
361
+ {
362
+ _key: 'about-visit',
363
+ _type: 'cta',
364
+ _version: BLOCK_VERSION,
365
+ title: words.about.visitTitle,
366
+ text: words.about.visitText,
367
+ actions: [
368
+ {
369
+ label: words.about.visitAction,
370
+ target: { href: `/${slug.contact}` },
371
+ emphasis: 'secondary',
372
+ },
373
+ ],
374
+ },
375
+ ]),
376
+ entry('order', [
377
+ prose('order-intro', words.order.intro),
378
+ {
379
+ _key: 'order-notes',
380
+ _type: 'accordion',
381
+ _version: BLOCK_VERSION,
382
+ title: words.order.notesTitle,
383
+ items: questions('order-notes', words.order.notes),
384
+ },
385
+ ]),
386
+ entry('delivery', [
387
+ prose('delivery-intro', words.delivery.intro),
388
+ {
389
+ _key: 'delivery-faq',
390
+ _type: 'faq',
391
+ _version: BLOCK_VERSION,
392
+ title: words.delivery.faqTitle,
393
+ items: questions('delivery-faq', words.delivery.faq),
394
+ },
395
+ ]),
396
+ entry('repairs', [
397
+ prose('repairs-intro', words.repairs.intro),
398
+ {
399
+ _key: 'repairs-figures',
400
+ _type: 'statCounter',
401
+ _version: BLOCK_VERSION,
402
+ title: words.repairs.figuresTitle,
403
+ stats: words.repairs.figures.map((item, index) => ({
404
+ _key: `repairs-figure-${index}`,
405
+ ...item,
406
+ })),
407
+ },
408
+ ]),
409
+ entry('contact', [prose('contact-details', words.contact)]),
410
+ entry('terms', [prose('terms', words.terms)]),
411
+ entry('credits', [creditsProse(words.credits, STORE_PHOTO_CREDITS)]),
785
412
  ];
786
413
  }
414
+ /** The credits page's body: a sentence, then one line per photograph with its licence and source. */
415
+ function creditsProse(credits, list) {
416
+ const lines = (credit, index) => {
417
+ const key = `credits-item-${index}`;
418
+ const link = (part, text, href) => ({
419
+ span: { _key: `${key}-s${part}`, _type: 'span', text, marks: [`${key}-l${part}`] },
420
+ mark: { _key: `${key}-l${part}`, _type: 'link', href },
421
+ });
422
+ const plain = (part, text) => ({
423
+ span: { _key: `${key}-s${part}`, _type: 'span', text, marks: [] },
424
+ mark: undefined,
425
+ });
426
+ const parts = [
427
+ plain('0', `${credit.title} · ${credit.author} · `),
428
+ credit.licenceUrl === undefined
429
+ ? plain('1', credit.licence)
430
+ : link('1', credit.licence, credit.licenceUrl),
431
+ plain('2', ' · '),
432
+ link('3', credits.sourceWord, credit.source),
433
+ ];
434
+ return {
435
+ _key: key,
436
+ _type: 'block',
437
+ style: 'normal',
438
+ listItem: 'bullet',
439
+ level: 1,
440
+ children: parts.map((part) => part.span),
441
+ markDefs: parts.flatMap((part) => (part.mark === undefined ? [] : [part.mark])),
442
+ };
443
+ };
444
+ return {
445
+ _key: 'credits-body',
446
+ _type: 'prose',
447
+ _version: BLOCK_VERSION,
448
+ body: [
449
+ ...credits.intro.map((line, index) => textBlock(`credits-intro-${index}`, 'normal', line)),
450
+ ...list.map(lines),
451
+ ],
452
+ };
453
+ }
787
454
  // ---------------------------------------------------------------------------
788
455
  // Media, menus, settings
789
456
  // ---------------------------------------------------------------------------
@@ -804,20 +471,6 @@ function storePalette() {
804
471
  }
805
472
  return skin.color;
806
473
  }
807
- const PRODUCT_ALT = {
808
- 'linen-table-runner': 'White linen runner with fringed ends laid along a dark oak table',
809
- 'enamel-mug': 'Forest green enamel mug with a steel rim on a wooden table',
810
- 'cable-knit-beanie': 'Charcoal cable-knit lambswool beanie against a white wall',
811
- 'canvas-tote': 'Undyed cotton canvas tote with long handles standing on its base',
812
- 'brushed-cotton-overshirt': 'Grey brushed cotton overshirt with a button-down collar and chest pocket',
813
- 'cast-iron-skillet': 'Black cast-iron skillet with a pouring lip, seen from above at an angle',
814
- 'leather-card-holder': 'Tan vegetable-tanned leather card holder with hand stitching and two cards inside',
815
- 'heavyweight-t-shirt': 'White heavyweight cotton T-shirt laid flat on a pale grey ground',
816
- 'striped-wool-blanket': 'Folded cream wool blanket with navy stripes and a knotted fringe',
817
- 'porcelain-pour-over-set': 'Porcelain coffee dripper resting on a glass carafe with a cork collar',
818
- 'canvas-shoulder-bag': 'Tan canvas shoulder bag with brown leather handles and a detachable strap',
819
- 'field-jacket': 'Olive cotton drill field jacket with four pockets and a stand collar',
820
- };
821
474
  /**
822
475
  * Every visual this blueprint seeds is a bundled photograph: the banner, one
823
476
  * per product, one per category (the photograph of a product from that
@@ -825,122 +478,129 @@ const PRODUCT_ALT = {
825
478
  * `spec` is `seedDemoMedia`'s fallback if a file is ever missing, never the
826
479
  * intended picture.
827
480
  */
828
- export const STORE_MEDIA_SPECS = [
829
- {
830
- name: 'hero',
831
- spec: heroArt(storePalette(), 'blocks', 11),
832
- alt: 'A canvas tote, a knitted beanie and a leather card holder laid out on undyed linen',
833
- photo: 'store/hero.jpg',
834
- },
835
- ...STORE_DEMO_CATEGORIES.map((demo, index) => ({
836
- name: `category-${demo.slug}`,
837
- spec: coverArt(storePalette(), 50 + index),
838
- alt: PRODUCT_ALT[demo.photoOf] ?? demo.name,
839
- photo: `store/${demo.photoOf}.jpg`,
840
- })),
841
- {
842
- name: 'story',
843
- spec: coverArt(storePalette(), 60),
844
- alt: PRODUCT_ALT['enamel-mug'],
845
- photo: 'store/enamel-mug.jpg',
846
- },
847
- ...STORE_DEMO_PRODUCTS.map((demo, index) => ({
848
- name: `product-${demo.slug}`,
849
- spec: productArt(storePalette(), index + 1),
850
- alt: PRODUCT_ALT[demo.slug] ?? demo.name,
851
- photo: `store/${demo.slug}.jpg`,
852
- })),
853
- ];
854
- export const STORE_MENUS = {
855
- header: [
856
- { label: 'Shop', url: '/shop' },
857
- ...STORE_DEMO_CATEGORIES.map((demo) => ({ label: demo.name, url: `/category/${demo.slug}` })),
858
- { label: 'About', url: '/about' },
859
- ],
860
- footer: [
861
- { label: 'About', url: '/about' },
862
- { label: 'How to order', url: '/how-to-order' },
863
- { label: 'Delivery and returns', url: '/delivery-and-returns' },
864
- { label: 'Repairs', url: '/repairs' },
865
- { label: 'Contact', url: '/contact' },
866
- { label: 'Terms and privacy', url: '/terms' },
867
- ],
868
- headerAction: { label: 'How to order', url: '/how-to-order' },
869
- };
481
+ export function storeMediaSpecs(copy) {
482
+ const palette = storePalette();
483
+ const altOf = (key) => copy.products.find((demo) => demo.key === key)?.alt ?? key;
484
+ return [
485
+ {
486
+ name: 'hero',
487
+ spec: heroArt(palette, 'blocks', 11),
488
+ alt: copy.media.hero,
489
+ photo: 'store/hero.jpg',
490
+ },
491
+ ...copy.categories.map((demo, index) => ({
492
+ name: `category-${demo.id}`,
493
+ spec: coverArt(palette, 50 + index),
494
+ alt: altOf(demo.photoOf),
495
+ photo: `store/${demo.photoOf}.jpg`,
496
+ })),
497
+ {
498
+ name: 'story',
499
+ spec: coverArt(palette, 60),
500
+ alt: copy.media.story,
501
+ photo: 'store/story.jpg',
502
+ },
503
+ ...copy.products.map((demo, index) => ({
504
+ name: `product-${demo.key}`,
505
+ spec: productArt(palette, index + 1),
506
+ alt: demo.alt,
507
+ photo: `store/${demo.key}.jpg`,
508
+ })),
509
+ ];
510
+ }
511
+ export function storeMenus(copy) {
512
+ const url = (key) => `/${copy.pageSlugs[key]}`;
513
+ return {
514
+ header: [
515
+ { label: copy.menus.shop, url: url('shop') },
516
+ ...copy.categories.map((demo) => ({
517
+ label: demo.name,
518
+ url: `${copy.schema.routes.category.replace('/:slug', '')}/${demo.slug}`,
519
+ })),
520
+ { label: copy.menus.about, url: url('about') },
521
+ ],
522
+ footer: copy.menus.footer.map((item) => ({ label: item.label, url: url(item.page) })),
523
+ headerAction: { label: copy.menus.action, url: url('order') },
524
+ };
525
+ }
870
526
  const HOME = { kind: 'home' };
871
527
  const SEARCH_RESULTS = { kind: 'search' };
872
528
  const pagePath = (path) => ({ kind: 'path', path });
873
- const CUSTOMER_CARE_PAGES = [
874
- { label: 'How to order', href: '/how-to-order' },
875
- { label: 'Delivery and returns', href: '/delivery-and-returns' },
876
- { label: 'Repairs', href: '/repairs' },
877
- { label: 'Contact', href: '/contact' },
878
- { label: 'Terms and privacy', href: '/terms' },
879
- ];
880
529
  function shownOn(mode, ...targets) {
881
530
  return { pages: { mode, targets } };
882
531
  }
883
- export const STORE_WIDGETS = [
884
- {
885
- area: 'sidebar',
886
- type: 'recentEntries',
887
- title: 'New in the shop',
888
- settings: { collection: 'product', count: 4, showDate: false, showImage: true },
889
- visibility: shownOn('only', SEARCH_RESULTS),
890
- },
891
- {
892
- area: 'sidebar',
893
- type: 'links',
894
- title: 'Customer care',
895
- settings: { items: CUSTOMER_CARE_PAGES.map((item) => ({ ...item })) },
896
- visibility: shownOn('only', ...CUSTOMER_CARE_PAGES.map((item) => pagePath(item.href)), SEARCH_RESULTS),
897
- },
898
- {
899
- area: 'sidebar',
900
- type: 'cta',
901
- title: 'Before you order',
902
- settings: {
903
- heading: 'A question about a size or a delivery',
904
- body: 'Write to us or call the shop. We reply within one working day, Tuesday to Saturday, and nothing is charged until you confirm.',
905
- label: 'Contact the shop',
906
- href: '/contact',
532
+ export function storeWidgets(copy) {
533
+ const w = copy.widgets;
534
+ const slug = copy.pageSlugs;
535
+ const care = ['order', 'delivery', 'repairs', 'contact', 'terms'].map((key) => ({
536
+ label: w.careLabels[key],
537
+ href: `/${slug[key]}`,
538
+ }));
539
+ const contactHref = `/${slug.contact}`;
540
+ return [
541
+ {
542
+ area: 'sidebar',
543
+ type: 'recentEntries',
544
+ title: w.newTitle,
545
+ settings: { collection: 'product', count: 4, showDate: false, showImage: true },
546
+ visibility: shownOn('only', SEARCH_RESULTS),
907
547
  },
908
- visibility: shownOn('only', ...CUSTOMER_CARE_PAGES.filter((item) => item.href !== '/contact').map((item) => pagePath(item.href))),
909
- },
910
- {
911
- area: 'footer-1',
912
- type: 'contact',
913
- title: 'Call the shop',
914
- settings: {
915
- phone: '+351 213 460 218',
916
- hours: [{ label: 'Answered', value: 'Tuesday to Saturday, during opening hours' }],
548
+ {
549
+ area: 'sidebar',
550
+ type: 'links',
551
+ title: w.careTitle,
552
+ settings: { items: care.map((item) => ({ ...item })) },
553
+ visibility: shownOn('only', ...care.map((item) => pagePath(item.href)), SEARCH_RESULTS),
917
554
  },
918
- visibility: shownOn('except', pagePath('/contact')),
919
- },
920
- {
921
- area: 'footer-2',
922
- type: 'cta',
923
- title: 'Letters from the workshop',
924
- settings: {
925
- heading: 'Four letters a year',
926
- body: 'New batches, repairs and the people who make our goods, written from the bench in Lisbon.',
927
- label: 'How to ask for them',
928
- href: '/contact',
555
+ {
556
+ area: 'sidebar',
557
+ type: 'cta',
558
+ title: w.beforeTitle,
559
+ settings: {
560
+ heading: w.beforeHeading,
561
+ body: w.beforeBody,
562
+ label: w.beforeLabel,
563
+ href: contactHref,
564
+ },
565
+ visibility: shownOn('only', ...care.filter((item) => item.href !== contactHref).map((item) => pagePath(item.href))),
929
566
  },
930
- visibility: shownOn('except', HOME, pagePath('/contact')),
931
- },
932
- ];
933
- export const STORE_SITE_SETTINGS = {
934
- 'general.tagline': 'Everyday goods, made to last and to be mended.',
935
- 'general.socialLinks': [
936
- { label: 'Instagram', url: 'https://instagram.com/example' },
937
- { label: 'Pinterest', url: 'https://pinterest.com/example' },
938
- ],
939
- 'general.footerNote': 'Rua da Boavista 84, 1200-066 Lisboa, Portugal. Shop and repair bench open Tuesday to Saturday, 11:00 to 19:00.\n\nRegistered in Portugal as a private limited company, NIPC 516 204 873.',
940
- // A catalogue is not a discussion: no comment form under a product. An
941
- // editor can open comments again per collection or per entry.
942
- 'discussion.enabled': false,
943
- };
567
+ {
568
+ area: 'footer-1',
569
+ type: 'contact',
570
+ title: w.phoneTitle,
571
+ settings: {
572
+ phone: w.phone,
573
+ hours: [{ label: w.phoneHoursLabel, value: w.phoneHoursValue }],
574
+ },
575
+ visibility: shownOn('except', pagePath(contactHref)),
576
+ },
577
+ {
578
+ area: 'footer-2',
579
+ type: 'cta',
580
+ title: w.lettersTitle,
581
+ settings: {
582
+ heading: w.lettersHeading,
583
+ body: w.lettersBody,
584
+ label: w.lettersLabel,
585
+ href: contactHref,
586
+ },
587
+ visibility: shownOn('except', HOME, pagePath(contactHref)),
588
+ },
589
+ ];
590
+ }
591
+ export function storeSiteSettings(copy) {
592
+ return {
593
+ 'general.tagline': copy.settings.tagline,
594
+ 'general.socialLinks': [
595
+ { label: 'Instagram', url: 'https://instagram.com/example' },
596
+ { label: 'Pinterest', url: 'https://pinterest.com/example' },
597
+ ],
598
+ 'general.footerNote': copy.settings.footerNote,
599
+ // A catalogue is not a discussion: no comment form under a product. An
600
+ // editor can open comments again per collection or per entry.
601
+ 'discussion.enabled': false,
602
+ };
603
+ }
944
604
  export const STORE_RECOMMENDED_AGENTS = [
945
605
  {
946
606
  name: 'performanceAgent',
@@ -954,78 +614,95 @@ export const STORE_RECOMMENDED_AGENTS = [
954
614
  },
955
615
  ];
956
616
  /** The email address a product's order button writes to, with the product in the subject line. */
957
- export function orderLinkFor(siteName, productName) {
958
- return `mailto:${shopEmail(nameOf(siteName), 'orders')}?subject=${encodeURIComponent(`Order: ${productName}`)}`;
617
+ export function orderLinkFor(siteName, productName, locale = 'en') {
618
+ const subject = storeCopyFor(locale).orderSubject.replace('{product}', productName);
619
+ return `mailto:${shopEmail(nameOf(siteName), 'orders')}?subject=${encodeURIComponent(subject)}`;
959
620
  }
621
+ // Kept for the blueprints that still list a single, English set of constants.
622
+ export const STORE_DEMO_PRODUCTS = STORE_COPY_EN.products;
623
+ export const STORE_DEMO_CATEGORIES = STORE_COPY_EN.categories;
624
+ export const STORE_MEDIA_SPECS = storeMediaSpecs(STORE_COPY_EN);
625
+ export const STORE_MENUS = storeMenus(STORE_COPY_EN);
626
+ export const STORE_WIDGETS = storeWidgets(STORE_COPY_EN);
627
+ export const STORE_SITE_SETTINGS = storeSiteSettings(STORE_COPY_EN);
960
628
  /**
961
629
  * Inserts the blueprint's content through the real `ContentStore`, never
962
630
  * mocked (house rule): categories first (the home page lists them in that
963
631
  * order), then the products oldest first, then the pages. Everything is
964
632
  * published, so every list and every link has something real behind it.
965
633
  */
966
- async function seedStoreDemoContent(ctx) {
967
- const { db, defaultLocale, adminId, media } = ctx;
968
- const siteName = nameOf(ctx.siteName);
969
- const categoryStore = createContentStore({ db, collection: category, defaultLocale });
970
- const productStore = createContentStore({ db, collection: product, defaultLocale });
971
- const pageStore = createContentStore({ db, collection: page, defaultLocale });
972
- for (const demo of STORE_DEMO_CATEGORIES) {
973
- const photo = media[`category-${demo.slug}`];
974
- await categoryStore.create({
975
- status: 'published',
976
- createdBy: adminId,
977
- values: {
978
- name: demo.name,
979
- slug: demo.slug,
980
- summary: demo.summary,
981
- ...(photo === undefined ? {} : { photo }),
982
- },
983
- blocks: { blocks: storeCategoryBlocks(demo).map(toBlockZoneEntry) },
984
- });
985
- }
986
- for (const demo of STORE_DEMO_PRODUCTS) {
987
- const photo = media[`product-${demo.slug}`];
988
- await productStore.create({
989
- status: 'published',
990
- createdBy: adminId,
991
- values: {
992
- name: demo.name,
993
- slug: demo.slug,
994
- description: demo.description,
995
- price: demo.price,
996
- currency: 'EUR',
997
- category: demo.category,
998
- inStock: demo.inStock,
999
- material: demo.material,
1000
- dimensions: demo.dimensions,
1001
- ...(demo.weight === undefined ? {} : { weight: demo.weight }),
1002
- ...(demo.capacity === undefined ? {} : { capacity: demo.capacity }),
1003
- origin: demo.origin,
1004
- care: demo.care,
1005
- delivery: demo.delivery,
1006
- orderLink: orderLinkFor(siteName, demo.name),
1007
- ...(photo === undefined ? {} : { photo }),
1008
- },
1009
- blocks: { blocks: storeProductBlocks(demo).map(toBlockZoneEntry) },
1010
- });
1011
- }
1012
- for (const demo of buildStoreDemoPages({ siteName, media })) {
1013
- await pageStore.create({
1014
- status: 'published',
1015
- createdBy: adminId,
1016
- values: { title: demo.title, slug: demo.slug },
1017
- blocks: { blocks: demo.blocks.map(toBlockZoneEntry) },
1018
- });
1019
- }
634
+ function seedStoreDemoContent(copy) {
635
+ return async (ctx) => {
636
+ const { db, defaultLocale, adminId, media } = ctx;
637
+ const siteName = nameOf(ctx.siteName);
638
+ const model = storeSchema(copy);
639
+ const categoryStore = createContentStore({ db, collection: model.category, defaultLocale });
640
+ const productStore = createContentStore({ db, collection: model.product, defaultLocale });
641
+ const pageStore = createContentStore({ db, collection: model.page, defaultLocale });
642
+ for (const demo of copy.categories) {
643
+ const photo = media[`category-${demo.id}`];
644
+ await categoryStore.create({
645
+ status: 'published',
646
+ createdBy: adminId,
647
+ values: {
648
+ name: demo.name,
649
+ slug: demo.slug,
650
+ summary: demo.summary,
651
+ ...(photo === undefined ? {} : { photo }),
652
+ },
653
+ blocks: { blocks: storeCategoryBlocks(demo).map(toBlockZoneEntry) },
654
+ });
655
+ }
656
+ for (const demo of copy.products) {
657
+ const photo = media[`product-${demo.key}`];
658
+ await productStore.create({
659
+ status: 'published',
660
+ createdBy: adminId,
661
+ values: {
662
+ name: demo.name,
663
+ slug: demo.slug,
664
+ description: demo.description,
665
+ price: demo.price,
666
+ currency: 'EUR',
667
+ category: categoryOf(copy, demo.category).name,
668
+ inStock: demo.inStock,
669
+ material: demo.material,
670
+ dimensions: demo.dimensions,
671
+ ...(demo.weight === undefined ? {} : { weight: demo.weight }),
672
+ ...(demo.capacity === undefined ? {} : { capacity: demo.capacity }),
673
+ origin: demo.origin,
674
+ care: demo.care,
675
+ delivery: demo.delivery,
676
+ orderLink: orderLinkFor(siteName, demo.name, copy.locale),
677
+ ...(photo === undefined ? {} : { photo }),
678
+ },
679
+ blocks: { blocks: storeProductBlocks(copy, demo).map(toBlockZoneEntry) },
680
+ });
681
+ }
682
+ for (const demo of buildStoreDemoPages({ siteName, media, locale: copy.locale })) {
683
+ await pageStore.create({
684
+ status: 'published',
685
+ createdBy: adminId,
686
+ values: { title: demo.title, slug: demo.slug },
687
+ blocks: { blocks: demo.blocks.map(toBlockZoneEntry) },
688
+ });
689
+ }
690
+ };
1020
691
  }
1021
- export const storeContentPack = {
1022
- collections: STORE_COLLECTIONS,
1023
- recommendedAgents: STORE_RECOMMENDED_AGENTS,
1024
- seedDemoContent: seedStoreDemoContent,
1025
- defaultTheme: '@cogenta/theme-ecommerce',
1026
- menus: STORE_MENUS,
1027
- widgets: STORE_WIDGETS,
1028
- siteSettings: STORE_SITE_SETTINGS,
1029
- mediaSpecs: STORE_MEDIA_SPECS,
1030
- };
692
+ /** The whole blueprint, in one language. */
693
+ export function createStoreContentPack(locale) {
694
+ const copy = storeCopyFor(locale);
695
+ return {
696
+ collections: storeSchema(copy).collections,
697
+ recommendedAgents: STORE_RECOMMENDED_AGENTS,
698
+ seedDemoContent: seedStoreDemoContent(copy),
699
+ defaultTheme: '@cogenta/theme-ecommerce',
700
+ menus: storeMenus(copy),
701
+ widgets: storeWidgets(copy),
702
+ siteSettings: storeSiteSettings(copy),
703
+ mediaSpecs: storeMediaSpecs(copy),
704
+ };
705
+ }
706
+ /** The English pack, which `BLUEPRINT_CONTENT_PACKS` lists; `contentPackFor` picks by locale. */
707
+ export const storeContentPack = createStoreContentPack('en');
1031
708
  //# sourceMappingURL=store.js.map