create-magic-storefront 0.1.1 → 0.1.3

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 (109) hide show
  1. package/package.json +1 -1
  2. package/template/.claude/skills/storefront-design/SKILL.md +19 -8
  3. package/template/.claude/skills/storefront-verify/SKILL.md +85 -0
  4. package/template/.claude/skills/vercel-react-best-practices/AGENTS.md +3810 -0
  5. package/template/.claude/skills/vercel-react-best-practices/README.md +123 -0
  6. package/template/.claude/skills/vercel-react-best-practices/SKILL.md +149 -0
  7. package/template/.claude/skills/vercel-react-best-practices/SOURCE.md +7 -0
  8. package/template/.claude/skills/vercel-react-best-practices/metadata.json +15 -0
  9. package/template/.claude/skills/vercel-react-best-practices/rules/_sections.md +46 -0
  10. package/template/.claude/skills/vercel-react-best-practices/rules/_template.md +28 -0
  11. package/template/.claude/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md +56 -0
  12. package/template/.claude/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  13. package/template/.claude/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  14. package/template/.claude/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  15. package/template/.claude/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  16. package/template/.claude/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  17. package/template/.claude/skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
  18. package/template/.claude/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  19. package/template/.claude/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  20. package/template/.claude/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  21. package/template/.claude/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md +63 -0
  22. package/template/.claude/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
  23. package/template/.claude/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  24. package/template/.claude/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  25. package/template/.claude/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  26. package/template/.claude/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  27. package/template/.claude/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  28. package/template/.claude/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  29. package/template/.claude/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  30. package/template/.claude/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  31. package/template/.claude/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  32. package/template/.claude/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  33. package/template/.claude/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  34. package/template/.claude/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  35. package/template/.claude/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  36. package/template/.claude/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  37. package/template/.claude/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
  38. package/template/.claude/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  39. package/template/.claude/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  40. package/template/.claude/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  41. package/template/.claude/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  42. package/template/.claude/skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
  43. package/template/.claude/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  44. package/template/.claude/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  45. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  46. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  47. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  48. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  49. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  50. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  51. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  52. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
  53. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
  54. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  55. package/template/.claude/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  56. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  57. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  58. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  59. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  60. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  61. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  62. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  63. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  64. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  65. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
  66. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  67. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  68. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  69. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  70. package/template/.claude/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  71. package/template/.claude/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  72. package/template/.claude/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  73. package/template/.claude/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  74. package/template/.claude/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  75. package/template/.claude/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  76. package/template/.claude/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
  77. package/template/.claude/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md +50 -0
  78. package/template/.claude/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  79. package/template/.claude/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
  80. package/template/.claude/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  81. package/template/.claude/skills/web-interface-guidelines/LICENSE +21 -0
  82. package/template/.claude/skills/web-interface-guidelines/SKILL.md +40 -0
  83. package/template/.claude/skills/web-interface-guidelines/SOURCE.md +9 -0
  84. package/template/.claude/skills/web-interface-guidelines/guidelines.md +155 -0
  85. package/template/AGENTS.md +19 -12
  86. package/template/PAGES.md +25 -2
  87. package/template/README.md +1 -1
  88. package/template/_gitignore +1 -0
  89. package/template/app/account/page.tsx +31 -11
  90. package/template/app/cart/page.tsx +50 -54
  91. package/template/app/checkout/page.tsx +86 -38
  92. package/template/app/collections/[handle]/page.tsx +3 -2
  93. package/template/app/error.tsx +6 -4
  94. package/template/app/globals.css +29 -0
  95. package/template/app/layout.tsx +4 -2
  96. package/template/app/not-found.tsx +5 -2
  97. package/template/app/pages/[handle]/page.tsx +3 -2
  98. package/template/app/search/page.tsx +11 -6
  99. package/template/components/buy-box.tsx +7 -4
  100. package/template/components/cart-link.tsx +8 -2
  101. package/template/components/pager.tsx +3 -1
  102. package/template/components/product-grid.tsx +9 -5
  103. package/template/components/sections/banner.tsx +7 -1
  104. package/template/components/sections/deal-of-day.tsx +16 -5
  105. package/template/components/sections/product-shelves.tsx +8 -7
  106. package/template/components/sections/store-reviews.tsx +7 -5
  107. package/template/lib/errors.ts +1 -4
  108. package/template/lib/i18n.ts +315 -0
  109. package/template/llms.txt +8 -6
