@rovela-ai/sdk 0.19.4 → 0.19.6

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 (236) hide show
  1. package/dist/admin/components/AdminPageHeader.d.ts.map +1 -1
  2. package/dist/admin/components/AdminPageHeader.js +9 -2
  3. package/dist/admin/components/AdminPageHeader.js.map +1 -1
  4. package/dist/admin/components/AdminUserMenu.d.ts.map +1 -1
  5. package/dist/admin/components/AdminUserMenu.js +2 -1
  6. package/dist/admin/components/AdminUserMenu.js.map +1 -1
  7. package/dist/admin/components/CustomerDetails.d.ts.map +1 -1
  8. package/dist/admin/components/CustomerDetails.js +2 -1
  9. package/dist/admin/components/CustomerDetails.js.map +1 -1
  10. package/dist/admin/components/EmailsManager.d.ts.map +1 -1
  11. package/dist/admin/components/EmailsManager.js +2 -1
  12. package/dist/admin/components/EmailsManager.js.map +1 -1
  13. package/dist/admin/components/LowStockAlert.d.ts.map +1 -1
  14. package/dist/admin/components/LowStockAlert.js +3 -2
  15. package/dist/admin/components/LowStockAlert.js.map +1 -1
  16. package/dist/admin/components/OrderDetails.d.ts.map +1 -1
  17. package/dist/admin/components/OrderDetails.js +2 -1
  18. package/dist/admin/components/OrderDetails.js.map +1 -1
  19. package/dist/admin/components/ProductTable.d.ts.map +1 -1
  20. package/dist/admin/components/ProductTable.js +4 -3
  21. package/dist/admin/components/ProductTable.js.map +1 -1
  22. package/dist/admin/components/RecentOrders.d.ts.map +1 -1
  23. package/dist/admin/components/RecentOrders.js +2 -1
  24. package/dist/admin/components/RecentOrders.js.map +1 -1
  25. package/dist/admin/components/SEOPreview.d.ts +2 -8
  26. package/dist/admin/components/SEOPreview.d.ts.map +1 -1
  27. package/dist/admin/components/SEOPreview.js +32 -5
  28. package/dist/admin/components/SEOPreview.js.map +1 -1
  29. package/dist/admin/components/SecondaryMetricsRow.d.ts.map +1 -1
  30. package/dist/admin/components/SecondaryMetricsRow.js +3 -2
  31. package/dist/admin/components/SecondaryMetricsRow.js.map +1 -1
  32. package/dist/admin/components/StatsCards.d.ts.map +1 -1
  33. package/dist/admin/components/StatsCards.js +2 -1
  34. package/dist/admin/components/StatsCards.js.map +1 -1
  35. package/docs/changelog/README.md +53 -0
  36. package/docs/changelog/epoch-01-chrome-consent.md +63 -0
  37. package/docs/changelog/epoch-02-platform-commerce.md +108 -0
  38. package/docs/changelog/epoch-03-i18n-files.md +72 -0
  39. package/docs/changelog/epoch-04-emails.md +65 -0
  40. package/docs/changelog/epoch-05-admin-experience.md +98 -0
  41. package/docs/changelog/epoch-06-mobile-integrity.md +92 -0
  42. package/docs/design/admin-ledger-visual-universe.html +1961 -0
  43. package/docs/design/admin-sidebar-and-band.html +542 -0
  44. package/package.json +3 -1
  45. package/templates/store-template/.claude/skills/add-section/SKILL.md +438 -0
  46. package/templates/store-template/.claude/skills/build-feature/SKILL.md +201 -0
  47. package/templates/store-template/.claude/skills/customize-theme/SKILL.md +167 -0
  48. package/templates/store-template/.claude/skills/debug-errors/SKILL.md +68 -0
  49. package/templates/store-template/.claude/skills/frontend-design/SKILL.md +176 -0
  50. package/templates/store-template/.claude/skills/generate-images/SKILL.md +115 -0
  51. package/templates/store-template/.claude/skills/manage-products/SKILL.md +187 -0
  52. package/templates/store-template/.claude/skills/override-sdk-component/SKILL.md +154 -0
  53. package/templates/store-template/.env.example +50 -0
  54. package/templates/store-template/.mcp.json +8 -0
  55. package/templates/store-template/.rovela/blueprint.example.json +190 -0
  56. package/templates/store-template/CLAUDE.md +14 -0
  57. package/templates/store-template/app/LayoutContent.tsx +106 -0
  58. package/templates/store-template/app/[...path]/page.tsx +79 -0
  59. package/templates/store-template/app/account/addresses/page.tsx +45 -0
  60. package/templates/store-template/app/account/layout.tsx +17 -0
  61. package/templates/store-template/app/account/orders/[id]/invoice/page.tsx +277 -0
  62. package/templates/store-template/app/account/orders/[id]/page.tsx +725 -0
  63. package/templates/store-template/app/account/orders/page.tsx +153 -0
  64. package/templates/store-template/app/account/page.tsx +184 -0
  65. package/templates/store-template/app/account/profile/page.tsx +434 -0
  66. package/templates/store-template/app/admin/(dashboard)/account/page.tsx +16 -0
  67. package/templates/store-template/app/admin/(dashboard)/analytics/events/page.tsx +14 -0
  68. package/templates/store-template/app/admin/(dashboard)/analytics/layout.tsx +48 -0
  69. package/templates/store-template/app/admin/(dashboard)/analytics/page.tsx +15 -0
  70. package/templates/store-template/app/admin/(dashboard)/analytics/visitors/page.tsx +14 -0
  71. package/templates/store-template/app/admin/(dashboard)/categories/[id]/page.tsx +38 -0
  72. package/templates/store-template/app/admin/(dashboard)/categories/new/page.tsx +35 -0
  73. package/templates/store-template/app/admin/(dashboard)/categories/page.tsx +223 -0
  74. package/templates/store-template/app/admin/(dashboard)/customers/[id]/page.tsx +26 -0
  75. package/templates/store-template/app/admin/(dashboard)/customers/page.tsx +33 -0
  76. package/templates/store-template/app/admin/(dashboard)/discounts/page.tsx +16 -0
  77. package/templates/store-template/app/admin/(dashboard)/emails/page.tsx +16 -0
  78. package/templates/store-template/app/admin/(dashboard)/files/page.tsx +16 -0
  79. package/templates/store-template/app/admin/(dashboard)/layout.tsx +44 -0
  80. package/templates/store-template/app/admin/(dashboard)/loading.tsx +88 -0
  81. package/templates/store-template/app/admin/(dashboard)/locations/page.tsx +16 -0
  82. package/templates/store-template/app/admin/(dashboard)/orders/[id]/page.tsx +66 -0
  83. package/templates/store-template/app/admin/(dashboard)/orders/page.tsx +26 -0
  84. package/templates/store-template/app/admin/(dashboard)/page.tsx +146 -0
  85. package/templates/store-template/app/admin/(dashboard)/payments/page.tsx +15 -0
  86. package/templates/store-template/app/admin/(dashboard)/products/[id]/page.tsx +38 -0
  87. package/templates/store-template/app/admin/(dashboard)/products/new/page.tsx +35 -0
  88. package/templates/store-template/app/admin/(dashboard)/products/page.tsx +31 -0
  89. package/templates/store-template/app/admin/(dashboard)/settings/page.tsx +46 -0
  90. package/templates/store-template/app/admin/(dashboard)/shipping/page.tsx +15 -0
  91. package/templates/store-template/app/admin/(dashboard)/tax/page.tsx +15 -0
  92. package/templates/store-template/app/admin/(dashboard)/users/[id]/page.tsx +114 -0
  93. package/templates/store-template/app/admin/(dashboard)/users/page.tsx +16 -0
  94. package/templates/store-template/app/admin/accept-invite/page.tsx +36 -0
  95. package/templates/store-template/app/admin/forgot-password/page.tsx +13 -0
  96. package/templates/store-template/app/admin/layout.tsx +47 -0
  97. package/templates/store-template/app/admin/login/page.tsx +528 -0
  98. package/templates/store-template/app/admin/reset-password/page.tsx +36 -0
  99. package/templates/store-template/app/api/account/addresses/[id]/route.ts +10 -0
  100. package/templates/store-template/app/api/account/addresses/route.ts +10 -0
  101. package/templates/store-template/app/api/account/change-password/route.ts +107 -0
  102. package/templates/store-template/app/api/account/orders/[id]/refund/route.ts +11 -0
  103. package/templates/store-template/app/api/account/orders/[id]/return/route.ts +14 -0
  104. package/templates/store-template/app/api/account/orders/[id]/route.ts +42 -0
  105. package/templates/store-template/app/api/account/orders/route.ts +29 -0
  106. package/templates/store-template/app/api/account/profile/route.ts +165 -0
  107. package/templates/store-template/app/api/admin/accept-invite/route.ts +11 -0
  108. package/templates/store-template/app/api/admin/analytics/events/route.ts +9 -0
  109. package/templates/store-template/app/api/admin/analytics/route.ts +10 -0
  110. package/templates/store-template/app/api/admin/analytics/visitors/route.ts +9 -0
  111. package/templates/store-template/app/api/admin/branding/favicon/route.ts +9 -0
  112. package/templates/store-template/app/api/admin/branding/logo/route.ts +9 -0
  113. package/templates/store-template/app/api/admin/categories/[id]/route.ts +9 -0
  114. package/templates/store-template/app/api/admin/categories/route.ts +9 -0
  115. package/templates/store-template/app/api/admin/check/route.ts +10 -0
  116. package/templates/store-template/app/api/admin/customer-groups/[id]/route.ts +10 -0
  117. package/templates/store-template/app/api/admin/customer-groups/route.ts +10 -0
  118. package/templates/store-template/app/api/admin/customers/[id]/addresses/[addressId]/route.ts +15 -0
  119. package/templates/store-template/app/api/admin/customers/[id]/addresses/route.ts +15 -0
  120. package/templates/store-template/app/api/admin/customers/[id]/route.ts +11 -0
  121. package/templates/store-template/app/api/admin/customers/bulk/route.ts +8 -0
  122. package/templates/store-template/app/api/admin/customers/route.ts +9 -0
  123. package/templates/store-template/app/api/admin/discounts/[id]/route.ts +11 -0
  124. package/templates/store-template/app/api/admin/discounts/route.ts +10 -0
  125. package/templates/store-template/app/api/admin/emails/preview/route.ts +4 -0
  126. package/templates/store-template/app/api/admin/emails/route.ts +5 -0
  127. package/templates/store-template/app/api/admin/emails/test/route.ts +4 -0
  128. package/templates/store-template/app/api/admin/files/route.ts +8 -0
  129. package/templates/store-template/app/api/admin/forgot-password/route.ts +7 -0
  130. package/templates/store-template/app/api/admin/linked-customer/route.ts +11 -0
  131. package/templates/store-template/app/api/admin/locations/[id]/route.ts +10 -0
  132. package/templates/store-template/app/api/admin/locations/route.ts +10 -0
  133. package/templates/store-template/app/api/admin/me/password/route.ts +13 -0
  134. package/templates/store-template/app/api/admin/me/route.ts +11 -0
  135. package/templates/store-template/app/api/admin/orders/[id]/refund/route.ts +7 -0
  136. package/templates/store-template/app/api/admin/orders/[id]/return/approve/route.ts +7 -0
  137. package/templates/store-template/app/api/admin/orders/[id]/return/reject/route.ts +7 -0
  138. package/templates/store-template/app/api/admin/orders/[id]/route.ts +9 -0
  139. package/templates/store-template/app/api/admin/orders/[id]/ship-with-shippo/route.ts +6 -0
  140. package/templates/store-template/app/api/admin/orders/[id]/shippo-rates/route.ts +6 -0
  141. package/templates/store-template/app/api/admin/orders/bulk/route.ts +8 -0
  142. package/templates/store-template/app/api/admin/orders/route.ts +9 -0
  143. package/templates/store-template/app/api/admin/payment-methods/[id]/route.ts +10 -0
  144. package/templates/store-template/app/api/admin/payment-methods/route.ts +10 -0
  145. package/templates/store-template/app/api/admin/products/[id]/route.ts +9 -0
  146. package/templates/store-template/app/api/admin/products/bulk/route.ts +9 -0
  147. package/templates/store-template/app/api/admin/products/route.ts +9 -0
  148. package/templates/store-template/app/api/admin/products/stats/route.ts +10 -0
  149. package/templates/store-template/app/api/admin/reset-password/route.ts +10 -0
  150. package/templates/store-template/app/api/admin/settings/route.ts +11 -0
  151. package/templates/store-template/app/api/admin/setup/route.ts +10 -0
  152. package/templates/store-template/app/api/admin/setup-guide/manual-mark/route.ts +13 -0
  153. package/templates/store-template/app/api/admin/setup-guide/route.ts +10 -0
  154. package/templates/store-template/app/api/admin/shipping/carriers/[id]/route.ts +9 -0
  155. package/templates/store-template/app/api/admin/shipping/carriers/route.ts +9 -0
  156. package/templates/store-template/app/api/admin/shipping/rates/[id]/route.ts +9 -0
  157. package/templates/store-template/app/api/admin/shipping/rates/route.ts +9 -0
  158. package/templates/store-template/app/api/admin/shipping/shippo/api-key/route.ts +1 -0
  159. package/templates/store-template/app/api/admin/shipping/shippo/validate/route.ts +1 -0
  160. package/templates/store-template/app/api/admin/shipping/zones/[id]/route.ts +9 -0
  161. package/templates/store-template/app/api/admin/shipping/zones/route.ts +9 -0
  162. package/templates/store-template/app/api/admin/stats/route.ts +9 -0
  163. package/templates/store-template/app/api/admin/stripe-status/route.ts +1 -0
  164. package/templates/store-template/app/api/admin/tax-zones/[id]/route.ts +7 -0
  165. package/templates/store-template/app/api/admin/tax-zones/route.ts +7 -0
  166. package/templates/store-template/app/api/admin/users/[id]/route.ts +14 -0
  167. package/templates/store-template/app/api/admin/users/route.ts +12 -0
  168. package/templates/store-template/app/api/admin-auth/[...nextauth]/route.ts +17 -0
  169. package/templates/store-template/app/api/analytics/track/route.ts +12 -0
  170. package/templates/store-template/app/api/auth/[...nextauth]/route.ts +19 -0
  171. package/templates/store-template/app/api/auth/forgot-password/route.ts +9 -0
  172. package/templates/store-template/app/api/auth/register/route.ts +9 -0
  173. package/templates/store-template/app/api/auth/resend-verification/route.ts +9 -0
  174. package/templates/store-template/app/api/auth/reset-password/route.ts +10 -0
  175. package/templates/store-template/app/api/auth/verify-email/route.ts +10 -0
  176. package/templates/store-template/app/api/categories/route.ts +10 -0
  177. package/templates/store-template/app/api/checkout/countries/route.ts +7 -0
  178. package/templates/store-template/app/api/checkout/discount/route.ts +9 -0
  179. package/templates/store-template/app/api/checkout/manual/route.ts +10 -0
  180. package/templates/store-template/app/api/checkout/payment-methods/route.ts +8 -0
  181. package/templates/store-template/app/api/checkout/pickup-locations/route.ts +8 -0
  182. package/templates/store-template/app/api/checkout/route.ts +10 -0
  183. package/templates/store-template/app/api/checkout/shipping/route.ts +21 -0
  184. package/templates/store-template/app/api/checkout/status/route.ts +10 -0
  185. package/templates/store-template/app/api/contact/route.ts +164 -0
  186. package/templates/store-template/app/api/media/presign/route.ts +7 -0
  187. package/templates/store-template/app/api/media/route.ts +7 -0
  188. package/templates/store-template/app/api/products/[slug]/route.ts +10 -0
  189. package/templates/store-template/app/api/products/route.ts +10 -0
  190. package/templates/store-template/app/api/store/settings/route.ts +12 -0
  191. package/templates/store-template/app/api/webhooks/stripe/route.ts +63 -0
  192. package/templates/store-template/app/auth/forgot-password/page.tsx +38 -0
  193. package/templates/store-template/app/auth/layout.tsx +17 -0
  194. package/templates/store-template/app/auth/reset-password/page.tsx +81 -0
  195. package/templates/store-template/app/auth/signin/page.tsx +62 -0
  196. package/templates/store-template/app/auth/signup/page.tsx +38 -0
  197. package/templates/store-template/app/auth/verify-email/page.tsx +185 -0
  198. package/templates/store-template/app/cart/page.tsx +137 -0
  199. package/templates/store-template/app/checkout/page.tsx +88 -0
  200. package/templates/store-template/app/checkout/success/page.tsx +50 -0
  201. package/templates/store-template/app/contact/layout.tsx +24 -0
  202. package/templates/store-template/app/contact/page.tsx +321 -0
  203. package/templates/store-template/app/faq/page.tsx +153 -0
  204. package/templates/store-template/app/globals.css +99 -0
  205. package/templates/store-template/app/layout.tsx +269 -0
  206. package/templates/store-template/app/not-found.tsx +35 -0
  207. package/templates/store-template/app/page.tsx +23 -0
  208. package/templates/store-template/app/privacy/page.tsx +281 -0
  209. package/templates/store-template/app/products/[slug]/ProductDetailClient.tsx +179 -0
  210. package/templates/store-template/app/products/[slug]/page.tsx +149 -0
  211. package/templates/store-template/app/products/layout.tsx +26 -0
  212. package/templates/store-template/app/products/page.tsx +102 -0
  213. package/templates/store-template/app/robots.ts +25 -0
  214. package/templates/store-template/app/sitemap.ts +76 -0
  215. package/templates/store-template/app/terms/page.tsx +313 -0
  216. package/templates/store-template/components/PathSyncBridge.tsx +61 -0
  217. package/templates/store-template/components/Providers.tsx +37 -0
  218. package/templates/store-template/components/layout/Footer.tsx +150 -0
  219. package/templates/store-template/components/layout/Header.tsx +162 -0
  220. package/templates/store-template/components/sections/.gitkeep +7 -0
  221. package/templates/store-template/components/sections/CTA.tsx +51 -0
  222. package/templates/store-template/components/sections/Features.tsx +91 -0
  223. package/templates/store-template/components/sections/Hero.tsx +85 -0
  224. package/templates/store-template/eslint.config.mjs +18 -0
  225. package/templates/store-template/lib/store-config.ts +77 -0
  226. package/templates/store-template/lib/store-policy.ts +68 -0
  227. package/templates/store-template/lib/utils.ts +21 -0
  228. package/templates/store-template/next-env.d.ts +6 -0
  229. package/templates/store-template/next.config.js +105 -0
  230. package/templates/store-template/package.json +32 -0
  231. package/templates/store-template/postcss.config.js +6 -0
  232. package/templates/store-template/proxy.ts +150 -0
  233. package/templates/store-template/public/rovela-logo.png +0 -0
  234. package/templates/store-template/tailwind.config.ts +74 -0
  235. package/templates/store-template/tsconfig.json +41 -0
  236. package/templates/store-template/types/next-auth.d.ts +32 -0
