@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.
- package/README.md +119 -0
- package/bin/install.js +116 -0
- package/commands/sf-add-view.md +21 -0
- package/commands/sf-init.md +16 -0
- package/commands/sf-theme.md +15 -0
- package/commands/sf-view.md +20 -0
- package/package.json +40 -0
- package/recipes/archetype.schema.json +39 -0
- package/recipes/archetypes.json +148 -0
- package/recipes/recipe.schema.json +59 -0
- package/recipes/recipes.json +90 -0
- package/recipes/sections.json +46 -0
- package/recipes/validate.mjs +190 -0
- package/skills/building-storefronts/SKILL.md +178 -0
- package/skills/building-storefronts/references/frontend-integration.md +229 -0
- package/skills/json-render-core/SKILL.md +291 -0
- package/skills/json-render-next/SKILL.md +194 -0
- package/skills/json-render-react/SKILL.md +298 -0
- package/skills/json-render-remotion/SKILL.md +111 -0
- package/skills/json-render-shadcn/SKILL.md +159 -0
- package/skills/json-render-solid/SKILL.md +204 -0
- package/skills/nextjs-shadcn/SKILL.md +303 -0
- package/skills/nextjs-shadcn/references/architecture.md +499 -0
- package/skills/nextjs-shadcn/references/project-setup.md +127 -0
- package/skills/nextjs-shadcn/references/shadcn-platform.md +258 -0
- package/skills/nextjs-shadcn/references/sidebar.md +274 -0
- package/skills/nextjs-shadcn/references/styling.md +555 -0
- package/skills/sf-scaffold/SKILL.md +118 -0
- package/skills/sf-theme-gen/SKILL.md +44 -0
- package/skills/sf-view-gen/SKILL.md +94 -0
- package/skills/shadcn-component-discovery/SKILL.md +273 -0
- package/skills/shadcn-component-discovery/references/registries.md +226 -0
- package/skills/shadcn-theming/SKILL.md +104 -0
- package/skills/shadcn-theming/references/templates/theme-setup.md +109 -0
- package/skills/shadcn-theming/references/theming-guide.md +90 -0
- package/skills/storefront-best-practices/SKILL.md +421 -0
- package/skills/storefront-best-practices/reference/components/breadcrumbs.md +123 -0
- package/skills/storefront-best-practices/reference/components/cart-popup.md +189 -0
- package/skills/storefront-best-practices/reference/components/country-selector.md +298 -0
- package/skills/storefront-best-practices/reference/components/footer.md +112 -0
- package/skills/storefront-best-practices/reference/components/hero.md +241 -0
- package/skills/storefront-best-practices/reference/components/megamenu.md +239 -0
- package/skills/storefront-best-practices/reference/components/navbar.md +397 -0
- package/skills/storefront-best-practices/reference/components/popups.md +221 -0
- package/skills/storefront-best-practices/reference/components/product-card.md +125 -0
- package/skills/storefront-best-practices/reference/components/product-reviews.md +217 -0
- package/skills/storefront-best-practices/reference/components/product-slider.md +174 -0
- package/skills/storefront-best-practices/reference/components/search.md +101 -0
- package/skills/storefront-best-practices/reference/connecting-to-backend.md +391 -0
- package/skills/storefront-best-practices/reference/design.md +388 -0
- package/skills/storefront-best-practices/reference/features/promotions.md +307 -0
- package/skills/storefront-best-practices/reference/features/wishlist.md +230 -0
- package/skills/storefront-best-practices/reference/layouts/account.md +380 -0
- package/skills/storefront-best-practices/reference/layouts/cart.md +316 -0
- package/skills/storefront-best-practices/reference/layouts/checkout.md +486 -0
- package/skills/storefront-best-practices/reference/layouts/home-page.md +264 -0
- package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +231 -0
- package/skills/storefront-best-practices/reference/layouts/product-details.md +527 -0
- package/skills/storefront-best-practices/reference/layouts/product-listing.md +520 -0
- package/skills/storefront-best-practices/reference/layouts/static-pages.md +356 -0
- package/skills/storefront-best-practices/reference/medusa.md +307 -0
- package/skills/storefront-best-practices/reference/mobile-responsiveness.md +183 -0
- package/skills/storefront-best-practices/reference/seo.md +195 -0
- package/templates/app/app/[[...slug]]/page.tsx +17 -0
- package/templates/app/app/[[...slug]]/renderer.tsx +10 -0
- package/templates/app/app/globals.css +101 -0
- package/templates/app/app/layout.tsx +35 -0
- package/templates/app/lib/__STOREFRONT__/catalog.ts +132 -0
- package/templates/app/lib/__STOREFRONT__/handlers.ts +33 -0
- package/templates/app/lib/__STOREFRONT__/registry.tsx +134 -0
- package/templates/app/lib/__STOREFRONT__/runtime.ts +25 -0
- package/templates/app/lib/__STOREFRONT__/spec/home.ts +62 -0
- package/templates/app/lib/__STOREFRONT__/spec/index.ts +59 -0
- package/templates/app/lib/__STOREFRONT__/spec/types.ts +14 -0
- package/templates/app/lib/__STOREFRONT__/state.ts +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@thorprovider/create-storefront"
|
|
3
|
+
purpose: "Installable command suite that scaffolds and customizes Thor Commerce storefronts"
|
|
4
|
+
lastReviewed: "2026-09-28"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# @thorprovider/create-storefront
|
|
8
|
+
|
|
9
|
+
Installable command suite that scaffolds and customizes Thor Commerce storefronts.
|
|
10
|
+
|
|
11
|
+
It ships a set of `/sf-*` OpenCode commands, their supporting skills, static project
|
|
12
|
+
templates, a recipe registry, and vendored skills — and installs them into any
|
|
13
|
+
project's `.opencode/` directory. Nothing else from the Thor Commerce monorepo is
|
|
14
|
+
required at generation time.
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
| Requirement | Supported |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| Node.js | >= 18.17.0 |
|
|
21
|
+
| Package manager | pnpm (for generated projects) |
|
|
22
|
+
| OpenCode | a version that supports project skills in `.opencode/skills/` |
|
|
23
|
+
| OS | macOS, Linux, Windows (via WSL) |
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
From the root of the project where you want the commands available:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pnpm dlx @thorprovider/create-storefront
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or, once installed as a dependency:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
create-storefront # installs into ./.opencode
|
|
37
|
+
create-storefront --dir apps/my-store
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The installer copies `commands/` and all skills under `skills/` (own skills and
|
|
41
|
+
vendored skills, flat) into `<target>/.opencode/`. It is idempotent: running it again
|
|
42
|
+
overwrites with the same versioned files and leaves everything else untouched.
|
|
43
|
+
|
|
44
|
+
After installing, open the project in OpenCode and run:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
/sf-init
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## What gets installed
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
<project>/.opencode/
|
|
54
|
+
.create-storefront-root # absolute package root (lets skills find templates/ + recipes/)
|
|
55
|
+
commands/
|
|
56
|
+
sf-init.md
|
|
57
|
+
sf-add-view.md
|
|
58
|
+
sf-view.md
|
|
59
|
+
sf-theme.md
|
|
60
|
+
skills/
|
|
61
|
+
sf-scaffold/
|
|
62
|
+
sf-view-gen/
|
|
63
|
+
sf-theme-gen/
|
|
64
|
+
nextjs-shadcn/
|
|
65
|
+
shadcn-theming/
|
|
66
|
+
shadcn-component-discovery/
|
|
67
|
+
storefront-best-practices/
|
|
68
|
+
building-storefronts/
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`templates/` and `recipes/` are **not** copied into the project. They are generation assets that stay in the installed package; the `.create-storefront-root` marker lets the skills resolve them at generation time. Keep the package installed (as a dependency or globally) while you use the commands.
|
|
72
|
+
|
|
73
|
+
## Commands
|
|
74
|
+
|
|
75
|
+
| Command | Purpose |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| `/sf-init` | Wizard: scaffold a new storefront with Next.js, `@thorprovider/blocks`, `@thorprovider/adapters` (Medusa), json-render, and a home view |
|
|
78
|
+
| `/sf-add-view <view>` | Add one view incrementally (`product`, `category`, `checkout`, `user-panel`) |
|
|
79
|
+
| `/sf-view <view> <change>` | Modify an existing view's spec, preserving structure |
|
|
80
|
+
| `/sf-theme` | Customize OKLCH color tokens (light/dark), typography, and identity metadata |
|
|
81
|
+
|
|
82
|
+
## First run
|
|
83
|
+
|
|
84
|
+
After installing into a project, open OpenCode in that project and run:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
/sf-init
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The wizard asks for a storefront name, Medusa backend URL, site name, and brand
|
|
91
|
+
color. It scaffolds a Next.js + json-render storefront with a home view, using
|
|
92
|
+
only `@thorprovider/blocks` for UI and `@thorprovider/adapters` for data.
|
|
93
|
+
|
|
94
|
+
Then grow the storefront incrementally:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
/sf-add-view product # add a view from its recipe
|
|
98
|
+
/sf-view home add a testimonials section # modify an existing view
|
|
99
|
+
/sf-theme # colors, typography, identity
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Generated projects expect a Medusa backend. Set `MEDUSA_BACKEND_URL` (and
|
|
103
|
+
`MEDUSA_REGION_ID`, `MEDUSA_PUBLISHABLE_KEY` as needed) in `.env.local`. Use the
|
|
104
|
+
`mock` adapter data source during local development.
|
|
105
|
+
|
|
106
|
+
## Design guarantees
|
|
107
|
+
|
|
108
|
+
- **Self-contained**: templates and skills travel with the package; no dependency on
|
|
109
|
+
the Thor Commerce monorepo or on machine-global skills at generation time.
|
|
110
|
+
- **Stack-constrained**: UI comes only from `@thorprovider/blocks`; data only from
|
|
111
|
+
`@thorprovider/adapters` and `@thorprovider/storefronts/commerce`.
|
|
112
|
+
- **Varied output**: a recipe registry lets the skills pick block variants and optional
|
|
113
|
+
sections (testimonials, FAQ, statistics, logo cloud, pricing) from your description,
|
|
114
|
+
so sites are not identical.
|
|
115
|
+
|
|
116
|
+
## Maintenance
|
|
117
|
+
|
|
118
|
+
See `VENDOR.md` for how vendored skills are refreshed and how to bump
|
|
119
|
+
templates.
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @thorprovider/create-storefront installer
|
|
3
|
+
// Copies commands/ and skills/ into <project>/.opencode/ (openspec-style).
|
|
4
|
+
// Idempotent: safe to re-run. Works without the Thor Commerce monorepo.
|
|
5
|
+
//
|
|
6
|
+
// Templates/ and recipes/ are NOT copied: they are generation assets that live
|
|
7
|
+
// inside the installed package and are resolved by the skills at generation
|
|
8
|
+
// time (see skills/sf-*/SKILL.md "Resolving package assets").
|
|
9
|
+
|
|
10
|
+
import { cp, mkdir, readdir, writeFile } from 'node:fs/promises'
|
|
11
|
+
import { existsSync } from 'node:fs'
|
|
12
|
+
import { dirname, join, resolve } from 'node:path'
|
|
13
|
+
import { fileURLToPath } from 'node:url'
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
16
|
+
const PKG_ROOT = resolve(__dirname, '..')
|
|
17
|
+
|
|
18
|
+
// Baked into the installed skills so they can locate templates/ and recipes/
|
|
19
|
+
// at generation time without walking the target filesystem.
|
|
20
|
+
const ASSET_MARKER_FILE = '.create-storefront-root'
|
|
21
|
+
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const out = { dir: process.cwd(), force: false }
|
|
24
|
+
for (let i = 0; i < argv.length; i++) {
|
|
25
|
+
const a = argv[i]
|
|
26
|
+
if (a === '--dir' || a === '-d') out.dir = resolve(argv[++i] ?? '.')
|
|
27
|
+
else if (a === '--force' || a === '-f') out.force = true
|
|
28
|
+
else if (a === '--help' || a === '-h') out.help = true
|
|
29
|
+
}
|
|
30
|
+
return out
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const HELP = `@thorprovider/create-storefront
|
|
34
|
+
|
|
35
|
+
Usage:
|
|
36
|
+
create-storefront [--dir <path>] [--force]
|
|
37
|
+
|
|
38
|
+
Installs the sf-* commands and skills into <path>/.opencode/.
|
|
39
|
+
Default <path> is the current working directory.
|
|
40
|
+
|
|
41
|
+
Options:
|
|
42
|
+
-d, --dir <path> Target project root (default: cwd)
|
|
43
|
+
-f, --force Overwrite files that already exist
|
|
44
|
+
-h, --help Show this help
|
|
45
|
+
`
|
|
46
|
+
|
|
47
|
+
async function copyDir(from, to, force) {
|
|
48
|
+
if (!existsSync(from)) return 0
|
|
49
|
+
await mkdir(to, { recursive: true })
|
|
50
|
+
let count = 0
|
|
51
|
+
const entries = await readdir(from, { withFileTypes: true })
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
const src = join(from, entry.name)
|
|
54
|
+
const dest = join(to, entry.name)
|
|
55
|
+
if (entry.isDirectory()) {
|
|
56
|
+
count += await copyDir(src, dest, force)
|
|
57
|
+
} else {
|
|
58
|
+
const exists = existsSync(dest)
|
|
59
|
+
if (exists && !force) continue
|
|
60
|
+
await cp(src, dest)
|
|
61
|
+
count++
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return count
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function main() {
|
|
68
|
+
const args = parseArgs(process.argv.slice(2))
|
|
69
|
+
if (args.help) {
|
|
70
|
+
console.log(HELP)
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const target = args.dir
|
|
75
|
+
if (!existsSync(target)) {
|
|
76
|
+
console.error(`Target directory does not exist: ${target}`)
|
|
77
|
+
process.exitCode = 1
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
const opencodeDir = join(target, '.opencode')
|
|
81
|
+
|
|
82
|
+
console.log(`Installing @thorprovider/create-storefront into ${opencodeDir}`)
|
|
83
|
+
|
|
84
|
+
const commands = await copyDir(
|
|
85
|
+
join(PKG_ROOT, 'commands'),
|
|
86
|
+
join(opencodeDir, 'commands'),
|
|
87
|
+
args.force,
|
|
88
|
+
)
|
|
89
|
+
const ownSkills = await copyDir(
|
|
90
|
+
join(PKG_ROOT, 'skills'),
|
|
91
|
+
join(opencodeDir, 'skills'),
|
|
92
|
+
args.force,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
// Record the package root so installed skills can resolve templates/ and
|
|
96
|
+
// recipes/ (generation assets) without the monorepo or a symlink.
|
|
97
|
+
const markerPath = join(opencodeDir, ASSET_MARKER_FILE)
|
|
98
|
+
if (args.force || !existsSync(markerPath)) {
|
|
99
|
+
await writeFile(markerPath, `${PKG_ROOT}\n`, 'utf8')
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(` commands: ${commands} file(s)`)
|
|
103
|
+
console.log(` skills: ${ownSkills} file(s)`)
|
|
104
|
+
console.log(` assets: ${PKG_ROOT} (templates/, recipes/)`)
|
|
105
|
+
console.log('')
|
|
106
|
+
console.log('Done. Available in OpenCode:')
|
|
107
|
+
console.log(' /sf-init /sf-add-view /sf-view /sf-theme')
|
|
108
|
+
if (!args.force) {
|
|
109
|
+
console.log('(Existing files were left untouched. Use --force to overwrite.)')
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
main().catch((err) => {
|
|
114
|
+
console.error(err)
|
|
115
|
+
process.exitCode = 1
|
|
116
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Add a single view to an existing Thor Commerce storefront (product, category, checkout, user-panel)"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Add one view to an existing Thor Commerce storefront, generated from a recipe.
|
|
6
|
+
|
|
7
|
+
**Input**: view name, optionally followed by a description of what the view should contain or emphasize.
|
|
8
|
+
Examples:
|
|
9
|
+
- `/sf-add-view product`
|
|
10
|
+
- `/sf-add-view category specialize in power stations, use a dense grid`
|
|
11
|
+
- `/sf-add-view checkout keep it single-page`
|
|
12
|
+
|
|
13
|
+
**Provided arguments**: $ARGUMENTS
|
|
14
|
+
|
|
15
|
+
Use the `sf-view-gen` skill.
|
|
16
|
+
|
|
17
|
+
**Constraints (do not violate without explicit user authorization):**
|
|
18
|
+
- Allowed view names: `home`, `product`, `category`, `checkout`, `user-panel`
|
|
19
|
+
- Block variants and optional sections MUST come from `recipes/` (`recipes.json`, `sections.json`)
|
|
20
|
+
- UI components come ONLY from `@thorprovider/blocks`
|
|
21
|
+
- Data access goes ONLY through `@thorprovider/adapters` / `@thorprovider/storefronts/commerce`
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Initialize a new Thor Commerce storefront (json-render + @thorprovider/blocks + Medusa via @thorprovider/adapters)"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Initialize a new Thor Commerce storefront via an interactive wizard.
|
|
6
|
+
|
|
7
|
+
**Input**: no arguments required — the wizard collects configuration.
|
|
8
|
+
**Provided arguments**: $ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Use the `sf-scaffold` skill to perform the initialization.
|
|
11
|
+
|
|
12
|
+
**Constraints (do not violate without explicit user authorization):**
|
|
13
|
+
- UI components come ONLY from `@thorprovider/blocks`
|
|
14
|
+
- Backend access goes ONLY through `@thorprovider/adapters` / `@thorprovider/storefronts/commerce`
|
|
15
|
+
- Views and components are generated from this package's `templates/` and `recipes/`
|
|
16
|
+
- Default scaffold is the `home` view only; other views are added with `/sf-add-view`
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Customize storefront theme: OKLCH colors (light/dark), typography, and identity metadata"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Customize the theme and identity of a Thor Commerce storefront.
|
|
6
|
+
|
|
7
|
+
**Input**: optional — the wizard asks what to customize (colors, typography, identity, SEO, Open Graph).
|
|
8
|
+
**Provided arguments**: $ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Use the `sf-theme-gen` skill.
|
|
11
|
+
|
|
12
|
+
**Constraints (do not violate without explicit user authorization):**
|
|
13
|
+
- Colors are CSS variables in OKLCH with complete background/foreground pairs (light AND dark)
|
|
14
|
+
- Never use raw Tailwind color utilities for themed colors
|
|
15
|
+
- Typography and metadata follow the package `templates/`
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Modify an existing storefront view's spec while preserving its structure"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Modify an existing view in a Thor Commerce storefront.
|
|
6
|
+
|
|
7
|
+
**Input**: view name followed by the change to make.
|
|
8
|
+
Examples:
|
|
9
|
+
- `/sf-view home add a statistics band after the hero`
|
|
10
|
+
- `/sf-view category switch to a 4-column grid`
|
|
11
|
+
|
|
12
|
+
**Provided arguments**: $ARGUMENTS
|
|
13
|
+
|
|
14
|
+
Use the `sf-view-gen` skill (modification workflow).
|
|
15
|
+
|
|
16
|
+
**Constraints (do not violate without explicit user authorization):**
|
|
17
|
+
- Allowed view names: `home`, `product`, `category`, `checkout`, `user-panel`
|
|
18
|
+
- Preserve element ids, `type`, untouched `props`, `$state` bindings, and `on` wiring
|
|
19
|
+
- Only add block variants/sections declared in `recipes/`
|
|
20
|
+
- UI components come ONLY from `@thorprovider/blocks`
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thorprovider/create-storefront",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Installable OpenCode command suite that scaffolds Thor Commerce json-render storefronts (Next.js, @thorprovider/blocks, @thorprovider/adapters, Medusa)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-storefront": "./bin/install.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"commands",
|
|
12
|
+
"skills",
|
|
13
|
+
"templates",
|
|
14
|
+
"recipes",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18.17.0"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"install:opencode": "node ./bin/install.js"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"registry": "https://registry.npmjs.org/"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/thorprovider/thor-commerce",
|
|
30
|
+
"directory": "packages/create-storefront"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"thor-commerce",
|
|
34
|
+
"opencode",
|
|
35
|
+
"storefront",
|
|
36
|
+
"json-render",
|
|
37
|
+
"scaffolding"
|
|
38
|
+
],
|
|
39
|
+
"license": "MIT"
|
|
40
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "archetype.schema.json",
|
|
4
|
+
"title": "Storefront archetype manifest",
|
|
5
|
+
"description": "Maps slots to named intents. Each intent resolves to a block variant that must be allowed by the view recipe for that slot.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["version", "slots"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": { "type": "string" },
|
|
11
|
+
"version": { "type": "string" },
|
|
12
|
+
"description": { "type": "string" },
|
|
13
|
+
"slots": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"minProperties": 1,
|
|
16
|
+
"additionalProperties": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": ["default", "intents"],
|
|
19
|
+
"additionalProperties": false,
|
|
20
|
+
"properties": {
|
|
21
|
+
"default": { "type": "string" },
|
|
22
|
+
"intents": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"minProperties": 1,
|
|
25
|
+
"additionalProperties": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"required": ["variant", "when"],
|
|
28
|
+
"additionalProperties": false,
|
|
29
|
+
"properties": {
|
|
30
|
+
"variant": { "type": "string" },
|
|
31
|
+
"when": { "type": "string", "minLength": 10 }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./archetype.schema.json",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Archetype (intent) layer. Maps a slot to named intents so selection is by meaning, not by variant ordinal. Each intent resolves to a variant that MUST be allowed by the recipe for that slot.",
|
|
5
|
+
"slots": {
|
|
6
|
+
"home.hero": {
|
|
7
|
+
"default": "showcase",
|
|
8
|
+
"intents": {
|
|
9
|
+
"compact": {
|
|
10
|
+
"variant": "StorefrontHero1",
|
|
11
|
+
"when": "A simple, text-forward hero with a single call to action and no product showcase."
|
|
12
|
+
},
|
|
13
|
+
"showcase": {
|
|
14
|
+
"variant": "StorefrontHero2",
|
|
15
|
+
"when": "A product-led hero that displays featured products alongside the headline."
|
|
16
|
+
},
|
|
17
|
+
"editorial": {
|
|
18
|
+
"variant": "StorefrontHero5",
|
|
19
|
+
"when": "A storytelling or brand-editorial hero with strong imagery and a narrative tone."
|
|
20
|
+
},
|
|
21
|
+
"promotional": {
|
|
22
|
+
"variant": "StorefrontHero6",
|
|
23
|
+
"when": "A campaign hero built around an offer, discount, or seasonal promotion."
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"home.benefits": {
|
|
28
|
+
"default": "compact",
|
|
29
|
+
"intents": {
|
|
30
|
+
"compact": {
|
|
31
|
+
"variant": "Feature1",
|
|
32
|
+
"when": "A short list of benefits with icons and one-line descriptions."
|
|
33
|
+
},
|
|
34
|
+
"detailed": {
|
|
35
|
+
"variant": "Feature2",
|
|
36
|
+
"when": "Benefits that need longer explanations, richer layout, or supporting media."
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"home.categories": {
|
|
41
|
+
"default": "standard",
|
|
42
|
+
"intents": {
|
|
43
|
+
"standard": {
|
|
44
|
+
"variant": "ProductCategory2",
|
|
45
|
+
"when": "A balanced grid of category cards with image and label."
|
|
46
|
+
},
|
|
47
|
+
"iconGrid": {
|
|
48
|
+
"variant": "ProductCategory1",
|
|
49
|
+
"when": "A compact icon-based category grid for many small categories."
|
|
50
|
+
},
|
|
51
|
+
"featured": {
|
|
52
|
+
"variant": "ProductCategory4",
|
|
53
|
+
"when": "Few, large featured category tiles that act as primary navigation."
|
|
54
|
+
},
|
|
55
|
+
"editorial": {
|
|
56
|
+
"variant": "ProductCategory5",
|
|
57
|
+
"when": "Category tiles presented as editorial imagery blocks."
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"product.overview": {
|
|
62
|
+
"default": "standard",
|
|
63
|
+
"intents": {
|
|
64
|
+
"standard": {
|
|
65
|
+
"variant": "ProductOverview1",
|
|
66
|
+
"when": "A straightforward product detail layout: gallery, title, price, add to cart."
|
|
67
|
+
},
|
|
68
|
+
"gallery": {
|
|
69
|
+
"variant": "ProductOverview2",
|
|
70
|
+
"when": "The product needs emphasis on a large image gallery with thumbnails."
|
|
71
|
+
},
|
|
72
|
+
"rich": {
|
|
73
|
+
"variant": "ProductOverview5",
|
|
74
|
+
"when": "A detailed product page with tabs, specs, and extensive structured information."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"product.reviews": {
|
|
79
|
+
"default": "list",
|
|
80
|
+
"intents": {
|
|
81
|
+
"list": {
|
|
82
|
+
"variant": "ReviewRating1",
|
|
83
|
+
"when": "A simple list of customer reviews with star ratings."
|
|
84
|
+
},
|
|
85
|
+
"summary": {
|
|
86
|
+
"variant": "ReviewRating2",
|
|
87
|
+
"when": "Reviews led by an aggregate rating summary and distribution."
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"category.filter": {
|
|
92
|
+
"default": "sidebar",
|
|
93
|
+
"intents": {
|
|
94
|
+
"inline": {
|
|
95
|
+
"variant": "CategoryFilter1",
|
|
96
|
+
"when": "A compact inline filter bar above the product grid."
|
|
97
|
+
},
|
|
98
|
+
"sidebar": {
|
|
99
|
+
"variant": "CategoryFilter2",
|
|
100
|
+
"when": "A left sidebar with facets, price range, and sort controls."
|
|
101
|
+
},
|
|
102
|
+
"rich": {
|
|
103
|
+
"variant": "CategoryFilter4",
|
|
104
|
+
"when": "Advanced faceted filtering with multiple facet groups and active-filter chips."
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"checkout.checkout": {
|
|
109
|
+
"default": "singlePage",
|
|
110
|
+
"intents": {
|
|
111
|
+
"singlePage": {
|
|
112
|
+
"variant": "CheckoutForm1",
|
|
113
|
+
"when": "A single-page checkout combining contact, shipping, and payment."
|
|
114
|
+
},
|
|
115
|
+
"multiStep": {
|
|
116
|
+
"variant": "CheckoutForm2",
|
|
117
|
+
"when": "A stepper checkout split into address, delivery, and payment steps."
|
|
118
|
+
},
|
|
119
|
+
"compact": {
|
|
120
|
+
"variant": "CheckoutForm3",
|
|
121
|
+
"when": "A minimal one-column checkout for fast, low-friction purchase."
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"user-panel.shell": {
|
|
126
|
+
"default": "standard",
|
|
127
|
+
"intents": {
|
|
128
|
+
"standard": {
|
|
129
|
+
"variant": "AppShell1",
|
|
130
|
+
"when": "A standard account shell with side navigation and content area."
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"user-panel.orderHistory": {
|
|
135
|
+
"default": "compact",
|
|
136
|
+
"intents": {
|
|
137
|
+
"compact": {
|
|
138
|
+
"variant": "OrderHistory1",
|
|
139
|
+
"when": "A concise list of past orders with status and totals."
|
|
140
|
+
},
|
|
141
|
+
"detailed": {
|
|
142
|
+
"variant": "OrderHistory2",
|
|
143
|
+
"when": "Order history with line-item detail, tracking, and reorder actions."
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://thorcommerce.dev/create-storefront/recipe.schema.json",
|
|
4
|
+
"title": "Thor Commerce Storefront View Recipe",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["version", "views"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"version": { "type": "string" },
|
|
9
|
+
"views": {
|
|
10
|
+
"type": "array",
|
|
11
|
+
"items": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"required": [
|
|
14
|
+
"name",
|
|
15
|
+
"description",
|
|
16
|
+
"route",
|
|
17
|
+
"loader",
|
|
18
|
+
"requiredDataKeys",
|
|
19
|
+
"defaultVariants",
|
|
20
|
+
"allowedVariants",
|
|
21
|
+
"optionalSections"
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"name": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["home", "product", "category", "checkout", "user-panel"]
|
|
27
|
+
},
|
|
28
|
+
"description": { "type": "string" },
|
|
29
|
+
"route": { "type": "string" },
|
|
30
|
+
"loader": { "type": "string" },
|
|
31
|
+
"requiredDataKeys": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": { "type": "string" },
|
|
34
|
+
"minItems": 1
|
|
35
|
+
},
|
|
36
|
+
"defaultVariants": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"additionalProperties": { "type": "string" }
|
|
39
|
+
},
|
|
40
|
+
"allowedVariants": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"additionalProperties": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"items": { "type": "string" },
|
|
45
|
+
"minItems": 1
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"optionalSections": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"enum": ["testimonials", "faq", "statistics", "logoCloud", "pricing"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|