Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions packages/b2c-dx-mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,13 @@ Storefront Next development tools for building modern storefronts.

| Tool | Description |
|------|-------------|
| `sfnext_development_guidelines` | Get Storefront Next development guidelines and best practices |
| `sfnext_site_theming` | Configure and manage site theming for Storefront Next |
| `sfnext_figma_to_component_workflow` | Convert Figma designs to Storefront Next components |
| `sfnext_generate_component` | Generate a new Storefront Next component |
| `sfnext_map_tokens_to_theme` | Map design tokens to Storefront Next theme configuration |
| `sfnext_design_decorator` | Apply design decorators to Storefront Next components |
| `sfnext_generate_page_designer_metadata` | Generate Page Designer metadata for Storefront Next components |
| `storefront_next_development_guidelines` | Get Storefront Next development guidelines and best practices |
| `storefront_next_site_theming` | Configure and manage site theming for Storefront Next |
| `storefront_next_figma_to_component_workflow` | Convert Figma designs to Storefront Next components |
| `storefront_next_generate_component` | Generate a new Storefront Next component |
| `storefront_next_map_tokens_to_theme` | Map design tokens to Storefront Next theme configuration |
| `storefront_next_design_decorator` | Apply design decorators to Storefront Next components |
| `storefront_next_generate_page_designer_metadata` | Generate Page Designer metadata for Storefront Next components |
| `scapi_discovery` | Discover available SCAPI endpoints and capabilities |
| `scapi_custom_api_discovery` | Discover custom SCAPI API endpoints |
| `mrt_bundle_push` | Build, push bundle (optionally deploy) |
Expand Down Expand Up @@ -296,7 +296,7 @@ npx mcp-inspector --cli node bin/dev.js --toolsets all --allow-non-ga-tools --me
# Call a specific tool
npx mcp-inspector --cli node bin/dev.js --toolsets all --allow-non-ga-tools \
--method tools/call \
--tool-name sfnext_design_decorator
--tool-name storefront_next_design_decorator
```

#### 2. IDE Integration
Expand Down
62 changes: 62 additions & 0 deletions packages/b2c-dx-mcp/content/auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Authentication & Session Management

## Architecture

Split-cookie architecture with server/client contexts:

- **Server middleware** (`auth.server.ts`): Manages SLAS tokens, writes cookies
- **Client middleware** (`auth.client.ts`): Reads cookies, maintains cache
- **React Context** (`AuthProvider`): Provides auth state to components

## Cookie Design

| Cookie Name | Purpose | User Type | Expiry | HttpOnly |
|-------------|---------|-----------|--------|----------|
| `cc-nx-g` | Guest refresh token | Guest | 30 days | No |
| `cc-nx` | Registered refresh token | Registered | 90 days | No |
| `cc-at` | Access token | Both | 30 min | No |
| `usid` | User session ID | Both | Matches refresh | No |
| `customerId` | Customer ID | Registered | Matches refresh | No |

**Key Points**:

- Only ONE refresh token exists (guest OR registered, never both)
- User type derived from which refresh token exists
- Cookies auto-namespaced with `siteId`
- Tokens auto-refresh when expired

## Usage in Loaders/Actions

```typescript
import { getAuth } from '@/middlewares/auth.server';

export function loader({ context }: LoaderFunctionArgs) {
const auth = getAuth(context);

// Access auth properties
const accessToken = auth.access_token;
const customerId = auth.customer_id;
const isGuest = auth.userType === 'guest';
const isRegistered = auth.userType === 'registered';

return { isGuest, customerId };
}
```

## Usage in Components

```typescript
import { useAuth } from '@/providers/auth';

export function MyComponent() {
const auth = useAuth();

if (auth?.userType === 'guest') {
return <LoginPrompt />;
}

return <div>Welcome, customer {auth?.customer_id}</div>;
}
```

**Reference:** See README-AUTH.md for complete authentication documentation.
110 changes: 110 additions & 0 deletions packages/b2c-dx-mcp/content/components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Component Patterns

## Use the `createPage` HOC

The `createPage` higher-order component standardizes page patterns with built-in Suspense and page key handling:

```typescript
import { use } from 'react';
import { createPage } from '@/components/create-page';

// Define your view component
function ProductView({
product,
category
}: {
product: Promise<Product>;
category?: Promise<Category>
}) {
const productData = use(product);
const categoryData = category ? use(category) : null;

return (
<div>
<h1>{productData.name}</h1>
{categoryData && <p>Category: {categoryData.name}</p>}
</div>
);
}

// Create page with fallback
const ProductPage = createPage({
component: ProductView,
fallback: <ProductSkeleton />
});

