@thorprovider/storefront 0.3.1

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/CHANGELOG.md +61 -0
  2. package/README.md +333 -0
  3. package/assets/templates/app/app/[[...slug]]/page.tsx +17 -0
  4. package/assets/templates/app/app/[[...slug]]/renderer.tsx +10 -0
  5. package/assets/templates/app/app/globals.css +101 -0
  6. package/assets/templates/app/app/layout.tsx +35 -0
  7. package/assets/templates/app/lib/__STOREFRONT__/catalog.ts +88 -0
  8. package/assets/templates/app/lib/__STOREFRONT__/handlers.ts +42 -0
  9. package/assets/templates/app/lib/__STOREFRONT__/mappers.ts +47 -0
  10. package/assets/templates/app/lib/__STOREFRONT__/registry.tsx +98 -0
  11. package/assets/templates/app/lib/__STOREFRONT__/runtime.ts +17 -0
  12. package/assets/templates/app/lib/__STOREFRONT__/spec/index.ts +48 -0
  13. package/assets/templates/app/lib/__STOREFRONT__/spec/page-root.ts +26 -0
  14. package/assets/templates/app/lib/__STOREFRONT__/spec/types.ts +14 -0
  15. package/assets/templates/app/lib/__STOREFRONT__/state.ts +35 -0
  16. package/assets/templates/app/lib/__STOREFRONT__/views/index.ts +7 -0
  17. package/assets/templates/app/lib/__STOREFRONT__/views/sections/faq.tsx +29 -0
  18. package/assets/templates/app/lib/__STOREFRONT__/views/sections/logoCloud.tsx +29 -0
  19. package/assets/templates/app/lib/__STOREFRONT__/views/sections/pricing.tsx +33 -0
  20. package/assets/templates/app/lib/__STOREFRONT__/views/sections/statistics.tsx +29 -0
  21. package/assets/templates/app/lib/__STOREFRONT__/views/sections/testimonials.tsx +28 -0
  22. package/assets/templates/app/lib/__STOREFRONT__/views/types.ts +46 -0
  23. package/assets/templates/views/home/index.tsx +142 -0
  24. package/assets/templates/views/home/registry.tsx +65 -0
  25. package/bin/storefront.js +531 -0
  26. package/commands/sf-add-view.md +26 -0
  27. package/commands/sf-theme.md +20 -0
  28. package/commands/sf-view.md +25 -0
  29. package/package.json +48 -0
  30. package/recipes/archetype.schema.json +39 -0
  31. package/recipes/archetypes.json +148 -0
  32. package/recipes/recipe.schema.json +59 -0
  33. package/recipes/recipes.json +90 -0
  34. package/recipes/sections.json +46 -0
  35. package/recipes/validate.mjs +190 -0
  36. package/scripts/render-templates.mjs +255 -0
  37. package/scripts/sync-assets.mjs +87 -0
  38. package/skills/building-storefronts/SKILL.md +178 -0
  39. package/skills/building-storefronts/references/frontend-integration.md +229 -0
  40. package/skills/json-render-core/SKILL.md +291 -0
  41. package/skills/json-render-next/SKILL.md +194 -0
  42. package/skills/json-render-react/SKILL.md +298 -0
  43. package/skills/json-render-remotion/SKILL.md +111 -0
  44. package/skills/json-render-shadcn/SKILL.md +159 -0
  45. package/skills/json-render-solid/SKILL.md +204 -0
  46. package/skills/nextjs-shadcn/SKILL.md +367 -0
  47. package/skills/nextjs-shadcn/references/architecture.md +499 -0
  48. package/skills/nextjs-shadcn/references/project-setup.md +162 -0
  49. package/skills/nextjs-shadcn/references/shadcn-platform.md +261 -0
  50. package/skills/nextjs-shadcn/references/sidebar.md +274 -0
  51. package/skills/nextjs-shadcn/references/styling.md +555 -0
  52. package/skills/sf-theme-gen/SKILL.md +61 -0
  53. package/skills/sf-view-gen/SKILL.md +116 -0
  54. package/skills/sf-view-gen/assets/recipes/archetypes.json +148 -0
  55. package/skills/sf-view-gen/assets/recipes/recipes.json +90 -0
  56. package/skills/sf-view-gen/assets/recipes/sections.json +46 -0
  57. package/skills/sf-view-gen/assets/templates/views/category/index.tsx +86 -0
  58. package/skills/sf-view-gen/assets/templates/views/category/registry.tsx +48 -0
  59. package/skills/sf-view-gen/assets/templates/views/checkout/index.tsx +192 -0
  60. package/skills/sf-view-gen/assets/templates/views/checkout/registry.tsx +45 -0
  61. package/skills/sf-view-gen/assets/templates/views/product/index.tsx +122 -0
  62. package/skills/sf-view-gen/assets/templates/views/product/registry.tsx +49 -0
  63. package/skills/sf-view-gen/assets/templates/views/sections/faq.client.tsx +20 -0
  64. package/skills/sf-view-gen/assets/templates/views/sections/faq.tsx +21 -0
  65. package/skills/sf-view-gen/assets/templates/views/sections/logoCloud.client.tsx +18 -0
  66. package/skills/sf-view-gen/assets/templates/views/sections/logoCloud.tsx +21 -0
  67. package/skills/sf-view-gen/assets/templates/views/sections/pricing.client.tsx +20 -0
  68. package/skills/sf-view-gen/assets/templates/views/sections/pricing.tsx +23 -0
  69. package/skills/sf-view-gen/assets/templates/views/sections/statistics.client.tsx +18 -0
  70. package/skills/sf-view-gen/assets/templates/views/sections/statistics.tsx +21 -0
  71. package/skills/sf-view-gen/assets/templates/views/sections/testimonials.client.tsx +19 -0
  72. package/skills/sf-view-gen/assets/templates/views/sections/testimonials.tsx +19 -0
  73. package/skills/sf-view-gen/assets/templates/views/user-panel/index.tsx +168 -0
  74. package/skills/sf-view-gen/assets/templates/views/user-panel/registry.tsx +49 -0
  75. package/skills/sf-view-gen/references/views.md +69 -0
  76. package/skills/sf-view-gen/scripts/validate.mjs +190 -0
  77. package/skills/shadcn-component-discovery/SKILL.md +273 -0
  78. package/skills/shadcn-component-discovery/references/registries.md +226 -0
  79. package/skills/shadcn-theming/SKILL.md +104 -0
  80. package/skills/shadcn-theming/references/templates/theme-setup.md +109 -0
  81. package/skills/shadcn-theming/references/theming-guide.md +90 -0
  82. package/skills/storefront-best-practices/SKILL.md +421 -0
  83. package/skills/storefront-best-practices/reference/components/breadcrumbs.md +123 -0
  84. package/skills/storefront-best-practices/reference/components/cart-popup.md +189 -0
  85. package/skills/storefront-best-practices/reference/components/country-selector.md +298 -0
  86. package/skills/storefront-best-practices/reference/components/footer.md +112 -0
  87. package/skills/storefront-best-practices/reference/components/hero.md +241 -0
  88. package/skills/storefront-best-practices/reference/components/megamenu.md +239 -0
  89. package/skills/storefront-best-practices/reference/components/navbar.md +397 -0
  90. package/skills/storefront-best-practices/reference/components/popups.md +221 -0
  91. package/skills/storefront-best-practices/reference/components/product-card.md +125 -0
  92. package/skills/storefront-best-practices/reference/components/product-reviews.md +217 -0
  93. package/skills/storefront-best-practices/reference/components/product-slider.md +174 -0
  94. package/skills/storefront-best-practices/reference/components/search.md +101 -0
  95. package/skills/storefront-best-practices/reference/connecting-to-backend.md +391 -0
  96. package/skills/storefront-best-practices/reference/design.md +388 -0
  97. package/skills/storefront-best-practices/reference/features/promotions.md +307 -0
  98. package/skills/storefront-best-practices/reference/features/wishlist.md +230 -0
  99. package/skills/storefront-best-practices/reference/layouts/account.md +380 -0
  100. package/skills/storefront-best-practices/reference/layouts/cart.md +316 -0
  101. package/skills/storefront-best-practices/reference/layouts/checkout.md +486 -0
  102. package/skills/storefront-best-practices/reference/layouts/home-page.md +264 -0
  103. package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +231 -0
  104. package/skills/storefront-best-practices/reference/layouts/product-details.md +527 -0
  105. package/skills/storefront-best-practices/reference/layouts/product-listing.md +520 -0
  106. package/skills/storefront-best-practices/reference/layouts/static-pages.md +356 -0
  107. package/skills/storefront-best-practices/reference/medusa.md +307 -0
  108. package/skills/storefront-best-practices/reference/mobile-responsiveness.md +183 -0
  109. package/skills/storefront-best-practices/reference/seo.md +195 -0