@@ -0,0 +1,315 @@
1
+ import type { Schema } from '@magicstoreai/storefront-client';
2
+
3
+ /**
4
+ * The storefront's own words, per language. Everything the merchant wrote (product titles,
5
+ * section titles, pages) comes translated from the API; only the interface is translated here.
6
+ * Server components pass `locale` from `lib/api.ts`, client components `useMagicStore().locale`.
7
+ */
8
+
9
+ type OrderStatus = Schema<'Order'>['status'];
10
+
11
+ function plural(
12
+ locale: string,
13
+ count: number,
14
+ forms: Partial<Record<Intl.LDMLPluralRule, string>> & { other: string },
15
+ ): string {
16
+ return forms[new Intl.PluralRules(locale).select(count)] ?? forms.other;
17
+ }
18
+
19
+ const en = {
20
+ // Navigation and shared
21
+ search: 'Search',
22
+ account: 'Account',
23
+ cart: 'Cart',
24
+ home: 'Home',
25
+ pages: 'Pages',
26
+ backToShop: 'Back to the shop',
27
+ continueShopping: 'Continue shopping',
28
+ seeAll: 'See all',
29
+ total: 'Total',
30
+ subtotal: 'Subtotal',
31
+ discount: 'Discount',
32
+ updating: 'Updating…',
33
+ // Errors
34
+ somethingWentWrong: 'Something went wrong',
35
+ tryAgainLater: 'Something went wrong. Please try again.',
36
+ tryAgain: 'Try again',
37
+ shopClosed: 'The shop is temporarily closed',
38
+ notFound: 'Page not found',
39
+ // Catalog
40
+ nothingHere: 'Nothing here yet.',
41
+ soldOut: 'Sold out',
42
+ preOrder: 'Pre-order',
43
+ sale: 'Sale',
44
+ isNew: 'New',
45
+ searchPlaceholder: 'What are you looking for?',
46
+ found: (count: number) => `${count} found`,
47
+ // Home sections
48
+ newArrivals: 'New arrivals',
49
+ onSale: 'On sale',
50
+ trending: 'Trending',
51
+ bestsellers: 'Bestsellers',
52
+ banner: 'Banner',
53
+ stockLeft: (remaining: number, initial: number) => `${remaining} of ${initial} left`,
54
+ endsAt: 'Ends',
55
+ customersSay: 'What our customers say',
56
+ reviewsCount: (count: number) =>
57
+ `${count} ${plural('en', count, { one: 'review', other: 'reviews' })}`,
58
+ recommendUs: (percent: number) => `${percent}% recommend us`,
59
+ leaveReview: 'Leave a review',
60
+ // Product
61
+ addToCart: 'Add to cart',
62
+ addedToCart: 'Added to cart.',
63
+ couldNotAdd: 'Could not add to cart.',
64
+ save: 'Save',
65
+ saved: 'Saved',
66
+ // Cart
67
+ cartEmpty: 'Your cart is empty',
68
+ loadingCart: 'Loading your cart…',
69
+ quantity: 'Quantity',
70
+ remove: 'Remove',
71
+ notAvailable: 'Not available any more',
72
+ discountCode: 'Discount code',
73
+ apply: 'Apply',
74
+ codeApplied: 'applied',
75
+ codeNotApplied: 'not applied',
76
+ checkout: 'Checkout',
77
+ // Checkout
78
+ checkoutTitle: 'Checkout',
79
+ preparingCheckout: 'Preparing checkout…',
80
+ contact: 'Contact',
81
+ name: 'Name',
82
+ phone: 'Phone',
83
+ saveContact: 'Save contact',
84
+ delivery: 'Delivery',
85
+ pickUp: 'Pick up',
86
+ orDeliverTo: 'Or deliver to',
87
+ deliverTo: 'Deliver to',
88
+ street: 'Street, house',
89
+ city: 'City',
90
+ latitude: 'Latitude',
91
+ longitude: 'Longitude',
92
+ useMyLocation: 'Use my location',
93
+ showDeliveryOptions: 'Show delivery options',
94
+ free: 'free',
95
+ payment: 'Payment',
96
+ placeOrder: 'Place order',
97
+ thankYou: 'Thank you!',
98
+ order: 'Order',
99
+ payNow: 'Pay now',
100
+ // Account
101
+ signIn: 'Sign in',
102
+ sendCode: 'Send code',
103
+ smsCode: 'Code from the SMS',
104
+ signOut: 'Sign out',
105
+ orders: 'Orders',
106
+ loadingOrders: 'Loading orders…',
107
+ noOrders: 'No orders yet.',
108
+ savedProducts: 'Saved products',
109
+ orderStatus: {
110
+ NEW: 'New',
111
+ ACCEPTED: 'Accepted',
112
+ PROCESSED: 'Processing',
113
+ ASSEMBLED: 'Packed',
114
+ DELIVERING: 'On the way',
115
+ DELIVERED: 'Delivered',
116
+ CANCELLED: 'Cancelled',
117
+ } satisfies Record<OrderStatus, string>,
118
+ };
119
+
120
+ export type Messages = typeof en;
121
+
122
+ const ru: Messages = {
123
+ search: 'Поиск',
124
+ account: 'Кабинет',
125
+ cart: 'Корзина',
126
+ home: 'Главная',
127
+ pages: 'Страницы',
128
+ backToShop: 'Вернуться в магазин',
129
+ continueShopping: 'Продолжить покупки',
130
+ seeAll: 'Смотреть все',
131
+ total: 'Итого',
132
+ subtotal: 'Товары',
133
+ discount: 'Скидка',
134
+ updating: 'Обновляем…',
135
+ somethingWentWrong: 'Что-то пошло не так',
136
+ tryAgainLater: 'Что-то пошло не так. Попробуйте ещё раз.',
137
+ tryAgain: 'Попробовать снова',
138
+ shopClosed: 'Магазин временно закрыт',
139
+ notFound: 'Страница не найдена',
140
+ nothingHere: 'Здесь пока ничего нет.',
141
+ soldOut: 'Нет в наличии',
142
+ preOrder: 'Предзаказ',
143
+ sale: 'Скидка',
144
+ isNew: 'Новинка',
145
+ searchPlaceholder: 'Что вы ищете?',
146
+ found: (count) => `Найдено: ${count}`,
147
+ newArrivals: 'Новинки',
148
+ onSale: 'Со скидкой',
149
+ trending: 'Популярное',
150
+ bestsellers: 'Хиты продаж',
151
+ banner: 'Баннер',
152
+ stockLeft: (remaining, initial) => `Осталось ${remaining} из ${initial}`,
153
+ endsAt: 'Закончится',
154
+ customersSay: 'Что говорят покупатели',
155
+ reviewsCount: (count) =>
156
+ `${count} ${plural('ru', count, { one: 'отзыв', few: 'отзыва', other: 'отзывов' })}`,
157
+ recommendUs: (percent) => `${percent}% рекомендуют нас`,
158
+ leaveReview: 'Оставить отзыв',
159
+ addToCart: 'В корзину',
160
+ addedToCart: 'Добавлено в корзину.',
161
+ couldNotAdd: 'Не удалось добавить в корзину.',
162
+ save: 'В избранное',
163
+ saved: 'В избранном',
164
+ cartEmpty: 'Корзина пуста',
165
+ loadingCart: 'Загружаем корзину…',
166
+ quantity: 'Количество',
167
+ remove: 'Удалить',
168
+ notAvailable: 'Больше недоступен',
169
+ discountCode: 'Промокод',
170
+ apply: 'Применить',
171
+ codeApplied: 'применён',
172
+ codeNotApplied: 'не применён',
173
+ checkout: 'Оформить заказ',
174
+ checkoutTitle: 'Оформление заказа',
175
+ preparingCheckout: 'Готовим оформление…',
176
+ contact: 'Контакты',
177
+ name: 'Имя',
178
+ phone: 'Телефон',
179
+ saveContact: 'Сохранить контакты',
180
+ delivery: 'Доставка',
181
+ pickUp: 'Самовывоз',
182
+ orDeliverTo: 'Или доставка по адресу',
183
+ deliverTo: 'Доставка по адресу',
184
+ street: 'Улица, дом',
185
+ city: 'Город',
186
+ latitude: 'Широта',
187
+ longitude: 'Долгота',
188
+ useMyLocation: 'Моё местоположение',
189
+ showDeliveryOptions: 'Показать способы доставки',
190
+ free: 'бесплатно',
191
+ payment: 'Оплата',
192
+ placeOrder: 'Подтвердить заказ',
193
+ thankYou: 'Спасибо!',
194
+ order: 'Заказ',
195
+ payNow: 'Оплатить',
196
+ signIn: 'Войти',
197
+ sendCode: 'Получить код',
198
+ smsCode: 'Код из SMS',
199
+ signOut: 'Выйти',
200
+ orders: 'Заказы',
201
+ loadingOrders: 'Загружаем заказы…',
202
+ noOrders: 'Заказов пока нет.',
203
+ savedProducts: 'Избранное',
204
+ orderStatus: {
205
+ NEW: 'Новый',
206
+ ACCEPTED: 'Принят',
207
+ PROCESSED: 'В обработке',
208
+ ASSEMBLED: 'Собран',
209
+ DELIVERING: 'В пути',
210
+ DELIVERED: 'Доставлен',
211
+ CANCELLED: 'Отменён',
212
+ },
213
+ };
214
+
215
+ const uz: Messages = {
216
+ search: 'Qidiruv',
217
+ account: 'Kabinet',
218
+ cart: 'Savat',
219
+ home: 'Bosh sahifa',
220
+ pages: 'Sahifalar',
221
+ backToShop: "Do'konga qaytish",
222
+ continueShopping: 'Xaridni davom ettirish',
223
+ seeAll: 'Barchasi',
224
+ total: 'Jami',
225
+ subtotal: 'Mahsulotlar',
226
+ discount: 'Chegirma',
227
+ updating: 'Yangilanmoqda…',
228
+ somethingWentWrong: 'Nimadir xato ketdi',
229
+ tryAgainLater: "Nimadir xato ketdi. Qaytadan urinib ko'ring.",
230
+ tryAgain: 'Qayta urinish',
231
+ shopClosed: "Do'kon vaqtincha yopiq",
232
+ notFound: 'Sahifa topilmadi',
233
+ nothingHere: "Hozircha bu yerda hech narsa yo'q.",
234
+ soldOut: "Sotuvda yo'q",
235
+ preOrder: 'Oldindan buyurtma',
236
+ sale: 'Chegirma',
237
+ isNew: 'Yangi',
238
+ searchPlaceholder: 'Nima qidiryapsiz?',
239
+ found: (count) => `${count} ta topildi`,
240
+ newArrivals: 'Yangi kelganlar',
241
+ onSale: 'Chegirmadagilar',
242
+ trending: 'Ommabop',
243
+ bestsellers: 'Xitlar',
244
+ banner: 'Banner',
245
+ stockLeft: (remaining, initial) => `${initial} tadan ${remaining} ta qoldi`,
246
+ endsAt: 'Tugaydi',
247
+ customersSay: 'Mijozlarimiz fikri',
248
+ reviewsCount: (count) => `${count} ta sharh`,
249
+ recommendUs: (percent) => `${percent}% bizni tavsiya qiladi`,
250
+ leaveReview: 'Sharh qoldirish',
251
+ addToCart: "Savatga qo'shish",
252
+ addedToCart: "Savatga qo'shildi.",
253
+ couldNotAdd: "Savatga qo'shib bo'lmadi.",
254
+ save: 'Saqlash',
255
+ saved: 'Saqlangan',
256
+ cartEmpty: "Savatingiz bo'sh",
257
+ loadingCart: 'Savat yuklanmoqda…',
258
+ quantity: 'Soni',
259
+ remove: "O'chirish",
260
+ notAvailable: 'Endi mavjud emas',
261
+ discountCode: 'Promokod',
262
+ apply: "Qo'llash",
263
+ codeApplied: "qo'llanildi",
264
+ codeNotApplied: "qo'llanilmadi",
265
+ checkout: 'Rasmiylashtirish',
266
+ checkoutTitle: 'Buyurtmani rasmiylashtirish',
267
+ preparingCheckout: 'Tayyorlanmoqda…',
268
+ contact: "Bog'lanish",
269
+ name: 'Ism',
270
+ phone: 'Telefon',
271
+ saveContact: 'Saqlash',
272
+ delivery: 'Yetkazib berish',
273
+ pickUp: 'Olib ketish',
274
+ orDeliverTo: 'Yoki manzilga yetkazish',
275
+ deliverTo: 'Manzilga yetkazish',
276
+ street: "Ko'cha, uy",
277
+ city: 'Shahar',
278
+ latitude: 'Kenglik',
279
+ longitude: 'Uzunlik',
280
+ useMyLocation: 'Joylashuvimni aniqlash',
281
+ showDeliveryOptions: "Yetkazib berish usullarini ko'rsatish",
282
+ free: 'bepul',
283
+ payment: "To'lov",
284
+ placeOrder: 'Buyurtmani tasdiqlash',
285
+ thankYou: 'Rahmat!',
286
+ order: 'Buyurtma',
287
+ payNow: "To'lash",
288
+ signIn: 'Kirish',
289
+ sendCode: 'Kod olish',
290
+ smsCode: 'SMS dagi kod',
291
+ signOut: 'Chiqish',
292
+ orders: 'Buyurtmalar',
293
+ loadingOrders: 'Buyurtmalar yuklanmoqda…',
294
+ noOrders: "Hozircha buyurtmalar yo'q.",
295
+ savedProducts: 'Saqlanganlar',
296
+ orderStatus: {
297
+ NEW: 'Yangi',
298
+ ACCEPTED: 'Qabul qilindi',
299
+ PROCESSED: 'Ishlov berilmoqda',
300
+ ASSEMBLED: "Yig'ildi",
301
+ DELIVERING: 'Yetkazilmoqda',
302
+ DELIVERED: 'Yetkazildi',
303
+ CANCELLED: 'Bekor qilindi',
304
+ },
305
+ };
306
+
307
+ export const MESSAGES = { en, ru, uz } as const;
308
+
309
+ /** The dictionary for a locale (`ru`, `ru-RU`, `uz-Latn-UZ`…); English when there is none. */
310
+ export function messages(locale: string): Messages {
311
+ const language = locale.toLowerCase().split('-')[0];
312
+ return language !== undefined && Object.hasOwn(MESSAGES, language)
313
+ ? MESSAGES[language as keyof typeof MESSAGES]
314
+ : MESSAGES.en;
315
+ }
package/template/llms.txt CHANGED
@@ -24,15 +24,15 @@ call the client method. `npx create-magic-storefront check` fails on either.
24
24
  npm create magic-storefront@latest my-shop -- --shop shop.example.uz