export default ProductPage;
```

**Benefits:**

- Eliminates repetitive Suspense/Await boilerplate
- Consistent loading states across pages
- Built-in page key management for navigation transitions
- Type-safe with full TypeScript support

## shadcn/ui Components

**RULES**:

- ✅ Add via: `npx shadcn@latest add <component-name>`
- ❌ DO NOT modify `src/components/ui/` directly
- ✅ Create custom components elsewhere

## Suspense Boundaries

Use granular Suspense boundaries for better UX:

```typescript
// ✅ RECOMMENDED - Multiple Suspense boundaries
export default function ProductPage({ loaderData: { product, reviews } }) {
return (
<div>
<Suspense fallback={<ProductHeaderSkeleton />}>
<Await resolve={product}>
{(data) => <ProductHeader product={data} />}
</Await>
</Suspense>

<Suspense fallback={<ReviewsSkeleton />}>
<Await resolve={reviews}>
{(data) => <ProductReviews reviews={data} />}
</Await>
</Suspense>
</div>
);
}

// ⚠️ OK - Single Suspense boundary (less granular)
export default createPage({
component: ProductView,
fallback: <ProductPageSkeleton />
});
```

## File Organization

```
src/components/product-tile/
├── index.tsx # Component
├── index.test.tsx # Tests
└── stories/
├── index.stories.tsx # Storybook stories
└── __snapshots__/ # Storybook snapshots (optional)
└── product-tile-snapshot.tsx.snap

# Skeleton components are separate components
src/components/product-skeleton/
├── index.tsx
├── index.test.tsx
└── stories/
└── index.stories.tsx
```

## Best Practices

1. **Extract view components** - Separate data handling from presentation
2. **Type safety** - Define proper TypeScript interfaces
3. **Consistent fallbacks** - Reusable skeleton components
4. **Colocate tests** - Keep tests next to components
5. **Story coverage** - Create stories for all reusable components
105 changes: 105 additions & 0 deletions packages/b2c-dx-mcp/content/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Configuration Management

## Overview

All configuration in `config.server.ts` with environment variable overrides.

## Adding Configuration

1. **Define type in `src/config/schema.ts`**:

```typescript
export type Config = {
app: {
myFeature: {
enabled: boolean;
maxItems: number;
};
};
};
```

2. **Add defaults in `config.server.ts`**:

```typescript
export default defineConfig({
app: {
myFeature: {
enabled: false,
maxItems: 10,
},
},
});
```

3. **Override via environment variables**:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we mention where to override vars?


```bash
PUBLIC__app__myFeature__enabled=true
PUBLIC__app__myFeature__maxItems=20
```

## Usage Patterns

**In React Components**:

```typescript
import { useConfig } from '@/config';

export function MyComponent() {
const config = useConfig();

if (config.app.myFeature.enabled) {
const maxItems = config.app.myFeature.maxItems;
// Your feature code
}
}
```

**In Loaders/Actions**:

```typescript
import { getConfig } from '@/config';

export function loader({ context }: LoaderFunctionArgs) {
const config = getConfig(context);

if (config.app.myFeature.enabled) {
// Your loader code
}
}
```

## Environment Variable Rules

Use the `PUBLIC__` prefix with double underscores (`__`) to set any config path:

```bash
# Environment variable → Config path
PUBLIC__app__site__locale=en-US → config.app.site.locale
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer used, being replaced by PUBLIC__app__commerce__sites

Copy link
Copy Markdown
Contributor Author

@yhsieh1 yhsieh1 Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! My branch is behind a few commits. I will update it. We will need to have final update and review to match up latest implementation when release.

PUBLIC__app__site__currency=EUR → config.app.site.currency
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

```

Values are automatically parsed (numbers, booleans, JSON arrays/objects).

Rules:
1. **`PUBLIC__` prefix**: Exposed to browser (client-safe values)
2. **No prefix**: Server-only (secrets, never exposed)
3. **`__` separator**: Navigate nested paths (`PUBLIC__app__site__locale`)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

4. **Case-insensitive**: All casings work
5. **Auto-parsing**: Strings, numbers, booleans, JSON
6. **Validation**: Paths must exist in `config.server.ts`

## Security

```bash
# ✅ Safe for client (PUBLIC__ prefix)
PUBLIC__app__commerce__api__clientId=abc123

# ✅ Server-only (no prefix)
COMMERCE_API_SLAS_SECRET=your-secret
```

Read server-only secrets directly from `process.env` - never add to config.

**Reference:** See src/config/README.md for complete configuration documentation.
Loading
Loading