@@ -0,0 +1,142 @@
1
+ // Thor Commerce view module: home
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 -> "home".
6
+
7
+ import { getCatalog } from '@thorprovider/runtime/commerce'
8
+ import { z } from 'zod'
9
+ import { pageRoot } from '../../spec/page-root'
10
+ import type { StorefrontElement } from '../../spec/types'
11
+ import type { ViewModule } from '../types'
12
+ import { registry } from './registry'
13
+ import { toFeaturedProduct } from '../../mappers'
14
+
15
+ const elements: Record<string, StorefrontElement> = {
16
+ 'home.hero': {
17
+ type: 'StorefrontHero',
18
+ props: {
19
+ badge: 'Bienvenido',
20
+ title: '__SITE_NAME__',
21
+ titleAccent: 'para cada proyecto',
22
+ description: 'Productos seleccionados con precios justos y entrega a tu puerta.',
23
+ products: { $state: '/heroProducts' },
24
+ primaryCta: { label: 'Comprar ahora' },
25
+ secondaryCta: { label: 'Ver categorías' },
26
+ },
27
+ on: { addToCart: { action: 'addToCart' }, openProduct: { action: 'openProduct' } },
28
+ },
29
+ 'home.benefits': {
30
+ type: 'Feature',
31
+ props: {
32
+ badge: '__SITE_NAME__',
33
+ title: 'Compra con confianza',
34
+ description: 'Beneficios pensados para que tu compra llegue segura y a tiempo.',
35
+ items: [
36
+ {
37
+ id: 'entrega',
38
+ title: 'Entrega segura',
39
+ description: 'Seguimiento de tu pedido hasta la puerta de tu casa.',
40
+ icon: 'truck',
41
+ },
42
+ {
43
+ id: 'pago',
44
+ title: 'Pago protegido',
45
+ description: 'Compra con confianza, múltiples opciones de pago.',
46
+ icon: 'shield-check',
47
+ },
48
+ {
49
+ id: 'soporte',
50
+ title: 'Soporte local',
51
+ description: 'Atención personalizada en todo el país.',
52
+ icon: 'headphones',
53
+ },
54
+ ],
55
+ },
56
+ },
57
+ 'home.categories': {
58
+ type: 'CategoryCards',
59
+ props: {
60
+ title: 'Compra por categoría',
61
+ description: 'Explora nuestro catálogo completo.',
62
+ categories: { $state: '/categories' },
63
+ },
64
+ on: { openCategory: { action: 'openCategory' } },
65
+ },
66
+ }
67
+
68
+ const ctaSchema = z.object({ label: z.string(), href: z.string().optional() })
69
+
70
+ // Mirrors the StorefrontHero block contract (FeaturedProduct) so a product-shape
71
+ // mismatch is a type error at the catalog boundary, not a runtime crash. The
72
+ // block requires every field — including `colors` — to be defined at render.
73
+ const featuredProductSchema = z.object({
74
+ id: z.string(),
75
+ name: z.string(),
76
+ brand: z.string(),
77
+ price: z.number(),
78
+ originalPrice: z.number(),
79
+ rating: z.number(),
80
+ reviewCount: z.number(),
81
+ inStock: z.boolean(),
82
+ isNew: z.boolean(),
83
+ isOnSale: z.boolean(),
84
+ image: z.string(),
85
+ colors: z.array(z.string()),
86
+ })
87
+
88
+ const catalog = {
89
+ StorefrontHero: {
90
+ props: z.object({
91
+ title: z.string(),
92
+ description: z.string(),
93
+ titleAccent: z.string().optional(),
94
+ badge: z.string().optional(),
95
+ products: z.array(featuredProductSchema),
96
+ primaryCta: ctaSchema.optional(),
97
+ secondaryCta: ctaSchema.optional(),
98
+ }),
99
+ description: 'Landing hero.',
100
+ },
101
+ Feature: {
102
+ props: z.object({
103
+ items: z.array(z.record(z.string(), z.unknown())),
104
+ badge: z.string().optional(),
105
+ title: z.string().optional(),
106
+ description: z.string().optional(),
107
+ }),
108
+ description: 'Benefit highlights.',
109
+ },
110
+ CategoryCards: {
111
+ props: z.object({
112
+ title: z.string().optional(),
113
+ description: z.string().optional(),
114
+ categories: z.array(z.record(z.string(), z.unknown())),
115
+ cta: ctaSchema.optional(),
116
+ }),
117
+ description: 'Category grid.',
118
+ },
119
+ }
120
+
121
+ export const home: ViewModule = {
122
+ name: 'home',
123
+ elements,
124
+ catalog,
125
+ registry,
126
+ route: {
127
+ path: '/',
128
+ loaderName: 'home',
129
+ layout: 'default',
130
+ metadata: {
131
+ title: 'Inicio',
132
+ description: 'Descubre los productos de __SITE_NAME__.',
133
+ },
134
+ entry: pageRoot('home', ['home.hero', 'home.benefits', 'home.categories'], elements),
135
+ },
136
+ loader: {
137
+ home: async () => {
138
+ const { products, categories } = await getCatalog()
139
+ return { heroProducts: products.slice(0, 4).map(toFeaturedProduct), categories }
140
+ },
141
+ },
142
+ }
@@ -0,0 +1,65 @@
1
+ 'use client'
2
+
3
+ // Thor Commerce view registry fragment: home
4
+ // Client boundary for the home 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
+ Feature1 as FeatureBlock,
11
+ ProductCategory2 as CategoryCardsBlock,
12
+ StorefrontHero1 as StorefrontHeroBlock,
13
+ } from '@thorprovider/blocks'
14
+ import type { FeaturedProduct } from '@thorprovider/blocks'
15
+ import { useStateStore } from '@json-render/react'
16
+ import type { ViewRegistry } from '../types'
17
+
18
+ export const registry: ViewRegistry = {
19
+ StorefrontHero: ({ props, emit }) => {
20
+ const { set } = useStateStore()
21
+ return (
22
+ <StorefrontHeroBlock
23
+ title={props.title as string}
24
+ description={props.description as string}
25
+ products={props.products as FeaturedProduct[]}
26
+ titleAccent={props.titleAccent as string}
27
+ badge={props.badge as string}
28
+ primaryCta={props.primaryCta as never}
29
+ secondaryCta={props.secondaryCta as never}
30
+ onAddToCart={(product) => {
31
+ set('/lastClicked', product)
32
+ emit('addToCart')
33
+ }}
34
+ onBuyNow={(product) => {
35
+ set('/lastClicked', product)
36
+ emit('openProduct')
37
+ }}
38
+ onSelectColor={() => {}}
39
+ />
40
+ )
41
+ },
42
+ Feature: ({ props }) => (
43
+ <FeatureBlock
44
+ items={props.items as never}
45
+ badge={props.badge as string}
46
+ title={props.title as string}
47
+ description={props.description as string}
48
+ />
49
+ ),
50
+ CategoryCards: ({ props, emit }) => {
51
+ const { set } = useStateStore()
52
+ return (
53
+ <CategoryCardsBlock
54
+ title={props.title as string}
55
+ description={props.description as string}
56
+ categories={props.categories as never}
57
+ cta={props.cta as never}
58
+ onBrowse={(category) => {
59
+ set('/lastCategory', (category.handle as string) ?? String(category.id))
60
+ emit('openCategory')
61
+ }}
62
+ />
63
+ )
64
+ },
65
+ }