@thorprovider/storefront 0.4.0-mvp.0 → 0.4.0-mvp.2

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 (166) hide show
  1. package/README.md +173 -153
  2. package/VENDOR.md +69 -0
  3. package/assets/openspec/config.yaml +38 -0
  4. package/assets/templates/AGENTS.md +76 -0
  5. package/assets/templates/app/app/[[...slug]]/page.tsx +42 -1
  6. package/assets/templates/app/app/[[...slug]]/renderer.tsx +13 -2
  7. package/assets/templates/app/app/globals.css +5 -8
  8. package/assets/templates/app/app/layout.tsx +1 -5
  9. package/assets/templates/app/app/robots.ts +9 -3
  10. package/assets/templates/app/app/sitemap.ts +64 -5
  11. package/assets/templates/app/lib/__STOREFRONT__/actions.ts +70 -0
  12. package/assets/templates/app/lib/__STOREFRONT__/catalog.ts +15 -5
  13. package/assets/templates/app/lib/__STOREFRONT__/commerce.ts +71 -0
  14. package/assets/templates/app/lib/__STOREFRONT__/composition.ts +26 -0
  15. package/assets/templates/app/lib/__STOREFRONT__/handlers.core.ts +36 -4
  16. package/assets/templates/app/lib/__STOREFRONT__/registry.tsx +82 -50
  17. package/assets/templates/app/lib/__STOREFRONT__/runtime.ts +3 -0
  18. package/assets/templates/app/lib/__STOREFRONT__/schema.ts +29 -14
  19. package/assets/templates/app/lib/__STOREFRONT__/section-observation.ts +182 -0
  20. package/assets/templates/app/lib/__STOREFRONT__/section-sources.ts +130 -0
  21. package/assets/templates/app/lib/__STOREFRONT__/shell/content.ts +31 -7
  22. package/assets/templates/app/lib/__STOREFRONT__/shell/props.ts +4 -0
  23. package/assets/templates/app/lib/__STOREFRONT__/spec/index.ts +56 -26
  24. package/assets/templates/app/lib/__STOREFRONT__/spec/seo.ts +165 -0
  25. package/assets/templates/app/lib/__STOREFRONT__/store-context.ts +26 -7
  26. package/assets/templates/app/lib/__STOREFRONT__/views/sections/index.ts +2 -1
  27. package/assets/templates/app/lib/__STOREFRONT__/views/sections/products.client.tsx +100 -0
  28. package/assets/templates/app/lib/__STOREFRONT__/views/sections/products.tsx +19 -0
  29. package/assets/templates/app/lib/__STOREFRONT__/views/sections/schema.products.ts +39 -0
  30. package/assets/templates/features/checkout/handlers.ts +6 -0
  31. package/assets/templates/features/customer-auth/state.ts +10 -1
  32. package/assets/templates/views/account/index.tsx +1 -1
  33. package/assets/templates/views/account/registry.tsx +80 -19
  34. package/assets/templates/views/account/schema.ts +1 -0
  35. package/assets/templates/views/cart/content.ts +11 -0
  36. package/assets/templates/views/cart/data.ts +23 -0
  37. package/assets/templates/views/cart/index.tsx +53 -0
  38. package/assets/templates/views/cart/props.ts +12 -0
  39. package/assets/templates/views/cart/registry.tsx +81 -0
  40. package/assets/templates/views/cart/schema.ts +52 -0
  41. package/assets/templates/views/category/assembly/assembly.json +1 -0
  42. package/assets/templates/views/category/assembly/index.skeleton.tsx +64 -6
  43. package/assets/templates/views/category/assembly/registry.skeleton.tsx +2 -1
  44. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/binding.json +5 -0
  45. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/catalog.part +4 -0
  46. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/element.part +7 -0
  47. package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/registry.part +18 -0
  48. package/assets/templates/views/category/index.tsx +76 -7
  49. package/assets/templates/views/category/props.ts +7 -0
  50. package/assets/templates/views/category/registry.tsx +19 -0
  51. package/assets/templates/views/category/schema.ts +13 -0
  52. package/assets/templates/views/home/assembly/assembly.json +9 -0
  53. package/assets/templates/views/home/assembly/index.skeleton.tsx +22 -4
  54. package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/element.part +1 -1
  55. package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/registry.part +2 -2
  56. package/assets/templates/views/home/data.ts +9 -0
  57. package/assets/templates/views/home/index.tsx +23 -5
  58. package/assets/templates/views/home/registry.tsx +2 -2
  59. package/assets/templates/views/product/data.ts +4 -2
  60. package/assets/templates/views/product/index.tsx +49 -5
  61. package/assets/templates/views/product/props.ts +7 -0
  62. package/assets/templates/views/product/registry.tsx +25 -0
  63. package/assets/templates/views/product/schema.ts +13 -0
  64. package/assets/templates/views/static/content.ts +4 -4
  65. package/assets/templates/views/static/index.tsx +1 -1
  66. package/bin/storefront.js +1231 -154
  67. package/examples/merchandising/category-led.json +37 -0
  68. package/examples/merchandising/collection-led.json +37 -0
  69. package/package.json +11 -7
  70. package/recipes/archetypes.json +9 -22
  71. package/recipes/catalog.json +40 -1
  72. package/recipes/features.json +25 -2
  73. package/recipes/recipe.schema.json +1 -1
  74. package/recipes/recipes.json +32 -30
  75. package/recipes/sections.json +10 -0
  76. package/recipes/validate.mjs +54 -0
  77. package/scripts/candidate.mjs +4 -4
  78. package/scripts/composers.mjs +25 -5
  79. package/scripts/env-file.mjs +86 -0
  80. package/scripts/file-classes.mjs +5 -0
  81. package/scripts/migrate-english-routes.mjs +276 -0
  82. package/scripts/pinning.mjs +74 -5
  83. package/scripts/plan-apply.mjs +149 -5
  84. package/scripts/reconcile.mjs +49 -11
  85. package/scripts/render-templates.mjs +97 -44
  86. package/scripts/section-config.mjs +253 -0
  87. package/scripts/starter.mjs +17 -0
  88. package/scripts/theme/color.mjs +185 -0
  89. package/scripts/theme/css-theme.mjs +233 -0
  90. package/scripts/theme/fonts.mjs +123 -0
  91. package/scripts/theme/import-export.mjs +125 -0
  92. package/scripts/theme/preset.mjs +93 -0
  93. package/scripts/theme/theme-plan.mjs +292 -0
  94. package/scripts/theme/tokens.mjs +137 -0
  95. package/scripts/view-assembly.mjs +47 -1
  96. package/skills/sf-feature/SKILL.md +32 -19
  97. package/skills/sf-setup/SKILL.md +79 -0
  98. package/skills/sf-theme-gen/SKILL.md +99 -36
  99. package/skills/sf-theme-gen/references/shadcn-theming.md +87 -0
  100. package/skills/{shadcn-theming/references/templates → sf-theme-gen/references}/theme-setup.md +15 -19
  101. package/skills/{shadcn-theming → sf-theme-gen}/references/theming-guide.md +6 -11
  102. package/skills/sf-view-gen/SKILL.md +63 -40
  103. package/skills/sf-view-gen/assets/recipes/archetypes.json +9 -22
  104. package/skills/sf-view-gen/assets/recipes/catalog.json +40 -1
  105. package/skills/sf-view-gen/assets/recipes/features.json +25 -2
  106. package/skills/sf-view-gen/assets/recipes/recipes.json +32 -30
  107. package/skills/sf-view-gen/assets/recipes/sections.json +10 -0
  108. package/skills/sf-view-gen/assets/templates/views/sections/products.client.tsx +100 -0
  109. package/skills/sf-view-gen/assets/templates/views/sections/products.tsx +19 -0
  110. package/skills/sf-view-gen/assets/templates/views/sections/schema.products.ts +39 -0
  111. package/skills/{json-render-core/SKILL.md → sf-view-gen/references/json-render-core.md} +4 -27
  112. package/skills/{json-render-next/SKILL.md → sf-view-gen/references/json-render-next.md} +5 -8
  113. package/skills/{json-render-react/SKILL.md → sf-view-gen/references/json-render-react.md} +3 -5
  114. package/skills/{json-render-shadcn/SKILL.md → sf-view-gen/references/json-render-shadcn.md} +3 -5
  115. package/skills/sf-view-gen/references/views.md +28 -37
  116. package/skills/sf-view-gen/scripts/validate.mjs +54 -0
  117. package/skills/storefront-workflow/SKILL.md +94 -31
  118. package/skills/{storefront-best-practices/reference/design.md → storefront-workflow/references/design-consistency.md} +13 -29
  119. package/CHANGELOG.md +0 -84
  120. package/assets/templates/views/user-panel/index.tsx +0 -106
  121. package/assets/templates/views/user-panel/registry.tsx +0 -54
  122. package/assets/templates/views/user-panel/schema.ts +0 -79
  123. package/commands/sf-add-view.md +0 -57
  124. package/commands/sf-feature.md +0 -28
  125. package/commands/sf-theme.md +0 -26
  126. package/commands/sf-view.md +0 -67
  127. package/skills/building-storefronts/SKILL.md +0 -178
  128. package/skills/building-storefronts/references/frontend-integration.md +0 -229
  129. package/skills/json-render-remotion/SKILL.md +0 -111
  130. package/skills/json-render-solid/SKILL.md +0 -204
  131. package/skills/nextjs-shadcn/SKILL.md +0 -367
  132. package/skills/nextjs-shadcn/references/architecture.md +0 -499
  133. package/skills/nextjs-shadcn/references/project-setup.md +0 -162
  134. package/skills/nextjs-shadcn/references/shadcn-platform.md +0 -261
  135. package/skills/nextjs-shadcn/references/sidebar.md +0 -274
  136. package/skills/nextjs-shadcn/references/styling.md +0 -555
  137. package/skills/shadcn-component-discovery/SKILL.md +0 -273
  138. package/skills/shadcn-component-discovery/references/registries.md +0 -226
  139. package/skills/shadcn-theming/SKILL.md +0 -104
  140. package/skills/storefront-best-practices/SKILL.md +0 -421
  141. package/skills/storefront-best-practices/reference/components/breadcrumbs.md +0 -123
  142. package/skills/storefront-best-practices/reference/components/cart-popup.md +0 -189
  143. package/skills/storefront-best-practices/reference/components/country-selector.md +0 -298
  144. package/skills/storefront-best-practices/reference/components/footer.md +0 -112
  145. package/skills/storefront-best-practices/reference/components/hero.md +0 -241
  146. package/skills/storefront-best-practices/reference/components/megamenu.md +0 -239
  147. package/skills/storefront-best-practices/reference/components/navbar.md +0 -397
  148. package/skills/storefront-best-practices/reference/components/popups.md +0 -221
  149. package/skills/storefront-best-practices/reference/components/product-card.md +0 -125
  150. package/skills/storefront-best-practices/reference/components/product-reviews.md +0 -217
  151. package/skills/storefront-best-practices/reference/components/product-slider.md +0 -174
  152. package/skills/storefront-best-practices/reference/components/search.md +0 -101
  153. package/skills/storefront-best-practices/reference/connecting-to-backend.md +0 -391
  154. package/skills/storefront-best-practices/reference/features/promotions.md +0 -307
  155. package/skills/storefront-best-practices/reference/features/wishlist.md +0 -230
  156. package/skills/storefront-best-practices/reference/layouts/account.md +0 -380
  157. package/skills/storefront-best-practices/reference/layouts/cart.md +0 -316
  158. package/skills/storefront-best-practices/reference/layouts/checkout.md +0 -486
  159. package/skills/storefront-best-practices/reference/layouts/home-page.md +0 -264
  160. package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +0 -231
  161. package/skills/storefront-best-practices/reference/layouts/product-details.md +0 -527
  162. package/skills/storefront-best-practices/reference/layouts/product-listing.md +0 -520
  163. package/skills/storefront-best-practices/reference/layouts/static-pages.md +0 -356
  164. package/skills/storefront-best-practices/reference/medusa.md +0 -307
  165. /package/skills/{storefront-best-practices/reference → storefront-workflow/references}/mobile-responsiveness.md +0 -0
  166. /package/skills/{storefront-best-practices/reference → storefront-workflow/references}/seo.md +0 -0