@@ -0,0 +1,108 @@
1
+ # E2 Storefront platform & commerce core — 0.5.2..0.9.2
2
+
3
+ ## What landed
4
+ First-party storefront analytics, path-bar sync, the storefront SEO/GEO
5
+ overhaul (canonical-host redirect, JSON-LD, per-store llms.txt), zone-native
6
+ free shipping — and the ENTIRE commerce core: server-priced checkout
7
+ (`buildQuote`), manual payment methods, the native discounts engine,
8
+ customer accounts/addresses/groups, click & collect, and group-gated
9
+ visibility.
10
+
11
+ ## SDK-internal (free via pin bump)
12
+ The analytics module (`AnalyticsProvider`, admin Dashboards/Events/Visitors
13
+ views), the whole checkout pricing core, payment-methods/discounts/groups/
14
+ locations managers, address book, `OrderTimeline`, bulk-selection
15
+ primitives. All mounted from the SDK — a pin bump delivers the machinery;
16
+ the NEW SURFACES below make it reachable.
17
+
18
+ ## Template contract
19
+ - `app/LayoutContent.tsx` — INTENT: the customer branch mounts
20
+ `<AnalyticsProvider>` (from `@rovela-ai/sdk/analytics`) INSIDE
21
+ `CookieConsentProvider` (consent-gated ingestion), wrapping
22
+ `<CartProvider>`. Also mounts `<PathSyncBridge />` (a small local client
23
+ component posting `rovela:navigation` to the platform iframe parent —
24
+ copy from the stock reference or create per its ~30-line contract).
25
+ - `proxy.ts` — CREATED in this epoch: canonical-host 308 redirect
26
+ (collapses `*.rovela.app`/`*.vercel.app` onto a verified custom domain;
27
+ inert without one). If the store has NO proxy.ts, add the stock one.
28
+ - `next.config.js` — adds a headers() rule serving `/llms.txt` as
29
+ markdown + noindex. Additive.
30
+ - `app/layout.tsx` — enriched Organization/WebSite JSON-LD. Additive;
31
+ adopt only if the store's layout is stock-shaped or the merchant wants
32
+ the SEO surfaces.
33
+
34
+ ## Behavior contracts
35
+ 1. **Checkout is server-priced (`buildQuote` is the ONLY money source).**
36
+ Client-submitted amounts/customerId/groupId are ignored or rejected
37
+ (`PricingError` → 4xx). Custom checkout code that POSTs its own totals
38
+ or passes `customerId` in the body must be reworked to let the server
39
+ price (catalog price + discounts + shipping + tax) and to rely on the
40
+ session for identity.
41
+ 2. **Native discounts replace Stripe coupons as the merchant surface.**
42
+ Legacy Stripe-coupon helpers still exist (feature-card usage) but the
43
+ admin Discounts manager + `/api/checkout/discount` are the system now.
44
+ 3. **`orders.payment_provider`** (default 'stripe') exists — custom order
45
+ readers must not assume every order is a Stripe order (manual methods
46
+ create `pending` orders with `manual_*` idempotency keys).
47
+ 4. **Free shipping is a PER-ZONE rate** (0.5.5). The global
48
+ `free_shipping_threshold` column is dormant/display-only — checkout no
49
+ longer injects a synthetic free-shipping line from it.
50
+ 5. Analytics ingestion is CONSENT-GATED — do not mount AnalyticsProvider
51
+ outside CookieConsentProvider.
52
+
53
+ ## Custom-code hazards (greps)
54
+ - `grep -rn "free_shipping_threshold\|freeShippingThreshold" app/ components/ lib/` —
55
+ any custom logic treating it as checkout-enforced must be re-pointed at
56
+ per-zone rates (a zero-price rate with min_order_amount).
57
+ - `grep -rn "customerId" app/checkout app/api/checkout components/checkout 2>/dev/null` —
58
+ custom checkout paths passing client identity must drop it (server
59
+ resolves via session).
60
+ - `grep -rn "createCheckoutSession\|/api/checkout" app/ components/ | grep -v node_modules` —
61
+ verify custom callers send items + selections only, never totals.
62
+ - `grep -rn "status === 'paid'\|paymentIntent" app/ components/ lib/` —
63
+ order readers should tolerate `payment_provider !== 'stripe'` and
64
+ `pending` manual orders.
65
+
66
+ ## DB (ALL self-heal — pre-applying the idempotent ALTERs is optional)
67
+ `analytics_events` (ensureAnalyticsTable) · `customer_addresses` +
68
+ `customers.phone/updated_at` (ensureCustomerAddressSchema) ·
69
+ `customer_groups` + `customers.group_id` (ensureCustomerGroupsSchema, wired
70
+ into every customer read incl. login) · `payment_methods` +
71
+ `orders.payment_provider/payment_method_*` (ensurePaymentMethodsSchema) ·
72
+ `discounts` + `discount_redemptions` (ensureDiscountsSchema) ·
73
+ `store_locations` + `orders.pickup_location_id` (ensureStoreLocationsSchema)
74
+ · `visible_to_groups` on payment_methods/shipping_rates/tax_zones
75
+ (ensureVisibilityColumns) · `store_settings.store_country`,
76
+ `orders.currency` snapshot.
77
+
78
+ ## New surfaces (thin mounts to ADD if absent, wired through THIS store's
79
+ dashboard layout + navItems — never assume stock structure)
80
+ - `/admin/analytics` (+ `/events`, `/visitors`, shared layout) and
81
+ `/api/admin/analytics/*` + `/api/analytics/track`
82
+ - `/admin/locations` + `/api/admin/locations/*` + `/api/checkout/pickup-locations`
83
+ - `/api/account/addresses*`, `/api/admin/customers/[id]/addresses*`
84
+ - `/api/admin/customer-groups*`, `/api/admin/payment-methods*`,
85
+ `/api/admin/discounts*`, `/api/checkout/{manual,payment-methods,discount}`
86
+ - `/api/admin/{customers,orders,products}/bulk`
87
+ (Each is a 1–15 line re-export of SDK handlers — see the stock reference.)
88
+
89
+ ## Existing components that gained dependencies (silent-degradation risk)
90
+ An SDK component the store ALREADY mounts now calls a NEW route — if that
91
+ route is missing the component renders but silently does nothing. These are
92
+ NOT "new surfaces" (the page already exists); they're new wiring under a page
93
+ you must not miss:
94
+ - `<PaymentSettings>` (admin payments page) now reads/writes
95
+ `/api/admin/payment-methods*` — without it the manual-methods manager loads
96
+ empty and saves fail.
97
+ - `<CheckoutFlow>` (storefront checkout) now calls
98
+ `/api/checkout/{manual,payment-methods,discount}` — without them the payment
99
+ step shows no manual methods and discount codes never validate.
100
+
101
+ ## Verify
102
+ - `/admin/analytics` renders its three tabs; a storefront visit with
103
+ consent accepted records an event.
104
+ - Checkout end-to-end: a cart prices server-side; a discount code
105
+ previews; the payment step shows Stripe (+ any manual methods).
106
+ - `/admin/locations` loads; storefront picks up pickup only when a
107
+ pickup-enabled location exists.
108
+ - Custom domain stores: apex/vercel hosts 308 to the canonical domain.
@@ -0,0 +1,72 @@
1
+ # E3 Languages & files — 0.10.0..0.13.1
2
+
3
+ ## What landed
4
+ Native multilingual storefronts (§61): path-prefix locale routing
5
+ (`/en/...`), key-symmetric UI catalogs, per-locale catalog content
6
+ overlays, hreflang alternates, the admin Languages toggle — plus the admin
7
+ files library (§60).
8
+
9
+ ## SDK-internal (free via pin bump)
10
+ The whole `core/i18n` module (`useT`/`getT`, `LocaleLink`/`useLocalePath`,
11
+ `LanguageSwitcher`, catalog overlay `localizeCatalogRow`), the
12
+ `@rovela-ai/sdk/locales` edge-safe subpath, `FilesManager` +
13
+ `MediaLibraryPicker`, the Settings → Languages control. A store that skips
14
+ the template migration stays single-language and loses nothing.
15
+
16
+ ## Template contract (the i18n adoption — the ONE structural migration)
17
+ Adopting multilingual requires reshaping three files BY INTENT:
18
+ - `proxy.ts` — parse a leading locale prefix (`/en|/fr…` from
19
+ `SUPPORTED_LOCALES` in `@rovela-ai/sdk/locales`), rewrite to the bare
20
+ path, and set `x-rovela-locale` / `x-rovela-geo-locale` /
21
+ `x-rovela-pathname` headers. `/api` and `/admin` are NEVER localized.
22
+ Keep the store's existing canonical-host logic intact.
23
+ - `app/layout.tsx` — resolve the request locale server-side
24
+ (`resolveStoreLocaleConfig`, `resolveRequestLocale`,
25
+ `resolveLocaleRedirect` from `@rovela-ai/sdk/core`; `localizedAlternates`
26
+ from `core/server`): 308 `permanentRedirect` for structural strips
27
+ (disabled/unknown/default-locale prefixes), temporary redirect for
28
+ preference hops; thread `locale`/`defaultLocale`/`enabledLocales` down.
29
+ - `app/LayoutContent.tsx` — accept those props and wrap the WHOLE tree in
30
+ `<RovelaLocaleProvider>` (OUTSIDE CookieConsentProvider). HYDRATION RULE
31
+ (load-bearing): locale config must come from these server-resolved props,
32
+ NEVER from a client fetch — a late fetch mis-resolves the default locale
33
+ at first paint and bounces hard loads of prefixed URLs.
34
+ If this store's layout/LayoutContent are heavily customized, graft the
35
+ locale resolution AROUND the customizations — the provider nesting order
36
+ and the server-threaded props are the contract; everything else is theirs.
37
+
38
+ ## Behavior contracts
39
+ - Internal links in multilingual stores go through `LocaleLink` /
40
+ `useLocalePath` — a bare `<Link href="/products">` drops the prefix.
41
+ - New user-visible strings on a multilingual store must exist in EVERY
42
+ enabled locale (store dictionary pattern — CLAUDE.md §5.5).
43
+ - Latent `formatPrice` hazard EXISTS IN THIS ERA'S SDK (integers > 100
44
+ treated as cents) — it is FIXED in E5; see E5's money contract for the
45
+ post-update behavior.
46
+ - Menu labels: a translated `section.name` now beats a hand-set
47
+ `meta.label`.
48
+
49
+ ## Custom-code hazards (greps)
50
+ - On stores adopting i18n: `grep -rn "href=\"/" app/ components/ | grep -v admin | grep -v api` —
51
+ storefront internal links should migrate to `LocaleLink` (mechanical but
52
+ wide; scope to nav/header/footer/product cards first).
53
+ - `grep -rn "useSearchParams\|usePathname" components/` — custom routing
54
+ logic may need the locale-stripped pathname (`x-rovela-pathname`).
55
+
56
+ ## DB (self-heal)
57
+ `products.translations` + `categories.translations`
58
+ (ensureCatalogTranslationsSchema) · `store_settings.default_locale` +
59
+ `enabled_locales` (settings ensure) · `orders.locale` / `customers.locale`.
60
+
61
+ ## New surfaces
62
+ - `/admin/files` + `/api/admin/files` (files library — thin mounts).
63
+ - Languages control lives INSIDE Settings (no new route).
64
+
65
+ ## Verify
66
+ - Single-language store post-update: storefront byte-identical behavior,
67
+ no locale prefixes anywhere.
68
+ - If multilingual was adopted: `/xx/products` renders translated UI, bare
69
+ paths serve the default locale, `/admin` and `/api` unaffected,
70
+ hreflang alternates emitted, hard-load of a prefixed checkout URL does
71
+ NOT bounce to the bare path.
72
+ - `/admin/files` lists the store's media.
@@ -0,0 +1,65 @@
1
+ # E4 Email editor — 0.14.0..0.15.2
2
+
3
+ ## What landed
4
+ The merchant email editor (§62): every transactional email brand-themed
5
+ from the store's blueprint, block-editable per language, testable, plus
6
+ merchant-created custom emails.
7
+
8
+ ## SDK-internal (free via pin bump)
9
+ The entire emails module rebuild: brand-derived shared theme (full Google
10
+ Fonts), block engine + registry, `prepareEmail` overrides at the send
11
+ boundary, FR localizer, `EmailsManager` admin UI. Existing email sends keep
12
+ working untouched — no `store_emails` row means byte-identical shipped
13
+ templates (fail-open by design).
14
+
15
+ ## Template contract
16
+ - `next.config.js` — MUST gain
17
+ `outputFileTracingIncludes: { '/**': ['./.rovela/blueprint.json'] }`.
18
+ WHY: the email theme reads the blueprint at runtime through a
19
+ bundler-invisible loader; without this line, Vercel functions that don't
20
+ statically import `core/config` ship WITHOUT the blueprint and merchant
21
+ emails silently render DEFAULT branding (fail-open, no crash — easy to
22
+ miss). Anchored insert into the existing config object; preserve
23
+ everything else in the store's next.config.
24
+ - New thin mounts: `app/admin/(dashboard)/emails/page.tsx` +
25
+ `app/api/admin/emails/{route,preview/route,test/route}.ts` — 1-line
26
+ re-exports; wire the nav entry through THIS store's `navItems`.
27
+
28
+ ## Behavior contracts
29
+ - The emails module graph must stay free of static node-builtin imports
30
+ (it is client-reachable via the auth barrel; a static `fs` import fails
31
+ `next build`). Relevant only if custom code imports from
32
+ `@rovela-ai/sdk/emails` into client components — don't.
33
+ - Email amounts are decimal STRINGS end-to-end; order numbers pass through
34
+ `bareOrderNumber()` (templates add their own `#`).
35
+
36
+ ## Custom-code hazards (greps)
37
+ - `grep -rn "from '@rovela-ai/sdk/emails" app/ components/ | grep -v "api/"` —
38
+ emails imports in client components are a build hazard; move to server.
39
+ - Stores with custom email senders: they keep working; the editor covers
40
+ registry emails only.
41
+
42
+ ## DB (self-heal)
43
+ `store_emails` table (ensureStoreEmailsSchema) ·
44
+ `store_settings.email_theme` (settings ensure).
45
+
46
+ ## New surfaces
47
+ `/admin/emails` (nav: Sales → Emails) + the three API mounts above.
48
+
49
+ ## Existing components that gained dependencies (silent-degradation risk)
50
+ - Every EXISTING transactional email sender (order confirmation, shipping,
51
+ admin invites…) now renders through the brand-derived theme, which reads
52
+ `.rovela/blueprint.json` at runtime. Without the `next.config.js`
53
+ `outputFileTracingIncludes` line (Template contract above), Vercel
54
+ functions that don't statically import `core/config` ship WITHOUT the
55
+ blueprint and emails silently fall back to DEFAULT branding — no error,
56
+ no crash, just unbranded emails. The store's email code needs zero
57
+ changes; the config line is the whole dependency.
58
+
59
+ ## Verify
60
+ - `/admin/emails` lists the registry; opening one renders a themed preview
61
+ (store colors/fonts, not default green).
62
+ - Send test delivers to the signed-in admin.
63
+ - AFTER PUBLISH (Vercel only): trigger any transactional email and confirm
64
+ it renders with the store's branding — this is the
65
+ outputFileTracingIncludes check; the sandbox can't prove it.
@@ -0,0 +1,98 @@
1
+ # E5 Admin experience — 0.15.3..0.18.7
2
+
3
+ ## What landed
4
+ The complete admin redesign ("LEDGER"): Shopify-style chrome (identity top
5
+ bar + nav-only sidebar), the branding architecture (R2-truth logo/favicon),
6
+ the save-bar and toast grammars, the auth-shell front door, the settings
7
+ correctness wave (timezone, store identity, currency, cookie-consent
8
+ configurator), and the consolidation kit (one modal, one empty state, one
9
+ search input, one pagination, one switch, one status badge).
10
+
11
+ ## SDK-internal (free via pin bump)
12
+ Everything above ships through SDK components stores already mount:
13
+ `AdminLayout`/`AdminNav`/`AdminTopBar` chrome, `AdminPageHeader`,
14
+ `AdminSaveBar`+`useDirtyState`, `adminToast`+`AdminToaster` (mounted by
15
+ AdminLayout), `AdminModal`/`DeleteConfirmDialog`/`DiscardChangesModal`,
16
+ `AdminEmptyState`/`AdminSearchInput`/`AdminPagination`/`AdminSwitch`/
17
+ `OrderStatusBadge`, `AdminAuthShell`, `BrandingAssetUpload` (logo+favicon),
18
+ `CookieBannerConfigurator`, the rebuilt Products/Orders/Customers tables,
19
+ dashboard metrics, `useAdminDates`. Old inline patterns keep compiling
20
+ (`AdminToast` component, `LogoUpload` remain exported for back-compat) —
21
+ they are DEPRECATED in favor of the kit but never break.
22
+
23
+ ## Template contract
24
+ - `app/admin/layout.tsx` — INTENT: the admin segment loads Plus Jakarta
25
+ Sans via `next/font` exposing `--admin-font-jakarta`, and declares
26
+ `export const viewport` (device-width) + `export const dynamic =
27
+ 'force-dynamic'` (admin is session-gated, never static; also silences a
28
+ benign per-page "Failed to read session" build-log block). Old stores
29
+ missing these exports still build — add them; they are additive.
30
+ - Admin auth pages (`app/admin/{login,forgot-password,reset-password,
31
+ accept-invite}/page.tsx`) — INTENT: thin mounts on the SDK's
32
+ `AdminAuthShell`-based forms. EXCEPTION: the login page's LoginForm/
33
+ SetupForm are deliberately INLINED in the template (platform postMessage
34
+ auto-login contract) — if this store's login page is the old inline
35
+ version it keeps working; update its JSX chrome only if adopting the new
36
+ look, and NEVER replace the inline forms with SDK imports.
37
+ - Branding: logo/favicon live at fixed R2 keys and mirror into
38
+ `store_settings.logo_url` / `favicon_url`; storefront + admin read
39
+ settings-first with env fallback.
40
+
41
+ ## Behavior contracts (READ CAREFULLY — the dangerous ones)
42
+ 1. **MONEY (0.18.1)**: `formatPrice` (emails + core) DROPPED the
43
+ integer-cents heuristic ("whole number > 100 means cents, divide by
44
+ 100"). Money is DECIMAL CURRENCY UNITS end-to-end (`29.99`), cents only
45
+ at the Stripe API boundary. A store whose custom code passes CENTS to
46
+ SDK formatters displayed correctly before and will display 100× after.
47
+ 2. **TIMEZONE (0.18.0)**: date rendering falls back to UTC (never
48
+ America/New_York); admin dates go through `useAdminDates` /
49
+ `formatDayLabel` in the STORE timezone; day-bucket queries use the store
50
+ timezone server-side.
51
+ 3. **Settings-first identity (0.17.0+)**: storeName/email/logo/favicon/
52
+ currency read LIVE from `store_settings` (`useStoreSettings` /
53
+ `findSettings`); `NEXT_PUBLIC_*` env is a build-time fallback only.
54
+ 4. **`orders.currency` snapshot**: order displays use the order's own
55
+ currency, not the store's current one.
56
+ 5. **Notification grammar**: events → `adminToast`; states → inline
57
+ `admin-alert`; document saves → the save bar morph (never a success
58
+ toast alongside it). Native `confirm()`/`alert()` are banned in admin.
59
+
60
+ ## Custom-code hazards (greps against THIS store's code)
61
+ - `grep -rn "formatPrice" app/ components/ lib/` — for each call site,
62
+ verify the value passed is decimal units. If the store stores/computes
63
+ cents anywhere outside a Stripe call, convert at the source (÷100 once,
64
+ where the cents enter) — do NOT reintroduce a display heuristic.
65
+ - `grep -rn "toLocaleString\|toLocaleDateString\|Intl.DateTimeFormat" app/admin components/` —
66
+ admin-facing dates hardcoding a locale/timezone should move to
67
+ `useAdminDates`.
68
+ - `grep -rn "NEXT_PUBLIC_STORE_LOGO_URL\|NEXT_PUBLIC_STORE_NAME" app/ components/` —
69
+ fine as fallbacks; if used as the ONLY source in custom components,
70
+ prefer `useStoreSettings()`.
71
+ - `grep -rn "<AdminToast\b" app/ components/` — old component still works;
72
+ when touching those files anyway, migrate outcomes to `adminToast`.
73
+ - Custom admin pages built by feature cards in this store: they keep
74
+ working, but any YOU touch during this update must follow CLAUDE.md §7.6
75
+ (kit components, admin tokens, no Loader2/Sparkles).
76
+
77
+ ## DB
78
+ `store_settings` gains `store_country`, `favicon_url`, `email_theme`,
79
+ `cookie_consent` (+ locale columns from E4). ALL self-heal via
80
+ `ensureStoreSettingsSchema` at the settings chokepoints — you MAY pre-run
81
+ `ALTER TABLE store_settings ADD COLUMN IF NOT EXISTS …` for each (idempotent)
82
+ so the first post-update request is clean, but it is not required.
83
+
84
+ ## New surfaces
85
+ None route-level in this epoch (chrome replaced in place). The auth pages'
86
+ new look ships via SDK; only adopt template-side JSX if the store's pages
87
+ are stock-shaped.
88
+
89
+ ## Verify
90
+ - Admin loads with the top bar + nav-only sidebar; store name and logo tile
91
+ render (skeletons while loading, never "Admin"/"A" placeholders).
92
+ - Open a product with a known price: displays the SAME amount as before
93
+ the update (the money-contract check — if it shows 100×, a custom call
94
+ site is passing cents).
95
+ - Order detail: dates in store timezone; totals in the order's currency.
96
+ - Settings page: edit a field → save bar rises; Save → morph; no double
97
+ toast.
98
+ - Login page still auto-logs-in from the platform (if you touched it).
@@ -0,0 +1,92 @@
1
+ # E6 Mobile + integrity — 0.19.0..0.19.6
2
+
3
+ ## What landed
4
+ The save-grammar completion across every admin manager, full mobile
5
+ responsiveness for the admin, the analytics views' migration onto admin
6
+ tokens, catalog schema self-heals that ended the fresh-store outage class,
7
+ build-log hygiene, and the client-side-navigation pass (0.19.6): every
8
+ internal admin link is a soft navigation and the product SEO preview shows
9
+ the store's real identity.
10
+
11
+ ## SDK-internal (free via pin bump)
12
+ - Save bar everywhere it belongs (0.19.0): Discounts/Locations editors,
13
+ CustomerDetails edit, account profile, EmailsManager (per-locale drafts,
14
+ theme) — with `DiscardChangesModal` back-guards. ProductForm/CategoryForm
15
+ fixed: no phantom "Unsaved changes" on open (dirty baseline captured only
16
+ after the fetch), translations echoed so saves can't wipe them.
17
+ - Mobile (0.19.1): sidebar becomes an overlay drawer under 767px, modals
18
+ become bottom sheets under 640px, `admin-col-optional` columns hide under
19
+ 480px, `pointer: coarse` touch sizing, shared `scroll-lock`.
20
+ - Analytics views on admin tokens with stacked CompactTable rows (0.19.2);
21
+ Recent Orders is a stacked two-line list; Low Stock pairs 6 rows (0.19.3).
22
+ - Catalog ensures (0.19.2): `products.metafields` + `translations` and
23
+ `store_settings.public_metafield_keys` self-heal at read chokepoints —
24
+ older branches converge on first query.
25
+ - Session helpers rethrow Next's static-prerender bailout (0.19.4) instead
26
+ of logging it as a failure.
27
+ - Internal-navigation pass (0.19.6): every internal `/admin/*` link in SDK
28
+ components (AdminPageHeader back, user menu, dashboard stat cards,
29
+ Recent Orders, Low Stock, Product table, order↔customer cross-links) is
30
+ now `next/link` — a bare `<a>` forced a full document reload that
31
+ remounted the whole admin and flashed the top-bar identity to skeletons.
32
+ - SEO preview wired to real identity (0.19.6): the product form's Search
33
+ Engine Listing preview shows the store's actual name (settings), its
34
+ favicon/logo mark (shared AdminBrandTile), and the store's own domain in
35
+ a Google-style breadcrumb — replacing the "Your Store /
36
+ yourstore.com" mockup. Meta fields themselves were already wired
37
+ end-to-end (form → API → PDP metadata); this is display-only.
38
+
39
+ ## Template contract
40
+ - `app/admin/layout.tsx` — adds `export const dynamic = 'force-dynamic'`
41
+ (0.19.4) on top of E5's viewport/font. Additive; removes ~21 benign
42
+ "Failed to read session" blocks per build.
43
+ - `app/admin/(dashboard)/users/[id]/page.tsx` — the details grid became
44
+ `grid grid-cols-1 sm:grid-cols-2` (mobile). Apply the responsive prefix
45
+ if the store's copy is stock-shaped.
46
+ - `app/products/page.tsx` — one message per state: on `error`, render ONLY
47
+ the error banner and SKIP `<ProductGrid>` (its built-in empty state
48
+ doubled the message); when empty, pass the page's copy via the grid's
49
+ `emptyState` prop and delete the standalone empty block. This page is
50
+ often customized — apply the INTENT (mutually exclusive error/empty
51
+ branches), not the stock markup. If the store's version already branches
52
+ exclusively, leave it.
53
+
54
+ ## Behavior contracts
55
+ - A `<table>` never sits bare in a card: 2–4 column cards use stacked row
56
+ lists; dense tables get `overflow-x-auto` wrappers + `admin-col-optional`.
57
+ Applies to any custom admin page you touch.
58
+ - Custom admin pages must hold at 375px (CLAUDE.md §7.6 mobile rules).
59
+
60
+ ## Custom-code hazards
61
+ - `grep -rn '<a href="/admin' app/admin/ components/ 2>/dev/null` — custom
62
+ admin pages with bare internal anchors full-reload the admin on click
63
+ (top-bar identity flashes). Convert hits to `next/link`. External links
64
+ (`target="_blank"`) stay `<a>`.
65
+ - `grep -rn "text-muted-foreground\|bg-card\|border-border" app/admin/` —
66
+ storefront tokens inside custom admin pages render against the merchant
67
+ theme and now visibly clash with the admin system; migrate hits you touch
68
+ to `hsl(var(--admin-*))` / `admin-*` classes.
69
+ - `grep -rn "body.style.overflow" app/ components/` — custom overlays must
70
+ not lock scroll directly; use the SDK's shared lock (AdminModal has it
71
+ built in).
72
+ - Custom pages with `<table>` in small cards: check them at 375px.
73
+
74
+ ## DB
75
+ Nothing new; 0.19.2's ensures ADD `metafields`/`translations`/
76
+ `public_metafield_keys` on older branches automatically. Pre-running the
77
+ idempotent ALTERs is optional.
78
+
79
+ ## New surfaces
80
+ None.
81
+
82
+ ## Verify
83
+ - Resize the admin to 375px: drawer opens from the hamburger, closes on
84
+ scrim/Escape; a delete dialog docks as a bottom sheet; Products table
85
+ scrolls itself (page never scrolls horizontally); Recent Orders shows
86
+ stacked rows.
87
+ - Open a product → back via the header arrow: no full page reload, no
88
+ top-bar identity flash. The SEO section's preview shows the store's own
89
+ name, mark and domain.
90
+ - Storefront `/products`: exactly ONE message in the error state and ONE
91
+ when no products match.
92
+ - `npm run build` log: zero "Failed to read session" blocks.