@thorprovider/create-storefront 0.1.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 (75) hide show
  1. package/README.md +119 -0
  2. package/bin/install.js +116 -0
  3. package/commands/sf-add-view.md +21 -0
  4. package/commands/sf-init.md +16 -0
  5. package/commands/sf-theme.md +15 -0
  6. package/commands/sf-view.md +20 -0
  7. package/package.json +40 -0
  8. package/recipes/archetype.schema.json +39 -0
  9. package/recipes/archetypes.json +148 -0
  10. package/recipes/recipe.schema.json +59 -0
  11. package/recipes/recipes.json +90 -0
  12. package/recipes/sections.json +46 -0
  13. package/recipes/validate.mjs +190 -0
  14. package/skills/building-storefronts/SKILL.md +178 -0
  15. package/skills/building-storefronts/references/frontend-integration.md +229 -0
  16. package/skills/json-render-core/SKILL.md +291 -0
  17. package/skills/json-render-next/SKILL.md +194 -0
  18. package/skills/json-render-react/SKILL.md +298 -0
  19. package/skills/json-render-remotion/SKILL.md +111 -0
  20. package/skills/json-render-shadcn/SKILL.md +159 -0
  21. package/skills/json-render-solid/SKILL.md +204 -0
  22. package/skills/nextjs-shadcn/SKILL.md +303 -0
  23. package/skills/nextjs-shadcn/references/architecture.md +499 -0
  24. package/skills/nextjs-shadcn/references/project-setup.md +127 -0
  25. package/skills/nextjs-shadcn/references/shadcn-platform.md +258 -0
  26. package/skills/nextjs-shadcn/references/sidebar.md +274 -0
  27. package/skills/nextjs-shadcn/references/styling.md +555 -0
  28. package/skills/sf-scaffold/SKILL.md +118 -0
  29. package/skills/sf-theme-gen/SKILL.md +44 -0
  30. package/skills/sf-view-gen/SKILL.md +94 -0
  31. package/skills/shadcn-component-discovery/SKILL.md +273 -0
  32. package/skills/shadcn-component-discovery/references/registries.md +226 -0
  33. package/skills/shadcn-theming/SKILL.md +104 -0
  34. package/skills/shadcn-theming/references/templates/theme-setup.md +109 -0
  35. package/skills/shadcn-theming/references/theming-guide.md +90 -0
  36. package/skills/storefront-best-practices/SKILL.md +421 -0
  37. package/skills/storefront-best-practices/reference/components/breadcrumbs.md +123 -0
  38. package/skills/storefront-best-practices/reference/components/cart-popup.md +189 -0
  39. package/skills/storefront-best-practices/reference/components/country-selector.md +298 -0
  40. package/skills/storefront-best-practices/reference/components/footer.md +112 -0
  41. package/skills/storefront-best-practices/reference/components/hero.md +241 -0
  42. package/skills/storefront-best-practices/reference/components/megamenu.md +239 -0
  43. package/skills/storefront-best-practices/reference/components/navbar.md +397 -0
  44. package/skills/storefront-best-practices/reference/components/popups.md +221 -0
  45. package/skills/storefront-best-practices/reference/components/product-card.md +125 -0
  46. package/skills/storefront-best-practices/reference/components/product-reviews.md +217 -0
  47. package/skills/storefront-best-practices/reference/components/product-slider.md +174 -0
  48. package/skills/storefront-best-practices/reference/components/search.md +101 -0
  49. package/skills/storefront-best-practices/reference/connecting-to-backend.md +391 -0
  50. package/skills/storefront-best-practices/reference/design.md +388 -0
  51. package/skills/storefront-best-practices/reference/features/promotions.md +307 -0
  52. package/skills/storefront-best-practices/reference/features/wishlist.md +230 -0
  53. package/skills/storefront-best-practices/reference/layouts/account.md +380 -0
  54. package/skills/storefront-best-practices/reference/layouts/cart.md +316 -0
  55. package/skills/storefront-best-practices/reference/layouts/checkout.md +486 -0
  56. package/skills/storefront-best-practices/reference/layouts/home-page.md +264 -0
  57. package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +231 -0
  58. package/skills/storefront-best-practices/reference/layouts/product-details.md +527 -0
  59. package/skills/storefront-best-practices/reference/layouts/product-listing.md +520 -0
  60. package/skills/storefront-best-practices/reference/layouts/static-pages.md +356 -0
  61. package/skills/storefront-best-practices/reference/medusa.md +307 -0
  62. package/skills/storefront-best-practices/reference/mobile-responsiveness.md +183 -0
  63. package/skills/storefront-best-practices/reference/seo.md +195 -0
  64. package/templates/app/app/[[...slug]]/page.tsx +17 -0
  65. package/templates/app/app/[[...slug]]/renderer.tsx +10 -0
  66. package/templates/app/app/globals.css +101 -0
  67. package/templates/app/app/layout.tsx +35 -0
  68. package/templates/app/lib/__STOREFRONT__/catalog.ts +132 -0
  69. package/templates/app/lib/__STOREFRONT__/handlers.ts +33 -0
  70. package/templates/app/lib/__STOREFRONT__/registry.tsx +134 -0
  71. package/templates/app/lib/__STOREFRONT__/runtime.ts +25 -0
  72. package/templates/app/lib/__STOREFRONT__/spec/home.ts +62 -0
  73. package/templates/app/lib/__STOREFRONT__/spec/index.ts +59 -0
  74. package/templates/app/lib/__STOREFRONT__/spec/types.ts +14 -0
  75. package/templates/app/lib/__STOREFRONT__/state.ts +35 -0