25
25
  ```
26
26
 
27
- scaffolds a Next.js App Router storefront (home from the merchant's sections, catalog, product,
28
- search, cart, checkout, sign-in, orders, SEO, webhook revalidation). Or install the packages:
27
+ scaffolds a Next.js App Router storefront (home from the merchant's sections or your own, catalog,
28
+ product, search, cart, checkout, sign-in, orders, SEO, webhook revalidation). Or install the packages:
29
29
  `npm i @magicstoreai/storefront-client @magicstoreai/hydrogen`.
30
30
 
31
31
  ## Docs
32
32
 
33
33
  - `PAGES.md` (in a scaffolded storefront; `examples/starter/PAGES.md` in the SDK repository): how to
34
- build each page type — home from the `/home` sections, collection, product, search, cart,
35
- checkout, account — with its data calls, cache tags, SEO and required states.
34
+ build each page type — home (from the `/home` sections or custom), collection, product, search,
35
+ cart, checkout, account — with its data calls, cache tags, SEO and required states.
36
36
  - [Hydrogen catalogue](node_modules/@magicstoreai/hydrogen/CATALOGUE.md): every export with its props
37
37
  or signature, an example, and the API operations it calls. In the SDK repository:
38
38
  `packages/hydrogen/CATALOGUE.md`.
@@ -65,8 +65,10 @@ Public catalog reads need no customer. Render them on the server with a client w
65
65
  - Lists paginate with `page` + `perPage` (default 24, max 100); read `meta.pagination`, or
66
66
  `<Pagination>`. Sorts order (`sort=-createdAt`), filters narrow (`filter[onSale]=true`).
67
67
  - A missing value is `null`, never `0` or `""`: show a fallback.
68
- - The home page is `GET /home`: an ordered list of sections, one `type` each
69
- (`GET /theme/section-schema` has every type's JSON Schema). Render an unknown type as nothing.
68
+ - The home page is yours to design. `GET /home` (an ordered list of sections, one `type` each;
69
+ `GET /theme/section-schema` has every type's JSON Schema) is optional: render it to let the
70
+ merchant arrange the page from the admin, or compose a custom home from catalog and content
71
+ data. When you render it, an unknown type renders as nothing.
70
72
 
71
73
  ## Credentials in the browser
72
74