@salesforce/b2c-dx-mcp 2.0.0 → 2.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 +15 -62
- package/dist/commands/mcp.d.ts +1 -0
- package/dist/commands/mcp.js +41 -9
- package/dist/registry.d.ts +3 -4
- package/dist/registry.js +7 -14
- package/dist/server.d.ts +1 -1
- package/dist/server.js +3 -1
- package/dist/services.d.ts +21 -1
- package/dist/services.js +39 -6
- package/dist/tools/adapter.d.ts +18 -2
- package/dist/tools/adapter.js +49 -10
- package/dist/tools/cartridges/index.js +16 -22
- package/dist/tools/diagnostics/config-inspect.js +4 -8
- package/dist/tools/diagnostics/debug-capture-at-breakpoint.js +3 -9
- package/dist/tools/diagnostics/debug-list-sessions.js +1 -0
- package/dist/tools/diagnostics/debug-start-session.js +16 -9
- package/dist/tools/diagnostics/debug-wait-for-stop.js +1 -3
- package/dist/tools/diagnostics/log-watch-registry.d.ts +3 -0
- package/dist/tools/diagnostics/log-watch-registry.js +1 -0
- package/dist/tools/diagnostics/logs-get-recent.js +2 -5
- package/dist/tools/diagnostics/logs-list-files.js +1 -1
- package/dist/tools/diagnostics/logs-watch-list.js +1 -0
- package/dist/tools/diagnostics/logs-watch-start.js +10 -10
- package/dist/tools/diagnostics/mrt-log-watch-registry.d.ts +3 -0
- package/dist/tools/diagnostics/mrt-log-watch-registry.js +0 -0
- package/dist/tools/diagnostics/mrt-logs-watch-list.js +1 -0
- package/dist/tools/diagnostics/mrt-logs-watch-poll.js +2 -5
- package/dist/tools/diagnostics/mrt-logs-watch-start.js +9 -8
- package/dist/tools/diagnostics/session-registry.d.ts +3 -0
- package/dist/tools/diagnostics/session-registry.js +2 -1
- package/dist/tools/docs/docs-list.js +4 -6
- package/dist/tools/docs/docs-read.js +2 -9
- package/dist/tools/docs/docs-schema-list.js +1 -1
- package/dist/tools/docs/docs-schema-read.js +2 -3
- package/dist/tools/docs/docs-schema-search.js +2 -2
- package/dist/tools/docs/docs-search.js +3 -9
- package/dist/tools/docs/storefront.js +3 -3
- package/dist/tools/docs/topics.js +3 -1
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.js +0 -1
- package/dist/tools/mrt/index.js +6 -2
- package/dist/tools/project-context.d.ts +38 -11
- package/dist/tools/project-context.js +32 -15
- package/dist/tools/pwav3/pwa-kit-development-guidelines.js +3 -43
- package/dist/tools/scapi/metrics-get.js +5 -23
- package/dist/tools/scapi/scapi-custom-api-generate-scaffold.d.ts +4 -0
- package/dist/tools/scapi/scapi-custom-api-generate-scaffold.js +29 -14
- package/dist/tools/scapi/scapi-custom-apis-get-status.js +3 -14
- package/dist/tools/scapi/scapi-schemas-list.js +11 -11
- package/dist/utils/constants.d.ts +2 -13
- package/dist/utils/constants.js +1 -20
- package/oclif.manifest.json +2 -2
- package/package.json +5 -5
- package/content/sfnext/auth.md +0 -62
- package/content/sfnext/components.md +0 -123
- package/content/sfnext/config.md +0 -180
- package/content/sfnext/data-fetching.md +0 -323
- package/content/sfnext/extensions.md +0 -80
- package/content/sfnext/i18n.md +0 -121
- package/content/sfnext/page-designer.md +0 -78
- package/content/sfnext/performance.md +0 -80
- package/content/sfnext/pitfalls.md +0 -141
- package/content/sfnext/quick-reference.md +0 -226
- package/content/sfnext/state-management.md +0 -75
- package/content/sfnext/styling.md +0 -51
- package/content/sfnext/testing.md +0 -232
- package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.d.ts +0 -24
- package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.js +0 -53
- package/dist/tools/storefrontnext/figma/figma-to-component/index.d.ts +0 -45
- package/dist/tools/storefrontnext/figma/figma-to-component/index.js +0 -332
- package/dist/tools/storefrontnext/figma/generate-component/decision.d.ts +0 -40
- package/dist/tools/storefrontnext/figma/generate-component/decision.js +0 -312
- package/dist/tools/storefrontnext/figma/generate-component/formatter.d.ts +0 -9
- package/dist/tools/storefrontnext/figma/generate-component/formatter.js +0 -92
- package/dist/tools/storefrontnext/figma/generate-component/index.d.ts +0 -117
- package/dist/tools/storefrontnext/figma/generate-component/index.js +0 -102
- package/dist/tools/storefrontnext/figma/map-tokens/css-parser.d.ts +0 -71
- package/dist/tools/storefrontnext/figma/map-tokens/css-parser.js +0 -260
- package/dist/tools/storefrontnext/figma/map-tokens/index.d.ts +0 -64
- package/dist/tools/storefrontnext/figma/map-tokens/index.js +0 -242
- package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.d.ts +0 -65
- package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.js +0 -268
- package/dist/tools/storefrontnext/index.d.ts +0 -30
- package/dist/tools/storefrontnext/index.js +0 -28
- package/dist/tools/storefrontnext/page-designer-decorator/analyzer.d.ts +0 -169
- package/dist/tools/storefrontnext/page-designer-decorator/analyzer.js +0 -567
- package/dist/tools/storefrontnext/page-designer-decorator/index.d.ts +0 -259
- package/dist/tools/storefrontnext/page-designer-decorator/index.js +0 -622
- package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.d.ts +0 -8
- package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.js +0 -65
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.d.ts +0 -13
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.js +0 -87
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.d.ts +0 -4
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.js +0 -55
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.d.ts +0 -22
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.js +0 -109
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.d.ts +0 -21
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.js +0 -60
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.d.ts +0 -27
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.js +0 -68
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.d.ts +0 -4
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.js +0 -65
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.d.ts +0 -11
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.js +0 -92
- package/dist/tools/storefrontnext/page-designer-decorator/rules.d.ts +0 -51
- package/dist/tools/storefrontnext/page-designer-decorator/rules.js +0 -70
- package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.d.ts +0 -116
- package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.js +0 -350
- package/dist/tools/storefrontnext/sfnext-development-guidelines.d.ts +0 -9
- package/dist/tools/storefrontnext/sfnext-development-guidelines.js +0 -141
- package/dist/tools/storefrontnext/site-theming/color-contrast.d.ts +0 -92
- package/dist/tools/storefrontnext/site-theming/color-contrast.js +0 -186
- package/dist/tools/storefrontnext/site-theming/color-mapping.d.ts +0 -16
- package/dist/tools/storefrontnext/site-theming/color-mapping.js +0 -131
- package/dist/tools/storefrontnext/site-theming/guidance-merger.d.ts +0 -11
- package/dist/tools/storefrontnext/site-theming/guidance-merger.js +0 -78
- package/dist/tools/storefrontnext/site-theming/index.d.ts +0 -14
- package/dist/tools/storefrontnext/site-theming/index.js +0 -128
- package/dist/tools/storefrontnext/site-theming/response-builder.d.ts +0 -16
- package/dist/tools/storefrontnext/site-theming/response-builder.js +0 -316
- package/dist/tools/storefrontnext/site-theming/theming-store.d.ts +0 -64
- package/dist/tools/storefrontnext/site-theming/theming-store.js +0 -417
- package/dist/tools/storefrontnext/site-theming/types.d.ts +0 -36
- package/dist/tools/storefrontnext/site-theming/types.js +0 -7
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# Common Pitfalls
|
|
2
|
-
|
|
3
|
-
## 1. Using Client Loaders/Actions
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
// ❌ NEVER USE - Client loaders are not permitted
|
|
7
|
-
export function clientLoader() { ... }
|
|
8
|
-
|
|
9
|
-
// ❌ NEVER USE - Client actions are not permitted
|
|
10
|
-
export function clientAction() { ... }
|
|
11
|
-
|
|
12
|
-
// ✅ REQUIRED - Server-only data loading
|
|
13
|
-
export function loader({ context }: LoaderFunctionArgs) {
|
|
14
|
-
const clients = createApiClients(context);
|
|
15
|
-
return { product: clients.shopperProducts.getProduct({...}) };
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// ✅ REQUIRED - Server-only actions
|
|
19
|
-
export async function action({ request, context }: ActionFunctionArgs) {
|
|
20
|
-
const clients = createApiClients(context);
|
|
21
|
-
// Handle mutation on server
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
**Decision tree:**
|
|
26
|
-
|
|
27
|
-
```text
|
|
28
|
-
Need data for page render?
|
|
29
|
-
└─ Use server `loader`
|
|
30
|
-
|
|
31
|
-
Need to handle mutations (form submissions, cart updates)?
|
|
32
|
-
└─ Use server `action`
|
|
33
|
-
|
|
34
|
-
Need on-demand fetching after page load?
|
|
35
|
-
└─ Use `useScapiFetcher` (search, modals, infinite scroll)
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
**Key Point:** ALL SCAPI requests happen on the server:
|
|
39
|
-
- `loader`: Runs on server, SCAPI direct (prod) or proxied (dev)
|
|
40
|
-
- `action`: Runs on server, handles mutations securely
|
|
41
|
-
- `useScapiFetcher`: Triggers server route that calls SCAPI
|
|
42
|
-
|
|
43
|
-
## 2. Module-Level i18n in Schemas
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// ❌ RACE CONDITION
|
|
47
|
-
const schema = z.object({
|
|
48
|
-
email: z.string().email(t('error')),
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// ✅ FACTORY PATTERN
|
|
52
|
-
export const createSchema = (t: TFunction) => {
|
|
53
|
-
return z.object({
|
|
54
|
-
email: z.string().email(t('error')),
|
|
55
|
-
});
|
|
56
|
-
};
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## 3. Using Async Loaders (Blocks Page Transitions)
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
// ❌ BLOCKS PAGE TRANSITIONS - Async loader with await
|
|
63
|
-
export async function loader({ context }: LoaderFunctionArgs) {
|
|
64
|
-
const product = await fetchProduct(); // Blocks!
|
|
65
|
-
const reviews = await fetchReviews(); // Blocks!
|
|
66
|
-
return { product, reviews };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// ✅ NON-BLOCKING - Synchronous loader returning promises
|
|
70
|
-
export function loader({ context }: LoaderFunctionArgs): PageData {
|
|
71
|
-
return {
|
|
72
|
-
product: fetchProduct(), // Streams progressively
|
|
73
|
-
reviews: fetchReviews(), // Streams progressively
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**Key insight:** Defining loaders as `async` and using `await` causes the entire page transition to block until all data resolves. Use synchronous loaders returning promises for streaming.
|
|
79
|
-
|
|
80
|
-
**Reference:** See `data-fetching` section for comprehensive loader patterns including mixed strategies (awaited + streamed).
|
|
81
|
-
|
|
82
|
-
## 4. Modifying shadcn/ui
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
// ❌ NEVER modify src/components/ui/
|
|
86
|
-
|
|
87
|
-
// ✅ Create wrapper
|
|
88
|
-
import { Button } from '@/components/ui/button';
|
|
89
|
-
export function MyButton(props) {
|
|
90
|
-
return <Button {...props} className="custom" />;
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## 5. Missing Namespace in i18n
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
// ❌ MISSING NAMESPACE
|
|
98
|
-
const {t} = useTranslation();
|
|
99
|
-
t('title'); // Won't work
|
|
100
|
-
|
|
101
|
-
// ✅ USE NAMESPACE
|
|
102
|
-
const {t} = useTranslation('product');
|
|
103
|
-
t('title'); // Works
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## 6. Not Using Context in Server Loaders
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
// ❌ MISSING CONTEXT
|
|
110
|
-
export function loader() {
|
|
111
|
-
const config = getConfig(); // Wrong!
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// ✅ PASS CONTEXT
|
|
115
|
-
export function loader({ context }: LoaderFunctionArgs) {
|
|
116
|
-
const config = getConfig(context); // Correct
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## 7. Forgetting to Namespace i18n Keys
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// ❌ MISSING NAMESPACE
|
|
124
|
-
const { t } = useTranslation();
|
|
125
|
-
t('title'); // Won't work without namespace
|
|
126
|
-
|
|
127
|
-
// ✅ USE NAMESPACE
|
|
128
|
-
const { t } = useTranslation('product');
|
|
129
|
-
t('title'); // Works
|
|
130
|
-
|
|
131
|
-
// OR
|
|
132
|
-
const { t } = getTranslation();
|
|
133
|
-
t('product:title'); // Works
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## 8. Using JavaScript Files
|
|
137
|
-
|
|
138
|
-
```text
|
|
139
|
-
❌ .js, .jsx, .mjs, .cjs files are BLOCKED
|
|
140
|
-
✅ Use .ts, .tsx files only
|
|
141
|
-
```
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
# Storefront Next - Development Guidelines (Quick Reference)
|
|
2
|
-
|
|
3
|
-
⚠️ **READ THESE CRITICAL RULES BEFORE WRITING ANY CODE** ⚠️
|
|
4
|
-
|
|
5
|
-
## 🏗️ Architecture Overview
|
|
6
|
-
|
|
7
|
-
**Server-rendered SPA** built on React Server Components:
|
|
8
|
-
- **React Router 7** in framework mode
|
|
9
|
-
- **Managed Runtime (MRT)** as data orchestration layer
|
|
10
|
-
- **All SCAPI requests execute on MRT server** (both SSR and client-side navigation)
|
|
11
|
-
|
|
12
|
-
**Key Point**: Client-side routing does NOT mean client-side data fetching. Loaders always run on the server.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## 🚨 Non-Negotiable Rules
|
|
17
|
-
|
|
18
|
-
### 1. Server-Only Data Loading
|
|
19
|
-
|
|
20
|
-
✅ **REQUIRED**: Use server `loader` for all SCAPI data fetching
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
export function loader({ context }: LoaderFunctionArgs): PageData {
|
|
24
|
-
const clients = createApiClients(context);
|
|
25
|
-
return {
|
|
26
|
-
product: clients.shopperProducts.getProduct({...}), // Promise - streams
|
|
27
|
-
reviews: clients.shopperProducts.getReviews({...}), // Promise - streams
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**Why?** Keeps SCAPI requests on MRT server for security, performance, and bundle size.
|
|
33
|
-
|
|
34
|
-
### 2. Synchronous Loaders (Not Async)
|
|
35
|
-
|
|
36
|
-
✅ **CRITICAL**: Loaders must be **synchronous functions that return promises**, NOT async functions.
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
// ✅ CORRECT - Enables streaming
|
|
40
|
-
export function loader({ context }: LoaderFunctionArgs): PageData {
|
|
41
|
-
const clients = createApiClients(context);
|
|
42
|
-
return {
|
|
43
|
-
product: clients.shopperProducts.getProduct({...}), // Promise - streams
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// ❌ AVOID - Blocks page transitions
|
|
48
|
-
export async function loader({ context }: LoaderFunctionArgs) {
|
|
49
|
-
const product = await clients.shopperProducts.getProduct({...}); // Blocks!
|
|
50
|
-
return { product };
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
**Why?** Async loaders block page transitions. Synchronous loaders enable progressive streaming.
|
|
55
|
-
|
|
56
|
-
### 3. TypeScript-Only
|
|
57
|
-
|
|
58
|
-
✅ **REQUIRED**: Use `.ts` and `.tsx` file extensions
|
|
59
|
-
❌ **BLOCKED**: `.js`, `.jsx`, `.mjs`, `.cjs` files are forbidden by ESLint
|
|
60
|
-
|
|
61
|
-
### 4. Use createPage() HOC
|
|
62
|
-
|
|
63
|
-
✅ **RECOMMENDED**: Use `createPage()` for standardized page patterns
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
import { createPage } from '@/components/create-page';
|
|
67
|
-
|
|
68
|
-
const ProductPage = createPage({
|
|
69
|
-
component: ProductView,
|
|
70
|
-
fallback: <ProductSkeleton />
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
export default ProductPage;
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### 5. Tailwind CSS 4 Only
|
|
77
|
-
|
|
78
|
-
✅ **REQUIRED**: Use Tailwind utility classes only
|
|
79
|
-
❌ **BLOCKED**: No inline styles (`style={{...}}`), no CSS modules, no separate CSS files
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
// ✅ CORRECT - Tailwind utilities
|
|
83
|
-
<div className="rounded-lg border border-border bg-card p-4">
|
|
84
|
-
<h2 className="text-lg font-semibold text-card-foreground">
|
|
85
|
-
{product.name}
|
|
86
|
-
</h2>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
// ❌ AVOID - Inline styles
|
|
90
|
-
<div style={{ padding: '1rem' }}>
|
|
91
|
-
|
|
92
|
-
// ❌ AVOID - CSS modules
|
|
93
|
-
import styles from './product-card.module.css';
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**Why?** Consistent styling approach, better performance, automatic dark mode support via theme variables.
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## 📋 Quick Patterns
|
|
101
|
-
|
|
102
|
-
### Data Fetching
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import { createApiClients } from '@/lib/api-clients';
|
|
106
|
-
|
|
107
|
-
export function loader({ context }: LoaderFunctionArgs): PageData {
|
|
108
|
-
const clients = createApiClients(context);
|
|
109
|
-
return {
|
|
110
|
-
product: clients.shopperProducts.getProduct({...}),
|
|
111
|
-
reviews: clients.shopperProducts.getReviews({...}),
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**See `data-fetching` section for:** loaders, actions, useScapiFetcher, parallel requests, data flow
|
|
117
|
-
|
|
118
|
-
### Authentication
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import { getAuth } from '@/middlewares/auth.server';
|
|
122
|
-
|
|
123
|
-
export function loader({ context }: LoaderFunctionArgs) {
|
|
124
|
-
const auth = getAuth(context);
|
|
125
|
-
return {
|
|
126
|
-
isGuest: auth.userType === 'guest',
|
|
127
|
-
customerId: auth.customer_id
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
**See `auth` section for:** cookie architecture, client usage, token management
|
|
133
|
-
|
|
134
|
-
### Configuration
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
// Components
|
|
138
|
-
import { useConfig } from '@/config';
|
|
139
|
-
const config = useConfig();
|
|
140
|
-
|
|
141
|
-
// Loaders/Actions
|
|
142
|
-
import { getConfig } from '@/config';
|
|
143
|
-
const config = getConfig(context);
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
**See `config` section for:** adding config, environment variables, security
|
|
147
|
-
|
|
148
|
-
### Internationalization
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
// Components
|
|
152
|
-
import { useTranslation } from 'react-i18next';
|
|
153
|
-
const { t } = useTranslation('product');
|
|
154
|
-
|
|
155
|
-
// Loaders/Actions
|
|
156
|
-
import { getTranslation } from '@/lib/i18next';
|
|
157
|
-
const { t } = getTranslation(context);
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
**See `i18n` section for:** validation schemas (factory pattern), language switching, extensions
|
|
161
|
-
|
|
162
|
-
### Components
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
// Suspense boundaries
|
|
166
|
-
import { Suspense } from 'react';
|
|
167
|
-
import { Await } from 'react-router';
|
|
168
|
-
|
|
169
|
-
<Suspense fallback={<ProductSkeleton />}>
|
|
170
|
-
<Await resolve={product}>
|
|
171
|
-
{(data) => <ProductHeader product={data} />}
|
|
172
|
-
</Await>
|
|
173
|
-
</Suspense>
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
**See `components` section for:** createPage HOC, file organization, best practices
|
|
177
|
-
|
|
178
|
-
### Styling
|
|
179
|
-
|
|
180
|
-
```typescript
|
|
181
|
-
// Tailwind utility classes
|
|
182
|
-
<div className="bg-background text-foreground border-border">
|
|
183
|
-
<button className="bg-primary text-primary-foreground rounded-md px-4 py-2">
|
|
184
|
-
Click me
|
|
185
|
-
</button>
|
|
186
|
-
</div>
|
|
187
|
-
|
|
188
|
-
// shadcn/ui: Add via npx shadcn@latest add <component-name>
|
|
189
|
-
import { Button } from '@/components/ui/button';
|
|
190
|
-
import { Card } from '@/components/ui/card';
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
**See `styling` section for:** Tailwind CSS 4 rules, Shadcn/ui components, dark mode, responsive design
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
## 🔍 Get Detailed Guidelines
|
|
198
|
-
|
|
199
|
-
Use the `sfnext_get_guidelines` MCP tool with specific sections:
|
|
200
|
-
|
|
201
|
-
```json
|
|
202
|
-
{
|
|
203
|
-
"sections": ["data-fetching", "components", "testing"]
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
**Available sections:**
|
|
208
|
-
- `data-fetching` - Loaders, actions, useScapiFetcher, data flow
|
|
209
|
-
- `components` - createPage HOC, Suspense, file organization
|
|
210
|
-
- `styling` - Tailwind CSS 4, Shadcn/ui, styling guidelines
|
|
211
|
-
- `testing` - Vitest, Storybook, coverage requirements
|
|
212
|
-
- `auth` - Authentication and session management
|
|
213
|
-
- `config` - Configuration system
|
|
214
|
-
- `i18n` - Internationalization patterns
|
|
215
|
-
- `state-management` - Client-side state with Zustand
|
|
216
|
-
- `page-designer` - Page Designer integration
|
|
217
|
-
- `performance` - Optimization techniques
|
|
218
|
-
- `extensions` - Extension development
|
|
219
|
-
- `pitfalls` - Common mistakes to avoid
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
**When in doubt:**
|
|
224
|
-
1. Check existing code for similar examples
|
|
225
|
-
2. Use the MCP tool to get detailed section guidance
|
|
226
|
-
3. Follow architectural principles: server-only, streaming, TypeScript
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Client-Side State Management
|
|
2
|
-
|
|
3
|
-
## Zustand Store Pattern
|
|
4
|
-
|
|
5
|
-
Storefront Next uses Zustand for client-side state (basket, wishlist):
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// src/middlewares/basket.client.ts
|
|
9
|
-
import {create} from 'zustand';
|
|
10
|
-
|
|
11
|
-
interface BasketStore {
|
|
12
|
-
basket: Basket | null;
|
|
13
|
-
setBasket: (basket: Basket | null) => void;
|
|
14
|
-
clearBasket: () => void;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const useBasketStore = create<BasketStore>((set) => ({
|
|
18
|
-
basket: null,
|
|
19
|
-
setBasket: (basket) => set({basket}),
|
|
20
|
-
clearBasket: () => set({basket: null}),
|
|
21
|
-
}));
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Context Integration
|
|
25
|
-
|
|
26
|
-
Access Zustand state via context helpers:
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
import { getBasket, updateBasket } from '@/middlewares/basket.client';
|
|
30
|
-
|
|
31
|
-
// In clientLoader
|
|
32
|
-
export const clientLoader: ClientLoaderFunction = ({ context }) => {
|
|
33
|
-
const basket = getBasket(context);
|
|
34
|
-
return { basket, itemCount: basket?.productItems?.length ?? 0 };
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// In components
|
|
38
|
-
function CartIcon() {
|
|
39
|
-
const basket = getBasket(context);
|
|
40
|
-
return <Badge count={basket?.productItems?.length ?? 0} />;
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Update Pattern
|
|
45
|
-
|
|
46
|
-
After mutations, update the store:
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
export async function clientAction({request, context}: ActionFunctionArgs) {
|
|
50
|
-
const formData = await request.formData();
|
|
51
|
-
const productId = formData.get('productId') as string;
|
|
52
|
-
|
|
53
|
-
const basket = getBasket(context);
|
|
54
|
-
const clients = createApiClients(context);
|
|
55
|
-
|
|
56
|
-
const {data: updatedBasket} = await clients.shopperBasketsV2.addItemToBasket({
|
|
57
|
-
params: {path: {basketId: basket.basketId}},
|
|
58
|
-
body: [{productId, quantity: 1}],
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// Update Zustand store
|
|
62
|
-
updateBasket(context, updatedBasket);
|
|
63
|
-
|
|
64
|
-
return Response.json({success: true, basket: updatedBasket});
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Best Practices
|
|
69
|
-
|
|
70
|
-
1. **Use for ephemeral client state**: Shopping cart, UI state, temporary selections
|
|
71
|
-
2. **Don't duplicate server state**: Prefer React Router loaders for server data
|
|
72
|
-
3. **Keep stores focused**: Separate stores for basket, wishlist, etc.
|
|
73
|
-
4. **Sync with server**: Update store after successful mutations
|
|
74
|
-
|
|
75
|
-
For full documentation on client-side state management patterns, see the Zustand documentation and React Router state management patterns.
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# Styling Guidelines
|
|
2
|
-
|
|
3
|
-
## Rules
|
|
4
|
-
|
|
5
|
-
- ✅ **Use Tailwind utility classes** in component JSX
|
|
6
|
-
- ✅ **Use `cn()` utility** for conditional classes (`import { cn } from '@/lib/utils'`)
|
|
7
|
-
- ✅ **Follow mobile-first** responsive patterns (`md:`, `lg:` breakpoints)
|
|
8
|
-
- ❌ **NO inline styles** (`style={{...}}`)
|
|
9
|
-
- ❌ **NO CSS modules** (`.module.css` files)
|
|
10
|
-
- ❌ **NO separate CSS files** for component styles
|
|
11
|
-
- ✅ **Custom CSS** only in `src/app.css` for global styles and theme configuration
|
|
12
|
-
|
|
13
|
-
## Shadcn/ui Components
|
|
14
|
-
|
|
15
|
-
**Adding components:**
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx shadcn@latest add <component-name>
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
**Rules:**
|
|
22
|
-
|
|
23
|
-
- ✅ **DO** customize components by editing files in `src/components/ui/`
|
|
24
|
-
- ❌ **DON'T** create custom components inside `src/components/ui/`
|
|
25
|
-
- ❌ **DON'T** manually copy components (use CLI instead)
|
|
26
|
-
|
|
27
|
-
## Dark Mode
|
|
28
|
-
|
|
29
|
-
Dark mode is supported via CSS variables and the `.dark` class. Theme variables automatically adapt:
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
<div className="bg-background text-foreground border-border">
|
|
33
|
-
<button className="bg-primary text-primary-foreground">
|
|
34
|
-
Click me
|
|
35
|
-
</button>
|
|
36
|
-
</div>
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Responsive Design
|
|
40
|
-
|
|
41
|
-
Follow mobile-first responsive design:
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
45
|
-
{/* Content */}
|
|
46
|
-
</div>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
**Reference:** See [README-UI-STYLING.md](docs/README-UI-STYLING.md) in your project for complete UI and styling documentation.
|