@salesforce/b2c-dx-mcp 2.0.0 → 2.1.0
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 +47 -9
- package/dist/registry.d.ts +3 -4
- package/dist/registry.js +7 -14
- package/dist/services.d.ts +21 -1
- package/dist/services.js +38 -1
- package/dist/tools/adapter.d.ts +19 -2
- package/dist/tools/adapter.js +49 -10
- package/dist/tools/cartridges/index.js +11 -3
- package/dist/tools/diagnostics/config-inspect.js +2 -2
- package/dist/tools/diagnostics/debug-list-sessions.js +1 -0
- package/dist/tools/diagnostics/debug-start-session.js +13 -2
- 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-watch-list.js +1 -0
- package/dist/tools/diagnostics/logs-watch-start.js +6 -1
- 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-start.js +7 -1
- package/dist/tools/diagnostics/session-registry.d.ts +3 -0
- package/dist/tools/diagnostics/session-registry.js +2 -1
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.js +0 -1
- package/dist/tools/mrt/index.js +4 -0
- package/dist/tools/project-context.d.ts +42 -11
- package/dist/tools/project-context.js +48 -15
- package/dist/tools/scapi/metrics-get.js +1 -1
- package/dist/tools/scapi/scapi-custom-api-generate-scaffold.d.ts +4 -0
- package/dist/tools/scapi/scapi-custom-api-generate-scaffold.js +27 -7
- package/dist/tools/scapi/scapi-custom-apis-get-status.js +1 -1
- package/dist/tools/scapi/scapi-schemas-list.js +1 -0
- package/dist/utils/constants.d.ts +2 -13
- package/dist/utils/constants.js +1 -20
- package/oclif.manifest.json +2 -2
- package/package.json +3 -3
- 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,80 +0,0 @@
|
|
|
1
|
-
# Extension Development
|
|
2
|
-
|
|
3
|
-
## Structure
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
src/extensions/my-extension/
|
|
7
|
-
├── plugin-config.json # Plugin configuration
|
|
8
|
-
├── components/ # Extension components
|
|
9
|
-
├── routes/ # Extension routes
|
|
10
|
-
├── locales/ # Extension translations
|
|
11
|
-
└── providers/ # Extension providers
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Plugin Configuration
|
|
15
|
-
|
|
16
|
-
**Insert component into plugin point**:
|
|
17
|
-
|
|
18
|
-
```json
|
|
19
|
-
{
|
|
20
|
-
"components": [
|
|
21
|
-
{
|
|
22
|
-
"pluginId": "header.before.cart",
|
|
23
|
-
"path": "extensions/my-extension/components/badge.tsx",
|
|
24
|
-
"order": 0
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
"contextProviders": [
|
|
28
|
-
{
|
|
29
|
-
"path": "extensions/my-extension/providers/my-provider.tsx",
|
|
30
|
-
"order": 0
|
|
31
|
-
}
|
|
32
|
-
]
|
|
33
|
-
}
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Extension Routes
|
|
37
|
-
|
|
38
|
-
Files in `routes/` auto-register:
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
// src/extensions/my-extension/routes/my-route.tsx
|
|
42
|
-
export function loader() {
|
|
43
|
-
return { message: 'Hello' };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export default function MyRoute() {
|
|
47
|
-
const { message } = useLoaderData();
|
|
48
|
-
return <div>{message}</div>;
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Extension Translations
|
|
53
|
-
|
|
54
|
-
Auto-namespaced as `extPascalCase`:
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
src/extensions/my-extension/locales/
|
|
58
|
-
├── en-US/translations.json
|
|
59
|
-
└── it-IT/translations.json
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
const {t} = useTranslation('extMyExtension');
|
|
64
|
-
t('welcome');
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Integration Markers
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
// Single line
|
|
71
|
-
/** @sfdc-extension-line SFDC_EXT_MY_FEATURE */
|
|
72
|
-
import myFeature from '@extensions/my-feature';
|
|
73
|
-
|
|
74
|
-
// Block
|
|
75
|
-
{/* @sfdc-extension-block-start SFDC_EXT_MY_FEATURE */}
|
|
76
|
-
<Link to="/my-feature">My Feature</Link>
|
|
77
|
-
{/* @sfdc-extension-block-end SFDC_EXT_MY_FEATURE */}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
For full documentation, read: src/extensions/README.md
|
package/content/sfnext/i18n.md
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
# Internationalization (i18n)
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
- **Server instance**: Has access to all translations for all languages
|
|
6
|
-
- **Client instance**: Dynamically imports translations as JavaScript chunks
|
|
7
|
-
- **Dual API**: `useTranslation()` for components, `getTranslation()` for everything else
|
|
8
|
-
|
|
9
|
-
## Adding Translations
|
|
10
|
-
|
|
11
|
-
**In `src/locales/{language}/translations.json`**:
|
|
12
|
-
|
|
13
|
-
```json
|
|
14
|
-
{
|
|
15
|
-
"product": {
|
|
16
|
-
"title": "Product Details",
|
|
17
|
-
"addToCart": "Add to Cart",
|
|
18
|
-
"greeting": "Hello, {{name}}!",
|
|
19
|
-
"itemCount": {
|
|
20
|
-
"zero": "No items",
|
|
21
|
-
"one": "{{count}} item",
|
|
22
|
-
"other": "{{count}} items"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Usage
|
|
29
|
-
|
|
30
|
-
**2. Use in React components:**
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
import { useTranslation } from 'react-i18next';
|
|
34
|
-
|
|
35
|
-
export function ProductCard() {
|
|
36
|
-
const { t } = useTranslation('product');
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div>
|
|
40
|
-
<h1>{t('title')}</h1>
|
|
41
|
-
<button>{t('addToCart')}</button>
|
|
42
|
-
<p>{t('greeting', { name: 'John' })}</p>
|
|
43
|
-
<p>{t('itemCount', { count: 5 })}</p>
|
|
44
|
-
</div>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
**3. Use in non-component code:**
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
import { getTranslation } from '@/lib/i18next';
|
|
53
|
-
|
|
54
|
-
// Client-side or utilities
|
|
55
|
-
const { t } = getTranslation();
|
|
56
|
-
const message = t('product:addToCart');
|
|
57
|
-
|
|
58
|
-
// Server-side (loaders/actions)
|
|
59
|
-
export function loader(args: LoaderFunctionArgs) {
|
|
60
|
-
const { t } = getTranslation(args.context);
|
|
61
|
-
return { title: t('product:title') };
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Validation Schemas with Translations
|
|
66
|
-
|
|
67
|
-
**CRITICAL**: Use factory pattern for Zod schemas to avoid race conditions:
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
// ❌ WRONG - Module-level schema (race condition)
|
|
71
|
-
export const schema = z.object({
|
|
72
|
-
email: z.string().email(t('validation:emailInvalid'))
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// ✅ CORRECT - Factory function
|
|
76
|
-
import type { TFunction } from 'i18next';
|
|
77
|
-
|
|
78
|
-
export const createSchema = (t: TFunction) => {
|
|
79
|
-
return z.object({
|
|
80
|
-
email: z.string().email(t('validation:emailInvalid'))
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// Usage in component
|
|
85
|
-
import { useMemo } from 'react';
|
|
86
|
-
import { useTranslation } from 'react-i18next';
|
|
87
|
-
|
|
88
|
-
function MyForm() {
|
|
89
|
-
const { t } = useTranslation();
|
|
90
|
-
const schema = useMemo(() => createSchema(t), [t]);
|
|
91
|
-
|
|
92
|
-
const form = useForm({ resolver: zodResolver(schema) });
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Language Switching
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
import LocaleSwitcher from '@/components/locale-switcher';
|
|
100
|
-
|
|
101
|
-
export function Footer() {
|
|
102
|
-
return <footer><LocaleSwitcher /></footer>;
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## Extension Translations
|
|
107
|
-
|
|
108
|
-
Extensions use `extPascalCase` namespace:
|
|
109
|
-
|
|
110
|
-
```
|
|
111
|
-
src/extensions/my-extension/locales/
|
|
112
|
-
├── en-US/translations.json
|
|
113
|
-
└── it-IT/translations.json
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
const {t} = useTranslation('extMyExtension');
|
|
118
|
-
t('welcome');
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
**Reference:** See README-I18N.md for complete internationalization documentation.
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# Page Designer Integration
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Page Designer is Commerce Cloud's visual editor in Business Manager: merchants build and edit storefront pages (home, category, etc.) without code. The app gets page structure (regions, components, attributes) from the **Shopper Experience API** and renders it via a **component registry** and `<Region>`.
|
|
6
|
-
|
|
7
|
-
## Concepts
|
|
8
|
-
|
|
9
|
-
| Concept | Role |
|
|
10
|
-
|--------|------|
|
|
11
|
-
| **Page** | Fetched in route loaders via `fetchPageFromLoader(args, { pageId })`. |
|
|
12
|
-
| **Region** | Named area on a page; rendered with `<Region page={...} regionId="..." componentData={...} />`. |
|
|
13
|
-
| **Component** | Content block (hero, grid, carousel, etc.) with a `typeId` and attributes; registered in `@/lib/registry`. |
|
|
14
|
-
| **Registry** | Static registry in `@/lib/static-registry.ts` is **auto-generated** by the staticRegistry Vite plugin — do not edit by hand. |
|
|
15
|
-
|
|
16
|
-
## Which pages use Page Designer
|
|
17
|
-
|
|
18
|
-
Only **content pages** that merchants edit in Business Manager use Page Designer; cart, checkout, account, and auth do not.
|
|
19
|
-
|
|
20
|
-
| Uses Page Designer | Does not |
|
|
21
|
-
|--------------------|----------|
|
|
22
|
-
| Home (`pageId: 'homepage'`), Category/PLP (`plp`), Search (`search`), Product/PDP (`pdp`) | Cart, Checkout, Account, Order confirmation, Auth |
|
|
23
|
-
|
|
24
|
-
To add a new content page: define a page type and ID in Commerce Cloud, then in your route use `fetchPageFromLoader(args, { pageId })` and `collectComponentDataPromises(args, pagePromise)`, and render `<Region>` for each region.
|
|
25
|
-
|
|
26
|
-
## Getting started
|
|
27
|
-
|
|
28
|
-
### Route (new Page Designer page)
|
|
29
|
-
|
|
30
|
-
- **In the loader**: call `fetchPageFromLoader(args, { pageId: '...' })` and `collectComponentDataPromises(args, pagePromise)`; return `page` and `componentData` (keep loaders synchronous; return promises for streaming).
|
|
31
|
-
- **In the layout**: for each region, render `<Region page={loaderData.page} regionId="..." componentData={loaderData.componentData} />` with optional `fallbackElement` and `errorElement` for Suspense/error boundaries.
|
|
32
|
-
- **On the route module**: add `@PageType({ name, description, supportedAspectTypes })` and `@RegionDefinition([{ id, name, description, maxComponents }])` so Business Manager knows the page type and regions. Example routes: home (`_app._index.tsx`), category/PLP (`_app.category.$categoryId.tsx`).
|
|
33
|
-
|
|
34
|
-
### Component (new Page Designer component)
|
|
35
|
-
|
|
36
|
-
- **Add a metadata class** with `@Component('typeId', { name, description })` and `@AttributeDefinition()` (and optionally `@AttributeDefinition({ type: 'image' })`, `type: 'url'`, etc.) for each prop you want editable in Page Designer. Use `@RegionDefinition([...])` if the component has nested regions (e.g. a grid with slots).
|
|
37
|
-
- **Implement the React component** so it accepts those props (and strips Page Designer–only props like `component`, `page`, `componentData`, `designMetadata` before spreading to the DOM). If the component needs server data (e.g. products for a carousel), export a `loader({ componentData, context })` and optionally a `fallback` component; the registry calls the loader during `collectComponentDataPromises` and passes resolved data as the `data` prop.
|
|
38
|
-
- **Use the MCP tool `sfnext_add_page_designer_decorator`** to generate decorators instead of writing them by hand. Example components: `components/hero/index.tsx`, `components/content-card/index.tsx`, `components/product-carousel/index.tsx`.
|
|
39
|
-
|
|
40
|
-
### After changes
|
|
41
|
-
|
|
42
|
-
- **Rebuild the app** so the static registry (`lib/static-registry.ts`) is regenerated by the staticRegistry Vite plugin. Do not edit the static registry by hand.
|
|
43
|
-
|
|
44
|
-
### Design mode
|
|
45
|
-
|
|
46
|
-
- **Edit** and **Preview** mode are detected from the request via `isDesignModeActive(request)` and `isPreviewModeActive(request)` from `@salesforce/storefront-next-runtime/design/mode`. The root layout exposes `pageDesignerMode` in loader data (`'EDIT' | 'PREVIEW' | undefined`) so the tree can adapt (e.g. show outlines, disable interactions) when running inside Page Designer.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
## MCP tools (recommended)
|
|
50
|
-
|
|
51
|
-
Use the **B2C DX MCP server** for Page Designer work instead of hand-writing decorators and metadata. Configure the B2C DX MCP server in your IDE (e.g. in MCP settings) so these tools are available.
|
|
52
|
-
|
|
53
|
-
### 1. `sfnext_add_page_designer_decorator` (STOREFRONTNEXT toolset)
|
|
54
|
-
|
|
55
|
-
Adds Page Designer decorators to an existing React component so it can be used in Business Manager. The tool analyzes the component, picks suitable props, infers types (e.g. `*Url`/`*Link` → url, `*Image` → image, `is*`/`show*` → boolean), and generates `@Component('typeId', { name, description })`, `@AttributeDefinition()` on a metadata class, and optionally `@RegionDefinition([...])` for nested regions. It skips complex or UI-only props (e.g. className, style, callbacks).
|
|
56
|
-
|
|
57
|
-
- **Auto mode** (fast): Ask in your IDE: *"Add Page Designer support to [ComponentName] with autoMode"*. The tool runs in one turn with no prompts.
|
|
58
|
-
- **Interactive mode** (control): Ask *"Add Page Designer support to [ComponentName]"* and answer questions about typeId, which props to expose, types, and optional nested regions.
|
|
59
|
-
|
|
60
|
-
### 2. `cartridge_deploy` (CARTRIDGES toolset)
|
|
61
|
-
|
|
62
|
-
Packages the cartridge, uploads it to Commerce Cloud via WebDAV, and unpacks it on the server. **Run `pnpm generate:cartridge` or `pnpm build` before `cartridge_deploy`.** Requires Commerce Cloud credentials (e.g. `dw.json` or explicit config). Use after generating metadata so the new/updated metadata is available in Business Manager.
|
|
63
|
-
|
|
64
|
-
### Typical workflow
|
|
65
|
-
|
|
66
|
-
1. **`sfnext_add_page_designer_decorator`** — Add decorators to the component (use autoMode for a quick first pass).
|
|
67
|
-
2. **Rebuild** — The static registry is auto-generated at build time by the staticRegistry Vite plugin.
|
|
68
|
-
3. **`cartridge_deploy`** — Deploy to Commerce Cloud so merchants can use the component in Business Manager.
|
|
69
|
-
|
|
70
|
-
## Best Practices
|
|
71
|
-
|
|
72
|
-
1. **Keep loaders synchronous**: Return promises for Page Designer pages to enable streaming
|
|
73
|
-
2. **Use registry for components**: Register all Page Designer components with proper `typeId`
|
|
74
|
-
3. **Handle design mode**: Adapt UI when `pageDesignerMode` is `'EDIT'` or `'PREVIEW'`
|
|
75
|
-
4. **Rebuild after registry changes**: Static registry is generated at build time
|
|
76
|
-
5. **Use MCP tools**: Leverage `sfnext_add_page_designer_decorator` for faster development
|
|
77
|
-
|
|
78
|
-
**Reference:** See README.md for complete Page Designer documentation and MCP tool setup.
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# Performance Optimization
|
|
2
|
-
|
|
3
|
-
## Bundle Size Limits
|
|
4
|
-
|
|
5
|
-
The application enforces strict bundle size limits defined in `package.json` under the `bundlesize` configuration. Refer to `package.json` for the complete list of limits.
|
|
6
|
-
|
|
7
|
-
**Check bundle size:**
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
pnpm bundlesize:test # Verify limits
|
|
11
|
-
pnpm bundlesize:analyze # Analyze composition
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Built-in Metrics
|
|
15
|
-
|
|
16
|
-
Enable in `config.server.ts`:
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
{
|
|
20
|
-
performance: {
|
|
21
|
-
metrics: {
|
|
22
|
-
serverPerformanceMetricsEnabled: true,
|
|
23
|
-
clientPerformanceMetricsEnabled: true,
|
|
24
|
-
serverTimingHeaderEnabled: false // Debug only
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Tracks:
|
|
31
|
-
|
|
32
|
-
- SSR operations and rendering time
|
|
33
|
-
- SCAPI API calls with parallelization
|
|
34
|
-
- Authentication operations
|
|
35
|
-
- Client-side navigations
|
|
36
|
-
|
|
37
|
-
## Best Practices
|
|
38
|
-
|
|
39
|
-
### 1. Parallel Data Fetching
|
|
40
|
-
|
|
41
|
-
**Key principle:** Return all promises simultaneously in loaders to enable parallel requests. Avoid sequential `await` calls.
|
|
42
|
-
|
|
43
|
-
**Reference:** See `data-fetching` section for detailed parallel vs sequential patterns and code examples.
|
|
44
|
-
|
|
45
|
-
### 2. Image Optimization
|
|
46
|
-
|
|
47
|
-
Use the `DynamicImage` component with WebP format:
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
import { DynamicImage } from '@/components/dynamic-image';
|
|
51
|
-
|
|
52
|
-
<DynamicImage
|
|
53
|
-
src={product.image.link}
|
|
54
|
-
alt={product.image.alt}
|
|
55
|
-
width={400}
|
|
56
|
-
height={400}
|
|
57
|
-
format="webp" // Default format
|
|
58
|
-
/>
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### 3. Progressive Streaming
|
|
62
|
-
|
|
63
|
-
**Key principle:** Use synchronous loaders returning promises to enable progressive streaming. Await only critical data, stream the rest.
|
|
64
|
-
|
|
65
|
-
**Reference:** See `data-fetching` section for detailed streaming patterns including mixed strategies (awaited + streamed).
|
|
66
|
-
|
|
67
|
-
### 4. Lighthouse Audits
|
|
68
|
-
|
|
69
|
-
Monitor performance metrics:
|
|
70
|
-
|
|
71
|
-
- Preload critical CSS
|
|
72
|
-
- Use WebP images by default
|
|
73
|
-
- Lazy load below-the-fold content
|
|
74
|
-
- Optimize font loading
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
pnpm lighthouse:ci # Run Lighthouse CI
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**Reference:** See README-PERFORMANCE.md for complete performance optimization documentation.
|
|
@@ -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
|
-
```
|