@@ -0,0 +1,183 @@
1
+ # Mobile Responsiveness for Ecommerce Storefronts
2
+
3
+ ## Contents
4
+
5
+ - [Overview](#overview)
6
+ - [Mobile Ecommerce Patterns](#mobile-ecommerce-patterns)
7
+ - [Touch-Friendly Interactions](#touch-friendly-interactions)
8
+ - [Mobile Performance](#mobile-performance)
9
+ - [Safe Area Insets (iOS)](#safe-area-insets-ios)
10
+ - [Common Mobile Mistakes](#common-mobile-mistakes)
11
+
12
+ ## Overview
13
+
14
+ Over 60% of ecommerce traffic is mobile. Mobile-first design is essential for conversion.
15
+
16
+ ### Key Requirements
17
+
18
+ - Mobile-first CSS (min-width media queries)
19
+ - 44x44px minimum touch targets
20
+ - Sticky header with cart access
21
+ - Large form inputs (48px height minimum)
22
+ - Optimized images for mobile
23
+ - Fast loading (LCP < 2.5s)
24
+
25
+ **Assumed knowledge**: AI agents already know mobile-first design principles, breakpoints, and responsive CSS. This guide focuses on ecommerce-specific mobile patterns.
26
+
27
+ ## Mobile Ecommerce Patterns
28
+
29
+ ### Sticky Elements (Critical for Conversion)
30
+
31
+ **Cart access always visible:**
32
+ - Sticky header with cart icon (top-right)
33
+ - Or: Sticky bottom navigation with cart
34
+ - Never hide cart in hamburger drawer
35
+ - Shows count badge, updates in real-time
36
+
37
+ **Sticky "Add to Cart" bar (product pages):**
38
+ - Fixed at bottom of screen
39
+ - Shows: Price + "Add to Cart" button
40
+ - Appears after scrolling past fold
41
+ - Always accessible without scrolling
42
+ - **CRITICAL: Must use `env(safe-area-inset-bottom)` for iOS devices** (see Safe Area Insets section)
43
+ - Significantly higher conversion rates
44
+
45
+ ### Mobile Navigation Patterns
46
+
47
+ **Bottom navigation (optional pattern):**
48
+ - Consider for mobile-heavy stores (>70% mobile traffic)
49
+ - 4-5 primary actions: Home, Categories, Cart, Account, Search
50
+ - Fixed at bottom (easier thumb access)
51
+ - Icons + labels for clarity
52
+
53
+ **When to use:**
54
+ - Mobile-first brands (fashion, beauty)
55
+ - Younger demographic (18-34)
56
+ - App-like experience desired
57
+
58
+ **When NOT to use:**
59
+ - Desktop-heavy traffic
60
+ - Complex navigation needs (>5 items)
61
+ - B2B stores (desktop-focused)
62
+
63
+ ### Mobile Product Browsing
64
+
65
+ **Image galleries:**
66
+ - Full-width swipeable carousel
67
+ - Pinch to zoom
68
+ - Tap to open full-screen view
69
+ - Dot indicators (1/5, 2/5)
70
+
71
+ **Filter drawer:**
72
+ - "Filters" button with badge count (e.g., "Filters (3)")
73
+ - Slide-out drawer (full-screen or 80% width)
74
+ - Accordion sections for filter categories
75
+ - "Apply" button at bottom (batch filtering)
76
+ - "Clear All" option at top
77
+
78
+ **Why batch filtering on mobile:**
79
+ - Prevents multiple re-renders on slow connections
80
+ - User adjusts multiple filters before applying
81
+ - Less disruptive mobile UX
82
+
83
+ ### Mobile Checkout Optimization
84
+
85
+ **Digital wallets priority (CRITICAL for mobile conversion):**
86
+ - Apple Pay / Google Pay buttons prominent at top (if supported in ecommerce backend)
87
+ - Can improve mobile checkout conversion by 20-40%
88
+ - One-click payment with pre-filled shipping addresses (if supported in ecommerce backend)
89
+ - Consider making digital wallet the default on mobile
90
+
91
+ **Decision: Order summary placement**
92
+ - Collapsible at top (recommended): Saves screen space for form, expandable for review
93
+ - Fixed at bottom: Always visible but takes space from form
94
+ - Use collapsible on mobile to prioritize form completion
95
+
96
+ **Form optimizations:**
97
+ - Single-column layout (never multi-column on mobile)
98
+ - 44-48px input height minimum
99
+ - Proper keyboard types (`inputMode="email"`, `"numeric"`, `"tel"`)
100
+ - Autocomplete attributes for autofill (`autocomplete="email"`, `"name"`, `"address-line1"`)
101
+ - Consider single-page layout over multi-step (less friction on mobile)
102
+
103
+ ## Touch-Friendly Interactions
104
+
105
+ **Standard touch targets:** 44x44px minimum for all interactive elements. Pay special attention to:
106
+ - Filter checkboxes on product listings
107
+ - Quantity +/- buttons on product pages
108
+ - Small action buttons on product cards
109
+ - Modal close buttons
110
+
111
+ **Swipe gestures for ecommerce:**
112
+ - Product image galleries (critical - users expect swipeable images)
113
+ - Related product sliders
114
+ - Category carousels
115
+
116
+ **Mobile input optimization:**
117
+ - 16px minimum font size for inputs (prevents iOS auto-zoom)
118
+ - Proper `inputMode` attributes: `"email"`, `"numeric"`, `"tel"`
119
+ - Autocomplete attributes: `autocomplete="email"`, `"name"`, `"address-line1"`
120
+
121
+ ## Mobile Performance
122
+
123
+ **Ecommerce performance priorities:**
124
+
125
+ 1. **Product images** (highest impact): Optimize for mobile (<500KB), lazy load below-fold, responsive images with appropriate sizes
126
+ 2. **Optimistic UI**: Cart count updates immediately, instant feedback on add to cart
127
+ 3. **Skeleton screens**: Show loading placeholders for product grids, not blank pages
128
+
129
+ **Critical mobile performance issues:**
130
+ - Unoptimized product images (>1MB) - most common issue
131
+ - Loading entire product catalog at once - use pagination or infinite scroll
132
+ - Heavy analytics scripts on checkout - defer to post-purchase
133
+
134
+ **Target**: LCP < 2.5s, mobile-optimized images, server-side rendering for product pages
135
+
136
+ ## Safe Area Insets (iOS)
137
+
138
+ Use `env(safe-area-inset-*)` to handle iOS notches and rounded corners on:
139
+ - Sticky headers (top inset)
140
+ - Sticky bottom navigation or add-to-cart bars (bottom inset)
141
+ - Full-screen modals
142
+
143
+ **Critical for ecommerce**: Bottom "Add to Cart" bars will be cut off by iOS home indicator without bottom inset (~34px). Test on real iOS devices with notches.
144
+
145
+ ## Common Mobile Mistakes
146
+
147
+ **Ecommerce-specific mobile issues:**
148
+
149
+ 1. **Hiding cart in drawer** - Cart icon hidden in hamburger menu. Keep cart always visible in header (top-right).
150
+
151
+ 2. **No sticky cart access** - Cart scrolls off screen on product pages. Use sticky header or sticky bottom "Add to Cart" bar.
152
+
153
+ 3. **Desktop-sized images** - Serving 2MB+ product images to mobile. Use responsive images optimized for mobile (<500KB).
154
+
155
+ 4. **Poor form experience** - Small inputs, wrong keyboards, no autocomplete. Use 48px inputs, proper `inputMode`, autocomplete attributes.
156
+
157
+ 5. **Hover-only interactions** - Quick view, wishlist only work on hover. Add tap handlers, show on tap instead.
158
+
159
+ 6. **Ignoring safe area insets** - Bottom "Add to Cart" bars cut off by iOS home indicator. Use `env(safe-area-inset-bottom)` for sticky bottom elements.
160
+
161
+ 7. **No digital wallet options** - Missing Apple Pay/Google Pay on mobile checkout. Mobile users expect one-tap checkout options.
162
+
163
+ ## Mobile Checklist
164
+
165
+ **Essential mobile optimizations:**
166
+
167
+ - [ ] Mobile-first CSS (min-width media queries)
168
+ - [ ] 44x44px minimum touch targets throughout
169
+ - [ ] Adequate spacing between interactive elements (8-16px)
170
+ - [ ] Sticky header with cart icon (always visible)
171
+ - [ ] Or: Sticky bottom "Add to Cart" bar on product pages
172
+ - [ ] Large form inputs (48px height minimum)
173
+ - [ ] Appropriate input types (`inputMode="email"`, `"numeric"`, `"tel"`)
174
+ - [ ] Swipeable image galleries on product pages
175
+ - [ ] Filter drawer with batch apply on product listings
176
+ - [ ] Digital wallets prominent in checkout (Apple Pay, Google Pay)
177
+ - [ ] Collapsible order summary in checkout
178
+ - [ ] Optimized images for mobile (<500KB)
179
+ - [ ] Lazy loading for below-fold content
180
+ - [ ] Safe area insets for iOS notches (sticky elements)
181
+ - [ ] 16px minimum font size (prevents iOS auto-zoom)
182
+ - [ ] Test on real mobile devices (not just Chrome DevTools)
183
+ - [ ] Core Web Vitals within targets (LCP < 2.5s, CLS < 0.1, INP < 200ms)
@@ -0,0 +1,195 @@
1
+ # SEO Optimization for Ecommerce Storefronts
2
+
3
+ ## Contents
4
+
5
+ - [Overview](#overview)
6
+ - [Meta Tags Requirements](#meta-tags-requirements)
7
+ - [Structured Data (Critical for Ecommerce)](#structured-data-critical-for-ecommerce)
8
+ - [Ecommerce URL Patterns](#ecommerce-url-patterns)
9
+ - [Product Page SEO](#product-page-seo)
10
+ - [Duplicate Content Issues](#duplicate-content-issues)
11
+ - [Dynamic Sitemaps](#dynamic-sitemaps)
12
+ - [Common SEO Mistakes](#common-seo-mistakes)
13
+
14
+ ## Overview
15
+
16
+ SEO is critical for ecommerce - organic search drives high-intent traffic. Proper implementation helps search engines understand products and enables rich results (star ratings, price, availability in search).
17
+
18
+ **Assumed knowledge**: AI agents know basic SEO (meta tags, Open Graph, Core Web Vitals). This guide focuses on ecommerce-specific patterns.
19
+
20
+ ### Every Product Page Needs
21
+
22
+ - Unique title and description (product name + features)
23
+ - Product schema with price, availability, rating
24
+ - Breadcrumb schema (category hierarchy)
25
+ - Canonical URL (prevents duplicate content)
26
+ - Descriptive image alt text
27
+ - Fast load time (LCP < 2.5s)
28
+
29
+ ## Meta Tags Requirements
30
+
31
+ Generate unique meta tags for every product page dynamically from product data:
32
+
33
+ - **Title**: "Product Name - Key Feature | Store Name" (50-60 characters)
34
+ - **Description**: Key features + USP (150-160 characters)
35
+ - **Open Graph** tags for social sharing (image 1200x630px)
36
+ - **Canonical URL** for variants and category paths
37
+
38
+ **Common mistake**: Same title/description across all products. Generate dynamically from product data.
39
+
40
+ ## Structured Data (Critical for Ecommerce)
41
+
42
+ Enables rich results in search (star ratings, price, availability shown directly in search results).
43
+
44
+ ### Product Schema (Required on All Product Pages)
45
+
46
+ Implement schema.org Product structured data with these critical fields:
47
+
48
+ **Essential fields:**
49
+ - `name`, `description`, `image`, `sku`, `brand`
50
+ - `offers` object with:
51
+ - `price`: Current price (Medusa: use as-is; other backends: check format)
52
+ - `priceCurrency`: ISO 4217 code (USD, EUR, GBP)
53
+ - `availability`: Must accurately reflect real stock status (InStock, OutOfStock, PreOrder)
54
+ - `priceValidUntil`: Required for Google Shopping (set 30+ days in future)
55
+
56
+ **Critical**: `availability` must be dynamic and accurate. Marking out-of-stock items as InStock violates Google's guidelines.
57
+
58
+ ### AggregateRating Schema (When Reviews Exist)
59
+
60
+ Add `aggregateRating` object to Product schema when real reviews exist:
61
+ - `ratingValue`: Average rating (e.g., "4.5")
62
+ - `reviewCount`: Total number of reviews
63
+ - `bestRating`: "5", `worstRating`: "1"
64
+
65
+ Displays star ratings in search results - powerful for CTR. **Only use for real reviews** - fake reviews violate guidelines.
66
+
67
+ ### Breadcrumb Schema (Navigation Hierarchy)
68
+
69
+ Implement schema.org BreadcrumbList showing category hierarchy:
70
+ - Home → Category → Product
71
+ - Each level has `position`, `name`, `item` URL
72
+ - Helps search engines understand site structure
73
+
74
+ ### Organization Schema (Homepage Only)
75
+
76
+ Add on homepage only: Organization name, URL, logo, contact information. Helps establish brand identity in search.
77
+
78
+ ## Ecommerce URL Patterns
79
+
80
+ **Product URLs**: Use readable slugs with hyphens (`/products/wireless-headphones-pro`). Include keywords naturally, keep short (<75 characters), never change URLs.
81
+
82
+ **Category URLs**: Choose consistent structure:
83
+ - Hierarchical (`/categories/electronics/laptops`) for deep catalogs
84
+ - Flat (`/categories/laptops`) for simpler management
85
+ - Don't mix both approaches
86
+
87
+ **Pagination URLs**: Use query parameters (`/products?page=2`). Implement `rel="prev"` and `rel="next"` tags. Each page is canonical to itself (NOT to page 1) so all pages can be indexed.
88
+
89
+ **Filter URLs**: Use query parameters (`/products?color=blue&size=large`).
90
+
91
+ **Canonical decision for filters:**
92
+ - Few filters (2-3): Index filtered pages (primary navigation)
93
+ - Many filters (5+): Canonical to unfiltered (prevents duplicate content)
94
+ - Popular combinations: Consider indexing separately
95
+
96
+ ## Product Page SEO
97
+
98
+ **Title tags**: Pattern "Product Name - Key Feature | Store Name" (50-60 characters). Avoid generic titles or keyword stuffing.
99
+
100
+ **Meta descriptions**: Include 2-3 key features + USP (free shipping, returns, warranty) in 150-160 characters. Make it compelling.
101
+
102
+ **Image alt text**: Descriptive and specific. Describe what's visible, include product name and key visual attributes. Don't keyword stuff. Keep under 125 characters.
103
+
104
+ ## Duplicate Content Issues
105
+
106
+ ### Ecommerce Duplicate Content Challenges
107
+
108
+ **Common scenarios:**
109
+ 1. **Product variants**: Same product in multiple colors/sizes
110
+ 2. **Multiple categories**: Product listed in multiple categories
111
+ 3. **Filter combinations**: Filtered views create unique URLs
112
+ 4. **Sort parameters**: Sorted views create unique URLs
113
+
114
+ ### Solution: Canonical URLs
115
+
116
+ **Variant handling:**
117
+ - Choose one variant as canonical (usually default)
118
+ - All other variants canonical to that one
119
+ - Example: Blue, Red, Green shirts all canonical to Blue (default)
120
+
121
+ **Multiple category paths:**
122
+ - Choose one category as canonical (usually primary category)
123
+ - Example: Product in both "Electronics" and "Laptops" → canonical to "Laptops"
124
+
125
+ **Filtered/sorted views:**
126
+ - Canonical to unfiltered, default-sorted page
127
+ - Example: `/products?color=blue&sort=price` → canonical to `/products`
128
+
129
+ **Implementation:**
130
+ ```html
131
+ <!-- On variant page (Red shirt) -->
132
+ <link rel="canonical" href="https://yourstore.com/products/cotton-tshirt" />
133
+
134
+ <!-- On filtered page -->
135
+ <link rel="canonical" href="https://yourstore.com/products" />
136
+ ```
137
+
138
+ ## Dynamic Sitemaps
139
+
140
+ Generate sitemaps dynamically from database to help search engines discover all products and categories.
141
+
142
+ **Requirements:**
143
+ - Include all public product and category pages
144
+ - Update `lastModified` when products change (fetch from database)
145
+ - Exclude `noindex` pages and filtered/sorted URLs
146
+ - Split into multiple sitemaps if >50,000 URLs
147
+ - Priority: Homepage (1.0) > Products (0.8) > Categories (0.6)
148
+
149
+ **Critical**: Regenerate sitemap when products are added/updated. Submit sitemap URL to Google Search Console.
150
+
151
+ ## Common SEO Mistakes
152
+
153
+ **Ecommerce-specific SEO issues:**
154
+
155
+ 1. **Duplicate content** - Same product accessible via multiple URLs (variants, categories). Use canonical URLs to consolidate signals.
156
+
157
+ 2. **Missing Product schema** - No structured data on product pages. Implement Product schema for rich results (ratings, price in search).
158
+
159
+ 3. **Incorrect availability status** - Marking out-of-stock items as "InStock" in schema. Dynamically set based on real stock levels (violates Google guidelines).
160
+
161
+ 4. **Thin product content** - Only image and price, no description. Add detailed descriptions, specifications, reviews (200+ words).
162
+
163
+ 5. **Static sitemap** - Never updates when products change. Generate dynamically from database so search engines discover new products.
164
+
165
+ 6. **Poor image alt text** - Missing or generic "product image". Use descriptive alt text for image search traffic.
166
+
167
+ ## SEO Checklist
168
+
169
+ ### On Every Product Page
170
+
171
+ - [ ] Unique, descriptive title tag (50-60 characters)
172
+ - [ ] Unique, compelling meta description (150-160 characters)
173
+ - [ ] Open Graph and Twitter Card tags
174
+ - [ ] Product schema with price, availability, rating (if reviews exist)
175
+ - [ ] Breadcrumb schema (category hierarchy)
176
+ - [ ] Descriptive alt text on all images
177
+ - [ ] Canonical URL (especially for variants)
178
+ - [ ] Fast load time (LCP < 2.5s)
179
+ - [ ] Mobile-responsive design
180
+ - [ ] Internal links to related products/categories
181
+ - [ ] Detailed product description (200+ words ideal)
182
+
183
+ ### Site-wide
184
+
185
+ - [ ] Dynamic XML sitemap submitted to search engines
186
+ - [ ] Robots.txt properly configured
187
+ - [ ] SSL certificate (HTTPS)
188
+ - [ ] Mobile-friendly design (44px touch targets)
189
+ - [ ] Organization schema on homepage
190
+ - [ ] Proper heading hierarchy (H1 for product title)
191
+ - [ ] Pagination implemented with rel="prev/next"
192
+ - [ ] Canonical URLs for filtered/sorted pages
193
+ - [ ] 404 pages with helpful navigation
194
+ - [ ] Image optimization (WebP, lazy loading)
195
+ - [ ] Core Web Vitals within targets (LCP < 2.5s, CLS < 0.1, INP < 200ms)
@@ -0,0 +1,17 @@
1
+ // Generated by Thor Commerce sf-scaffold (template: templates/app/app/[[...slug]]/page.tsx)
2
+
3
+ import { notFound } from 'next/navigation'
4
+ import { __STOREFRONT_CAMEL__App } from '@/lib/__STOREFRONT__/runtime'
5
+ import { StorefrontRenderer } from './renderer'
6
+
7
+ export const { generateMetadata, generateStaticParams } = __STOREFRONT_CAMEL__App
8
+
9
+ export default async function Page({
10
+ params,
11
+ }: {
12
+ params: Promise<{ slug?: string[] }>
13
+ }) {
14
+ const data = await __STOREFRONT_CAMEL__App.getPageData({ params })
15
+ if (!data) return notFound()
16
+ return <StorefrontRenderer {...data} />
17
+ }
@@ -0,0 +1,10 @@
1
+ 'use client'
2
+
3
+ // Generated by Thor Commerce sf-scaffold (template: templates/app/app/[[...slug]]/renderer.tsx)
4
+
5
+ import { PageRenderer } from '@json-render/next'
6
+ import type { PageData } from '@json-render/next'
7
+
8
+ export function StorefrontRenderer(data: PageData) {
9
+ return <PageRenderer {...data} />
10
+ }
@@ -0,0 +1,101 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "@thorprovider/blocks/styles.css";
4
+
5
+ @custom-variant dark (&:is(.dark *));
6
+
7
+ @theme inline {
8
+ --color-background: var(--background);
9
+ --color-foreground: var(--foreground);
10
+ --color-card: var(--card);
11
+ --color-card-foreground: var(--card-foreground);
12
+ --color-popover: var(--popover);
13
+ --color-popover-foreground: var(--popover-foreground);
14
+ --color-primary: var(--primary);
15
+ --color-primary-foreground: var(--primary-foreground);
16
+ --color-secondary: var(--secondary);
17
+ --color-secondary-foreground: var(--secondary-foreground);
18
+ --color-muted: var(--muted);
19
+ --color-muted-foreground: var(--muted-foreground);
20
+ --color-accent: var(--accent);
21
+ --color-accent-foreground: var(--accent-foreground);
22
+ --color-destructive: var(--destructive);
23
+ --color-destructive-foreground: var(--destructive-foreground);
24
+ --color-success: var(--success);
25
+ --color-success-foreground: var(--success-foreground);
26
+ --color-warning: var(--warning);
27
+ --color-warning-foreground: var(--warning-foreground);
28
+ --color-border: var(--border);
29
+ --color-input: var(--input);
30
+ --color-ring: var(--ring);
31
+ --radius-sm: var(--radius-sm);
32
+ --radius-md: var(--radius-md);
33
+ --radius-lg: var(--radius-lg);
34
+ --radius-xl: var(--radius-xl);
35
+ --font-sans: var(--font-geist-sans);
36
+ }
37
+
38
+ :root {
39
+ --background: oklch(0.98 0.002 90);
40
+ --foreground: oklch(0.15 0 0);
41
+ --card: oklch(1 0 0);
42
+ --card-foreground: oklch(0.15 0 0);
43
+ --popover: oklch(1 0 0);
44
+ --popover-foreground: oklch(0.15 0 0);
45
+ --primary: oklch(0.15 0 0);
46
+ --primary-foreground: oklch(0.98 0.002 90);
47
+ --secondary: oklch(0.96 0.003 90);
48
+ --secondary-foreground: oklch(0.15 0 0);
49
+ --muted: oklch(0.94 0.003 90);
50
+ --muted-foreground: oklch(0.45 0 0);
51
+ --accent: oklch(0.58 0.16 25);
52
+ --accent-foreground: oklch(1 0 0);
53
+ --destructive: oklch(0.55 0.2 25);
54
+ --destructive-foreground: oklch(0.98 0.002 90);
55
+ --success: oklch(0.47 0.14 155);
56
+ --success-foreground: oklch(0.98 0.01 155);
57
+ --warning: oklch(0.55 0.18 75);
58
+ --warning-foreground: oklch(0.98 0.02 75);
59
+ --border: oklch(0.88 0.003 90);
60
+ --input: oklch(0.92 0.003 90);
61
+ --ring: oklch(0.15 0 0);
62
+ --radius-sm: 0.25rem;
63
+ --radius-md: 0.375rem;
64
+ --radius-lg: 0.5rem;
65
+ --radius-xl: 0.75rem;
66
+ }
67
+
68
+ .dark {
69
+ --background: oklch(0.15 0 0);
70
+ --foreground: oklch(0.98 0.002 90);
71
+ --card: oklch(0.2 0 0);
72
+ --card-foreground: oklch(0.98 0.002 90);
73
+ --popover: oklch(0.2 0 0);
74
+ --popover-foreground: oklch(0.98 0.002 90);
75
+ --primary: oklch(0.98 0.002 90);
76
+ --primary-foreground: oklch(0.15 0 0);
77
+ --secondary: oklch(0.25 0.003 90);
78
+ --secondary-foreground: oklch(0.98 0.002 90);
79
+ --muted: oklch(0.25 0.003 90);
80
+ --muted-foreground: oklch(0.65 0 0);
81
+ --accent: oklch(0.65 0.15 25);
82
+ --accent-foreground: oklch(0.15 0 0);
83
+ --destructive: oklch(0.65 0.2 25);
84
+ --destructive-foreground: oklch(0.15 0 0);
85
+ --success: oklch(0.6 0.13 155);
86
+ --success-foreground: oklch(0.1 0.02 155);
87
+ --warning: oklch(0.7 0.15 75);
88
+ --warning-foreground: oklch(0.1 0.02 75);
89
+ --border: oklch(0.3 0.003 90);
90
+ --input: oklch(0.3 0.003 90);
91
+ --ring: oklch(0.85 0 0);
92
+ }
93
+
94
+ @layer base {
95
+ * {
96
+ @apply border-border;
97
+ }
98
+ body {
99
+ @apply bg-background text-foreground;
100
+ }
101
+ }
@@ -0,0 +1,35 @@
1
+ // Generated by Thor Commerce sf-scaffold (template: templates/app/app/layout.tsx)
2
+
3
+ import type { Metadata } from 'next'
4
+ import { Geist } from 'next/font/google'
5
+ import { StorefrontProvider } from '@thorprovider/storefronts/host-glue/providers'
6
+ import { themeVarsToCss, themeTokensToVars } from '@thorprovider/storefronts/render-core/theme'
7
+ import { DEFAULT_THEME_TOKENS } from '@thorprovider/storefronts/contracts'
8
+ import { registry } from '@/lib/__STOREFRONT__/registry'
9
+ import './globals.css'
10
+
11
+ const geist = Geist({
12
+ variable: '--font-geist-sans',
13
+ subsets: ['latin'],
14
+ })
15
+
16
+ const themeCss = themeVarsToCss(themeTokensToVars(DEFAULT_THEME_TOKENS))
17
+
18
+ export const metadata: Metadata = {
19
+ title: '__SITE_NAME__',
20
+ description: 'Tienda online de __SITE_NAME__.',
21
+ }
22
+
23
+ export default function RootLayout({
24
+ children,
25
+ }: Readonly<{ children: React.ReactNode }>) {
26
+ return (
27
+ <html lang="es" className={geist.variable}>
28
+ <body className="font-sans antialiased">
29
+ <StorefrontProvider themeCss={themeCss} registry={registry}>
30
+ {children}
31
+ </StorefrontProvider>
32
+ </body>
33
+ </html>
34
+ )
35
+ }
@@ -0,0 +1,132 @@
1
+ // Generated by Thor Commerce sf-scaffold (template: templates/app/lib/__STOREFRONT__/catalog.ts)
2
+ // json-render catalog for the base storefront. Recipe-added views extend this file.
3
+ // UI contracts come exclusively from @thorprovider/blocks.
4
+
5
+ import { defineCatalog } from '@json-render/core'
6
+ import { schema } from '@json-render/react/schema'
7
+ import { z } from 'zod'
8
+ import { cardProductSchema } from '@thorprovider/blocks'
9
+
10
+ const ctaSchema = z.object({
11
+ label: z.string(),
12
+ href: z.string().optional(),
13
+ })
14
+
15
+ const navLinkSchema = z.object({
16
+ label: z.string(),
17
+ href: z.string().optional(),
18
+ })
19
+
20
+ const footerLinkSchema = z.object({
21
+ label: z.string(),
22
+ href: z.string().optional(),
23
+ })
24
+
25
+ const footerLinkColumnSchema = z.object({
26
+ title: z.string(),
27
+ links: z.array(footerLinkSchema),
28
+ })
29
+
30
+ const featuredProductSchema = z.object({
31
+ id: z.union([z.string(), z.number()]),
32
+ name: z.string(),
33
+ price: z.number(),
34
+ image: z.string(),
35
+ href: z.string().optional(),
36
+ })
37
+
38
+ const categoryCardSchema = z.object({
39
+ id: z.union([z.string(), z.number()]),
40
+ title: z.string(),
41
+ image: z.string(),
42
+ href: z.string().optional(),
43
+ count: z.number().optional(),
44
+ })
45
+
46
+ const featureItemSchema = z.object({
47
+ id: z.union([z.string(), z.number()]),
48
+ title: z.string(),
49
+ description: z.string(),
50
+ icon: z.string().optional(),
51
+ })
52
+
53
+ const productSchema = cardProductSchema
54
+
55
+ export const catalog = defineCatalog(schema, {
56
+ components: {
57
+ Layout: {
58
+ props: z.object({}),
59
+ slots: ['default', 'header', 'footer'],
60
+ description: 'Shared store layout with header and footer regions',
61
+ },
62
+ Navbar: {
63
+ props: z.object({
64
+ navLinks: z.array(navLinkSchema),
65
+ logoText: z.string(),
66
+ logoHref: z.string().optional(),
67
+ currentPath: z.string().optional(),
68
+ signIn: ctaSchema.optional(),
69
+ cta: ctaSchema.optional(),
70
+ cartCount: z.number().optional(),
71
+ }),
72
+ description: 'Store navigation bar with links and auth CTA',
73
+ },
74
+ StorefrontHero: {
75
+ props: z.object({
76
+ title: z.string(),
77
+ description: z.string(),
78
+ products: z.array(featuredProductSchema),
79
+ titleAccent: z.string().optional(),
80
+ badge: z.string().optional(),
81
+ primaryCta: ctaSchema.optional(),
82
+ secondaryCta: ctaSchema.optional(),
83
+ }),
84
+ description: 'E-commerce storefront hero with featured products',
85
+ },
86
+ Feature: {
87
+ props: z.object({
88
+ items: z.array(featureItemSchema),
89
+ badge: z.string().optional(),
90
+ title: z.string().optional(),
91
+ description: z.string().optional(),
92
+ learnMoreLabel: z.string().optional(),
93
+ ctaLabel: z.string().optional(),
94
+ }),
95
+ description: 'Feature benefits grid',
96
+ },
97
+ CategoryCards: {
98
+ props: z.object({
99
+ title: z.string().optional(),
100
+ description: z.string().optional(),
101
+ categories: z.array(categoryCardSchema),
102
+ cta: ctaSchema.optional(),
103
+ }),
104
+ description: 'Category grid with image overlay',
105
+ },
106
+ ProductCard: {
107
+ props: z.object({
108
+ products: z.array(productSchema),
109
+ heading: z.string().optional(),
110
+ maxItems: z.number().optional(),
111
+ }),
112
+ description: 'Product grid',
113
+ },
114
+ Footer: {
115
+ props: z.object({
116
+ brandName: z.string(),
117
+ brandDescription: z.string().optional(),
118
+ linkColumns: z.array(footerLinkColumnSchema),
119
+ newsletter: z
120
+ .object({
121
+ placeholder: z.string().optional(),
122
+ buttonLabel: z.string(),
123
+ })
124
+ .optional(),
125
+ }),
126
+ description: 'Store footer with link columns and newsletter',
127
+ },
128
+ },
129
+ actions: {},
130
+ })
131
+
132
+ export type StorefrontCatalog = typeof catalog