@@ -1,106 +0,0 @@
1
- // Thor Commerce view module: user-panel
2
- // Server Component module: elements + catalog entries + route + loader only.
3
- // The client-side component mappings live in ./registry.tsx ('use client'); this
4
- // module imports them as data so the RSC graph never evaluates @json-render/react
5
- // on the server. Registered by importing it in ../index.ts. Recipe: recipes.json -> "user-panel".
6
-
7
- import { getCatalog } from '@thorprovider/runtime/commerce'
8
- import { pageRoot } from '../../spec/page-root'
9
- import type { StorefrontElement } from '../../spec/types'
10
- import type { ViewModule } from '../types'
11
- import { registry } from './registry'
12
- import { appShellPropsSchema, orderHistoryPropsSchema } from './schema'
13
-
14
- const elements: Record<string, StorefrontElement> = {
15
- 'userPanel.shell': {
16
- type: 'AppShell',
17
- props: {
18
- brandName: '__SITE_NAME__',
19
- navGroupLabel: 'Mi cuenta',
20
- navItems: [
21
- { label: 'Mis pedidos', href: '/cuenta', icon: 'package', active: true },
22
- { label: 'Mi perfil', href: '/cuenta/perfil', icon: 'user' },
23
- { label: 'Ajustes', href: '/cuenta/ajustes', icon: 'settings' },
24
- ],
25
- user: {
26
- name: 'Cliente Demo',
27
- email: 'cliente@ejemplo.com',
28
- initials: 'CD',
29
- },
30
- breadcrumb: [
31
- { label: 'Inicio', href: '/' },
32
- { label: 'Mi cuenta' },
33
- ],
34
- pageTitle: 'Mi cuenta',
35
- pageDescription: 'Consulta tus pedidos recientes y gestiona tu cuenta.',
36
- action: { label: 'Seguir comprando', href: '/' },
37
- stats: [
38
- { label: 'Pedidos', value: '1' },
39
- { label: 'Estado', value: 'Confirmado' },
40
- ],
41
- },
42
- children: ['userPanel.orderHistory'],
43
- },
44
- 'userPanel.orderHistory': {
45
- type: 'OrderHistory',
46
- props: {
47
- orders: { $state: '/lastOrderLines' },
48
- title: 'Historial de pedidos',
49
- description: 'Tus compras recientes y su estado.',
50
- },
51
- on: {
52
- viewOrder: { action: 'viewOrder' },
53
- downloadInvoice: { action: 'downloadInvoice' },
54
- },
55
- },
56
- }
57
-
58
- const catalog = {
59
- AppShell: {
60
- props: appShellPropsSchema,
61
- slots: ['default'],
62
- description: 'Panel de cuenta con navegación lateral, cabecera y área de contenido.',
63
- },
64
- OrderHistory: {
65
- props: orderHistoryPropsSchema,
66
- description: 'Historial de pedidos del cliente.',
67
- },
68
- }
69
-
70
- export const userPanel: ViewModule = {
71
- name: 'user-panel',
72
- elements,
73
- catalog,
74
- registry,
75
- route: {
76
- path: '/cuenta',
77
- loaderName: 'userPanel',
78
- layout: 'default',
79
- metadata: {
80
- title: 'Mi cuenta',
81
- description: 'Consulta tu historial de pedidos y gestiona tu cuenta.',
82
- },
83
- entry: pageRoot('userPanel', ['userPanel.shell'], elements),
84
- },
85
- loader: {
86
- userPanel: async () => {
87
- const { products } = await getCatalog()
88
- const placedAt = new Date()
89
- const orderDate = placedAt.toISOString().slice(0, 10)
90
- const lastOrderLines = products.slice(0, 3).map((product, index) => ({
91
- name: product.title,
92
- image: product.image,
93
- color: 'Estándar',
94
- size: 'Único',
95
- quantity: index + 1,
96
- price: product.price,
97
- orderDate,
98
- }))
99
- // Only lastOrderLines is bound by this view's elements. lastOrder and
100
- // orderPlaced belong to the checkout contract (StorefrontOrder shape and
101
- // an ISO timestamp); writing demo values in a foreign shape here would
102
- // leak into /checkout state and crash CheckoutConfirmation.
103
- return { lastOrderLines }
104
- },
105
- },
106
- }
@@ -1,54 +0,0 @@
1
- 'use client'
2
-
3
- // Thor Commerce view registry fragment: user-panel
4
- // Client boundary for the user-panel view. Imports value bindings from
5
- // @json-render/react and components from @thorprovider/blocks — both must stay
6
- // on the client side of the RSC graph. Kept separate from index.tsx so the view
7
- // spec (elements/catalog/route/loader) stays a pure Server Component module.
8
-
9
- import {
10
- AppShell1 as AppShellBlock,
11
- OrderHistory1 as OrderHistoryBlock,
12
- } from '@thorprovider/blocks'
13
- import { useStateStore } from '@json-render/react'
14
- import { appShellPropsSchema, orderHistoryPropsSchema } from './schema'
15
- import type { ViewRegistry } from '../types'
16
-
17
- export const registry: ViewRegistry = {
18
- AppShell: ({ props, children }) => {
19
- const parsed = appShellPropsSchema.parse(props)
20
- return (
21
- <AppShellBlock
22
- brandName={parsed.brandName}
23
- navGroupLabel={parsed.navGroupLabel}
24
- navItems={parsed.navItems}
25
- user={parsed.user}
26
- breadcrumb={parsed.breadcrumb}
27
- pageTitle={parsed.pageTitle}
28
- pageDescription={parsed.pageDescription}
29
- action={parsed.action}
30
- stats={parsed.stats}
31
- >
32
- {children}
33
- </AppShellBlock>
34
- )
35
- },
36
- OrderHistory: ({ props, emit }) => {
37
- const parsed = orderHistoryPropsSchema.parse(props)
38
- const { set } = useStateStore()
39
- return (
40
- <OrderHistoryBlock
41
- orders={parsed.orders}
42
- title={parsed.title}
43
- description={parsed.description}
44
- onViewDetails={() => {
45
- set('/orderDetailsOpen', true)
46
- emit('viewOrder')
47
- }}
48
- onDownloadInvoice={() => {
49
- emit('downloadInvoice')
50
- }}
51
- />
52
- )
53
- },
54
- }
@@ -1,79 +0,0 @@
1
- // Thor Commerce view schema fragment: user-panel
2
- // Zod mirrors of the block contracts for this view — the single source for the
3
- // catalog entries and the client-side registry parsing (json-render does not
4
- // validate props against the catalog itself, so the registry parses here).
5
- // Kept free of React and server imports so the Server Component module and the
6
- // 'use client' registry can share one contract.
7
-
8
- import { z } from 'zod'
9
-
10
- export const ctaSchema = z.object({ label: z.string(), href: z.string().optional() })
11
-
12
- // Mirrors the AppShell1NavItem block contract: `icon` is a NAME of the
13
- // AppShell1NavIcon set — the block resolves it to a component internally.
14
- export const appShellNavItemSchema = z.object({
15
- label: z.string(),
16
- href: z.string(),
17
- icon: z.enum([
18
- 'layout-dashboard',
19
- 'package',
20
- 'user',
21
- 'settings',
22
- 'home',
23
- 'shopping-cart',
24
- 'bar-chart-3',
25
- 'users',
26
- 'folder-kanban',
27
- ]),
28
- active: z.boolean().optional(),
29
- })
30
-
31
- export const appShellUserSchema = z.object({
32
- name: z.string(),
33
- email: z.string(),
34
- initials: z.string(),
35
- })
36
-
37
- export const breadcrumbItemSchema = z.object({
38
- label: z.string(),
39
- href: z.string().optional(),
40
- })
41
-
42
- export const statSchema = z.object({
43
- label: z.string(),
44
- value: z.string(),
45
- })
46
-
47
- // Mirrors the OrderHistory1Order block contract.
48
- export const orderLineSchema = z.object({
49
- name: z.string(),
50
- image: z.string(),
51
- color: z.string(),
52
- size: z.string(),
53
- quantity: z.number(),
54
- price: z.number(),
55
- orderDate: z.string(),
56
- })
57
-
58
- export const appShellPropsSchema = z.object({
59
- brandName: z.string().optional(),
60
- navGroupLabel: z.string().optional(),
61
- navItems: z.array(appShellNavItemSchema).optional(),
62
- user: appShellUserSchema.optional(),
63
- breadcrumb: z.array(breadcrumbItemSchema).optional(),
64
- pageTitle: z.string().optional(),
65
- pageDescription: z.string().optional(),
66
- action: ctaSchema.optional(),
67
- stats: z.array(statSchema).optional(),
68
- })
69
-
70
- export const orderHistoryPropsSchema = z.object({
71
- orders: z.array(orderLineSchema),
72
- title: z.string().optional(),
73
- description: z.string().optional(),
74
- })
75
-
76
- export type AppShellNavItem = z.infer<typeof appShellNavItemSchema>
77
- export type AppShellProps = z.infer<typeof appShellPropsSchema>
78
- export type OrderLine = z.infer<typeof orderLineSchema>
79
- export type OrderHistoryProps = z.infer<typeof orderHistoryPropsSchema>
@@ -1,57 +0,0 @@
1
- ---
2
- description: "Add a view to a Thor Commerce storefront via the storefront CLI"
3
- ---
4
-
5
- Add one view to the current storefront. The CLI is the structural authority; do
6
- not copy templates or edit derived files.
7
-
8
- **Input**: view name, optionally a description of what it should contain.
9
- Examples:
10
- - `/sf-add-view product`
11
- - `/sf-add-view category specialize in power stations, use a dense grid`
12
-
13
- **Provided arguments**: $ARGUMENTS
14
-
15
- Use the `sf-view-gen` skill. The agent selects the change and delegates every
16
- structural write to the CLI; the user states the change in natural language and
17
- never types a command.
18
-
19
- **Flow:**
20
- 1. `npx @thorprovider/storefront views --json` — confirm the view is supported
21
- and read its `supportedIntents`, `registeredSlots`, `allowedSections`,
22
- `maxSections`, and the top-level `sectionTypes`. Held units (`user-panel`,
23
- recommendations) and the feature-owned `checkout` view are rejected; sections
24
- are composable (step 4).
25
- 2. Choose an intent per slot by meaning from the user's description.
26
- 3. Delegate the write:
27
- `npx @thorprovider/storefront view add <name> [--intent slot=intent] [--variant slot=Variant]`
28
- 4. To compose **sections** on the new view, delegate to the CLI's section
29
- operations (`section.add` / `section.remove` / `section.reorder`) in E1's
30
- operations envelope `{ "formatVersion": 1, "operations": [ ... ] }`; `plan` is
31
- read-only and `apply --plan` is the only writer:
32
- - `section.add` (`view`, `type`, optional `id`, `variant`, `at`) adds an
33
- editorial instance; `type` must be in the view's `allowedSections`, an
34
- omitted `id` is auto-minted, and the add is rejected past `maxSections`.
35
- - `section.remove` (`view`, `id`) removes an editorial instance; a registered
36
- core slot (`slot:<slot>`) cannot be removed.
37
- - `section.reorder` (`view`, `order`) requires `order` to be a permutation of
38
- the view's current entry ids: every current id exactly once and every
39
- registered slot present.
40
-
41
- ```bash
42
- npx @thorprovider/storefront plan --operations operations.json --out plan.json
43
- npx @thorprovider/storefront apply --plan plan.json
44
- ```
45
-
46
- Only `faq` and `cta` are executable editorial types. Held types
47
- (`testimonials`, `statistics`, `logoCloud`, `pricing`) are not available and
48
- are refused with the bounded reason the registry reports. These three section
49
- operations are implemented and supported — there is no proposed or future
50
- section command.
51
- 5. Report the result. If the CLI exits non-zero, show its message; never
52
- hand-edit derived files to work around it.
53
-
54
- **Constraints:**
55
- - UI only `@thorprovider/blocks`; data only `@thorprovider/adapters` +
56
- `@thorprovider/runtime/commerce`.
57
- - No manual template copy, no derived-file edits, no manual barrel edits.
@@ -1,28 +0,0 @@
1
- ---
2
- description: "Add or remove a storefront feature bundle (e.g. checkout) via the storefront CLI"
3
- ---
4
-
5
- Add or remove a feature bundle in the current storefront. A feature may own
6
- views (plus its state/handlers/adapter wiring), an owned route, and instance
7
- mounts into a host view's slot; the CLI writes every derived file.
8
-
9
- **Input**: `add <name>` or `remove <name>` (e.g. `add checkout`).
10
- **Provided arguments**: $ARGUMENTS
11
-
12
- Use the `sf-feature` skill.
13
-
14
- **Flow:**
15
- 1. `npx @thorprovider/storefront features --json` — confirm the feature is
16
- supported. Held features are rejected before any write.
17
- 2. Delegate the write:
18
- `npx @thorprovider/storefront feature add|remove <name>`
19
- 3. Report the result and any preserved user-owned file the CLI names. A
20
- mount-based feature (e.g. `benefits` at `home.benefits`) leaves the host
21
- view's customized content in place; the CLI reports its location.
22
-
23
- **Constraints:**
24
- - The curated MVP features are `checkout` (owns the `/checkout` route) and
25
- `benefits` (mounts at `home.benefits`).
26
- - No derived-file edits; the CLI reconciles state/handlers/adapter wiring.
27
- - Purchase logic is owned by `single-tenant-commerce-mvp`; this installs
28
- structural wiring only.
@@ -1,26 +0,0 @@
1
- ---
2
- description: "Customize storefront theme: OKLCH colors (light/dark), typography, and identity metadata"
3
- ---
4
-
5
- Customize the theme and identity of the current storefront. The manifest
6
- (`storefront.config.json`) is the theme authority; the CLI applies deterministic
7
- changes.
8
-
9
- **Input**: optional — the wizard asks what to customize (colors, typography, identity, SEO, Open Graph).
10
- **Provided arguments**: $ARGUMENTS
11
-
12
- Use the `sf-theme-gen` skill.
13
-
14
- **Flow:**
15
- 1. Run from inside the project (no directory argument).
16
- 2. **Mode (light/dark/system)** is manifest state, not a hand edit:
17
- `npx @thorprovider/storefront theme --mode light|dark|system`
18
- 3. Colors/typography/metadata are user-owned edits in `app/globals.css` and
19
- `app/layout.tsx`, following the skill's assets.
20
- 4. `npx @thorprovider/storefront sync` and report.
21
-
22
- **Constraints (do not violate without explicit user authorization):**
23
- - Colors are CSS variables in OKLCH with complete background/foreground pairs
24
- (light AND dark); never raw Tailwind color utilities for themed colors.
25
- - Never hand-edit `app/layout.tsx` for the mode — the CLI rewrites the
26
- `ThemeProvider` wiring idempotently from the manifest.
@@ -1,67 +0,0 @@
1
- ---
2
- description: "Modify a storefront view's user-owned content/props/data, or compose its sections, via the storefront CLI"
3
- ---
4
-
5
- Modify an existing view in the current storefront.
6
-
7
- **Input**: view name followed by the change to make.
8
- Examples:
9
- - `/sf-view home add a FAQ section after the hero`
10
- - `/sf-view home move the CTA above the benefits`
11
- - `/sf-view category switch to a 4-column grid`
12
-
13
- **Provided arguments**: $ARGUMENTS
14
-
15
- Use the `sf-view-gen` skill. The agent selects the change and delegates every
16
- structural write to the CLI; the user describes the change in natural language
17
- and never types a command.
18
-
19
- **Flow:**
20
- 1. Read the registry through the CLI
21
- (`npx @thorprovider/storefront views --json`) for the view's
22
- `registeredSlots`, `allowedSections`, `maxSections`, and the top-level
23
- `sectionTypes`.
24
- 2. If the change composes **sections**, delegate to the CLI's section
25
- operations — do not edit derived files. They are carried in E1's operations
26
- envelope `{ "formatVersion": 1, "operations": [ ... ] }`; `plan` is read-only
27
- and validates the whole intended state, `apply --plan` is the only writer:
28
- - `{ "op": "section.add", "view": "home", "type": "faq" }` — optional `id`,
29
- `variant`, and `at` (0-based insertion index, default append). `type` must
30
- be in the view's `allowedSections`; omit `id` to auto-mint one; rejected
31
- when adding would exceed `maxSections`.
32
- - `{ "op": "section.remove", "view": "home", "id": "home-faq-1" }` — removes
33
- an editorial instance. A registered core slot (`slot:<slot>`) cannot be
34
- removed.
35
- - `{ "op": "section.reorder", "view": "home", "order": ["slot:hero",
36
- "home-faq-1", "slot:benefits", "slot:categories"] }` — `order` must be a
37
- permutation of the view's current entry ids: every current id exactly once
38
- and every registered slot present.
39
-
40
- ```bash
41
- npx @thorprovider/storefront plan --operations operations.json --out plan.json
42
- npx @thorprovider/storefront apply --plan plan.json
43
- ```
44
-
45
- Only `faq` and `cta` are executable editorial types. Held types
46
- (`testimonials`, `statistics`, `logoCloud`, `pricing`) are not available and
47
- are refused with the bounded reason the registry reports; never present a
48
- held type as available. A removed instance's content is preserved in the
49
- view's user-owned `content.ts`; re-adding the same `id` rebinds it, while an
50
- auto-minted id never does. These three section operations are implemented and
51
- supported — there is no proposed or future section command; the held section
52
- types are the only not-yet-available part of this surface.
53
- 3. If the change is a different block variant or an added/removed view, delegate
54
- to the CLI: `npx @thorprovider/storefront view add|remove ...`.
55
- 4. If the change is content/props/data, edit only the **user-owned** files:
56
- `lib/<name>/views/<view>/content.ts`, `props.ts`, `data.ts`, `schema.ts`, and
57
- `lib/<name>/mappers.ts`.
58
- 5. Regenerate the derived wrappers around the edit:
59
- `npx @thorprovider/storefront sync`.
60
- 6. Report the result and the files touched.
61
-
62
- **Constraints:**
63
- - Preserve exported names, element ids, and the prop/event contracts the derived
64
- wrapper imports.
65
- - Never edit derived files (`index.tsx`, `registry.tsx`, `views/index.ts`,
66
- `views/registry.ts`, `catalog.ts`, `runtime.ts`, `spec/index.ts`).
67
- - UI only `@thorprovider/blocks`.
@@ -1,178 +0,0 @@
1
- ---
2
- name: building-storefronts
3
- description: Load automatically when planning, researching, or implementing Medusa storefront features (calling custom API routes, SDK integration, React Query patterns, data fetching). REQUIRED for all storefront development in ALL modes (planning, implementation, exploration). Contains SDK usage patterns, frontend integration, and critical rules for calling Medusa APIs.
4
- ---
5
-
6
- # Medusa Storefront Development
7
-
8
- Frontend integration guide for building storefronts with Medusa. Covers SDK usage, React Query patterns, and calling custom API routes.
9
-
10
- ## When to Apply
11
-
12
- **Load this skill for ANY storefront development task, including:**
13
- - Calling custom Medusa API routes from the storefront
14
- - Integrating Medusa SDK in frontend applications
15
- - Using React Query for data fetching
16
- - Implementing mutations with optimistic updates
17
- - Error handling and cache invalidation
18
-
19
- **Also load building-with-medusa when:** Building the backend API routes that the storefront calls
20
-
21
- ## CRITICAL: Load Reference Files When Needed
22
-
23
- **The quick reference below is NOT sufficient for implementation.** You MUST load the reference file before writing storefront integration code.
24
-
25
- **Load this reference when implementing storefront features:**
26
-
27
- - **Calling API routes?** → MUST load `references/frontend-integration.md` first
28
- - **Using SDK?** → MUST load `references/frontend-integration.md` first
29
- - **Implementing React Query?** → MUST load `references/frontend-integration.md` first
30
-
31
- ## Rule Categories by Priority
32
-
33
- | Priority | Category | Impact | Prefix |
34
- |----------|----------|--------|--------|
35
- | 1 | SDK Usage | CRITICAL | `sdk-` |
36
- | 2 | React Query Patterns | HIGH | `query-` |
37
- | 3 | Data Display | HIGH (includes CRITICAL price rule) | `display-` |
38
- | 4 | Error Handling | MEDIUM | `error-` |
39
-
40
- ## Quick Reference
41
-
42
- ### 1. SDK Usage (CRITICAL)
43
-
44
- - `sdk-always-use` - **ALWAYS use the Medusa JS SDK for ALL API requests** - NEVER use regular fetch()
45
- - `sdk-existing-methods` - For built-in endpoints, use existing SDK methods (`sdk.store.product.list()`, `sdk.admin.order.retrieve()`)
46
- - `sdk-client-fetch` - For custom API routes, use `sdk.client.fetch()`
47
- - `sdk-required-headers` - SDK automatically adds required headers (publishable API key for store, auth for admin) - regular fetch() missing these headers causes errors
48
- - `sdk-no-json-stringify` - **NEVER use JSON.stringify() on body** - SDK handles serialization automatically
49
- - `sdk-plain-objects` - Pass plain JavaScript objects to body, not strings
50
- - `sdk-locate-first` - Always locate where SDK is instantiated in the project before using it
51
-
52
- ### 2. React Query Patterns (HIGH)
53
-
54
- - `query-use-query` - Use `useQuery` for GET requests (data fetching)
55
- - `query-use-mutation` - Use `useMutation` for POST/DELETE requests (mutations)
56
- - `query-invalidate` - Invalidate queries in `onSuccess` to refresh data after mutations
57
- - `query-keys-hierarchical` - Structure query keys hierarchically for effective cache management
58
- - `query-loading-states` - Always handle `isLoading`, `isPending`, `isError` states
59
-
60
- ### 3. Data Display (HIGH)
61
-
62
- - `display-price-format` - **CRITICAL**: Prices from Medusa are stored as-is ($49.99 = 49.99, NOT in cents). Display them directly - NEVER divide by 100
63
-
64
- ### 4. Error Handling (MEDIUM)
65
-
66
- - `error-on-error` - Implement `onError` callback in mutations to handle failures
67
- - `error-display` - Show error messages to users when mutations fail
68
- - `error-rollback` - Use optimistic updates with rollback on error for better UX
69
-
70
- ## Critical SDK Pattern
71
-
72
- **ALWAYS pass plain objects to the SDK - NEVER use JSON.stringify():**
73
-
74
- ```typescript
75
- // ✅ CORRECT - Plain object
76
- await sdk.client.fetch("/store/reviews", {
77
- method: "POST",
78
- body: {
79
- product_id: "prod_123",
80
- rating: 5,
81
- }
82
- })
83
-
84
- // ❌ WRONG - JSON.stringify breaks the request
85
- await sdk.client.fetch("/store/reviews", {
86
- method: "POST",
87
- body: JSON.stringify({ // ❌ DON'T DO THIS!
88
- product_id: "prod_123",
89
- rating: 5,
90
- })
91
- })
92
- ```
93
-
94
- **Why this matters:**
95
- - The SDK handles JSON serialization automatically
96
- - Using JSON.stringify() will double-serialize and break the request
97
- - The server won't be able to parse the body
98
-
99
- ## Common Mistakes Checklist
100
-
101
- Before implementing, verify you're NOT doing these:
102
-
103
- **SDK Usage:**
104
- - [ ] Using regular fetch() instead of the Medusa JS SDK (causes missing header errors)
105
- - [ ] Not using existing SDK methods for built-in endpoints (e.g., using sdk.client.fetch("/store/products") instead of sdk.store.product.list())
106
- - [ ] Using JSON.stringify() on the body parameter
107
- - [ ] Manually setting Content-Type headers (SDK adds them)
108
- - [ ] Hardcoding SDK import paths (locate in project first)
109
- - [ ] Not using sdk.client.fetch() for custom routes
110
-
111
- **React Query:**
112
- - [ ] Not invalidating queries after mutations
113
- - [ ] Using flat query keys instead of hierarchical
114
- - [ ] Not handling loading and error states
115
- - [ ] Forgetting to disable buttons during mutations (isPending)
116
-
117
- **Data Display:**
118
- - [ ] **CRITICAL**: Dividing prices by 100 when displaying (prices are stored as-is: $49.99 = 49.99, NOT in cents)
119
-
120
- **Error Handling:**
121
- - [ ] Not implementing onError callbacks
122
- - [ ] Not showing error messages to users
123
- - [ ] Not handling network failures gracefully
124
-
125
- ## How to Use
126
-
127
- **For detailed patterns and examples, load reference file:**
128
-
129
- ```
130
- references/frontend-integration.md - SDK usage, React Query patterns, API integration
131
- ```
132
-
133
- The reference file contains:
134
- - Step-by-step SDK integration patterns
135
- - Complete React Query examples
136
- - Correct vs incorrect code examples
137
- - Query key best practices
138
- - Optimistic update patterns
139
- - Error handling strategies
140
-
141
- ## When to Use MedusaDocs MCP Server
142
-
143
- **Use this skill for (PRIMARY SOURCE):**
144
- - How to call custom API routes from storefront
145
- - SDK usage patterns (sdk.client.fetch)
146
- - React Query integration patterns
147
- - Common mistakes and anti-patterns
148
-
149
- **Use MedusaDocs MCP server for (SECONDARY SOURCE):**
150
- - Built-in SDK methods (sdk.admin.*, sdk.store.*)
151
- - Official Medusa SDK API reference
152
- - Framework-specific configuration options
153
-
154
- **Why skills come first:**
155
- - Skills contain critical patterns like "don't use JSON.stringify" that MCP doesn't emphasize
156
- - Skills show correct vs incorrect patterns; MCP shows what's possible
157
- - Planning requires understanding patterns, not just API reference
158
-
159
- ## Integration with Backend
160
-
161
- **⚠️ CRITICAL: ALWAYS use the Medusa JS SDK - NEVER use regular fetch()**
162
-
163
- When building features that span backend and frontend:
164
-
165
- 1. **Backend (building-with-medusa skill):** Module → Workflow → API Route
166
- 2. **Storefront (this skill):** SDK → React Query → UI Components
167
- 3. **Connection:**
168
- - Built-in endpoints: Use existing SDK methods (`sdk.store.product.list()`)
169
- - Custom API routes: Use `sdk.client.fetch("/store/my-route")`
170
- - **NEVER use regular fetch()** - missing publishable API key causes errors
171
-
172
- **Why the SDK is required:**
173
- - Store routes need `x-publishable-api-key` header
174
- - Admin routes need `Authorization` and session headers
175
- - SDK handles all required headers automatically
176
- - Regular fetch() without headers → authentication/authorization errors
177
-
178
- See `building-with-medusa` for backend API route patterns.