44
55## 🏗️ Architecture Overview
66
7- This is a ** server-rendered SPA** built on React Server Components with:
8-
7+ ** Server-rendered SPA** built on React Server Components:
98- ** React Router 7** in framework mode
10- - ** Managed Runtime (MRT)** as the data orchestration layer
11- - ** Server-side data fan-out** - All SCAPI requests execute on MRT
12-
13- ### Navigation Pattern
14-
15- ** Initial Page Load (SSR):**
16- 1 . Browser requests URL
17- 2 . MRT server runs ` loader ` function
18- 3 . SCAPI requests execute on server
19- 4 . HTML progressively streamed to browser
20- 5 . React hydrates on client
21-
22- ** Subsequent Navigations (Client-Side Routing + Server Data):**
23- 1 . Browser intercepts navigation (no page reload)
24- 2 . Browser fetches data via XHR/fetch from server
25- 3 . MRT server runs ` loader ` function
26- 4 . SCAPI requests still execute on server
27- 5 . JSON response sent to browser
28- 6 . React updates DOM (no hydration needed)
29-
30- ** Key Point** : Client-side routing does NOT mean client-side data fetching. Loaders still run on the server.
31-
32- ### Key Architectural Decisions
33-
34- 1 . ** Server-Side Data Orchestration** : MRT is not just a proxy - it's a ** data orchestration layer** . All SCAPI requests execute on the server for both initial and subsequent navigations. Parallel/sequential requests are aggregated into single request to MRT and progressively streamed to the client.
9+ - ** Managed Runtime (MRT)** as data orchestration layer
10+ - ** All SCAPI requests execute on MRT server** (both SSR and client-side navigation)
3511
36- 2 . ** React Router Framework Mode** : Enables server-side rendering with data streaming, client-side routing (SPA) with server data fetching, file-based routing, and actions for mutations.
37-
38- 3 . ** Progressive Streaming** : Loaders should be ** synchronous functions that return objects containing promises** , NOT async functions. This enables non-blocking page transitions and streaming SSR.
39-
40- ### Project Structure
41-
42- ``` text
43- src/
44- ├── routes/ # React Router routes with loaders/actions
45- ├── components/ # React components
46- ├── lib/ # Utilities and helpers
47- ├── hooks/ # Custom React hooks
48- ├── middlewares/ # Server/client middleware (auth, i18n)
49- ├── providers/ # React Context providers
50- ├── extensions/ # Modular feature extensions
51- ├── config/ # Configuration system
52- └── locales/ # i18n translations
53- ```
54-
55- ### Route Conventions
56-
57- - ` _app.*.tsx ` : Routes with app layout (header, footer)
58- - ` _empty.*.tsx ` : Routes without layout (auth pages)
59- - ` action.*.tsx ` : Server-only actions (mutations)
60- - ` resource.*.tsx ` : API-like routes returning JSON
12+ ** Key Point** : Client-side routing does NOT mean client-side data fetching. Loaders always run on the server.
6113
6214---
6315
64- ## 🚨 Non-Negotiable Architecture Rules
65-
66- ### 1. Data Loading Architecture
16+ ## 🚨 Non-Negotiable Rules
6717
68- ** Initial Page Load** : Server-Side Rendering (SSR)
69-
70- - Server runs ` loader ` functions on MRT
71- - SCAPI requests execute server-side
72- - HTML progressively streamed to browser
73- - React hydrates on client
74-
75- ** Subsequent Navigations** : Client-Side Routing + Server Data Fetching
76-
77- - Browser handles navigation without page reload (SPA)
78- - ** BUT ` loader ` functions still fetch data from server** (via XHR/fetch)
79- - No full page reload, but data requests remain server-side
18+ ### 1. Server-Only Data Loading
8019
8120✅ ** REQUIRED** : Use server ` loader ` for all SCAPI data fetching
8221
8322``` typescript
84- // ✅ REQUIRED - Server-only data loading
8523export function loader({ context }: LoaderFunctionArgs ): PageData {
8624 const clients = createApiClients (context );
8725 return {
@@ -91,35 +29,34 @@ export function loader({ context }: LoaderFunctionArgs): PageData {
9129}
9230```
9331
94- ** Why?** Keeps SCAPI requests on MRT server for security, performance, and bundle size—even during client-side navigation .
32+ ** Why?** Keeps SCAPI requests on MRT server for security, performance, and bundle size.
9533
96- ### 2. TypeScript-First (JavaScript Blocked )
34+ ### 2. Synchronous Loaders (Not Async )
9735
98- ✅ ** REQUIRED** : Use ` .ts ` and ` .tsx ` file extensions
99- ❌ ** BLOCKED** : ` .js ` , ` .jsx ` , ` .mjs ` , ` .cjs ` files are forbidden by ESLint
100-
101- ### 3. Progressive Streaming with Suspense
102-
103- ✅ ** CRITICAL** : Loaders should be ** synchronous functions that return objects containing promises** , NOT async functions.
36+ ✅ ** CRITICAL** : Loaders must be ** synchronous functions that return promises** , NOT async functions.
10437
10538``` typescript
106- // ✅ CORRECT - Synchronous loader (enables streaming)
39+ // ✅ CORRECT - Enables streaming
10740export function loader({ context }: LoaderFunctionArgs ): PageData {
10841 const clients = createApiClients (context );
10942 return {
11043 product: clients .shopperProducts .getProduct ({... }), // Promise - streams
111- reviews: clients .shopperProducts .getReviews ({... }), // Promise - streams
11244 };
11345}
11446
115- // ❌ AVOID - Async loaders block page transitions
47+ // ❌ AVOID - Blocks page transitions
11648export async function loader({ context }: LoaderFunctionArgs ) {
11749 const product = await clients .shopperProducts .getProduct ({... }); // Blocks!
11850 return { product };
11951}
12052```
12153
122- ** See ` data-fetching ` section for detailed patterns and explanations.**
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
12360
12461### 4. Use createPage() HOC
12562
@@ -136,14 +73,15 @@ const ProductPage = createPage({
13673export default ProductPage ;
13774```
13875
76+ ---
77+
13978## 📋 Quick Patterns
14079
14180### Data Fetching
14281
14382``` typescript
14483import { createApiClients } from ' @/lib/api-clients' ;
14584
146- // ✅ CORRECT - Synchronous loader (enables streaming)
14785export function loader({ context }: LoaderFunctionArgs ): PageData {
14886 const clients = createApiClients (context );
14987 return {
@@ -153,7 +91,7 @@ export function loader({ context }: LoaderFunctionArgs): PageData {
15391}
15492```
15593
156- ** See ` data-fetching ` section for comprehensive patterns , actions, and best practices. **
94+ ** See ` data-fetching ` section for: ** loaders , actions, useScapiFetcher, parallel requests, data flow
15795
15896### Authentication
15997
@@ -162,127 +100,90 @@ import { getAuth } from '@/middlewares/auth.server';
162100
163101export function loader({ context }: LoaderFunctionArgs ) {
164102 const auth = getAuth (context );
165-
166- // Access auth properties
167- const accessToken = auth .access_token ;
168- const customerId = auth .customer_id ;
169- const isGuest = auth .userType === ' guest' ;
170- const isRegistered = auth .userType === ' registered' ;
171-
172- return { isGuest , customerId };
103+ return {
104+ isGuest: auth .userType === ' guest' ,
105+ customerId: auth .customer_id
106+ };
173107}
174108```
175109
110+ ** See ` auth ` section for:** cookie architecture, client usage, token management
111+
176112### Configuration
177113
178114``` typescript
179- // In React components
115+ // Components
180116import { useConfig } from ' @/config' ;
181117const config = useConfig ();
182- const siteName = config .app .site .locale ;
183118
184- // In loaders/actions
119+ // Loaders/Actions
185120import { getConfig } from ' @/config' ;
186- export function loader({ context }: LoaderFunctionArgs ) {
187- const config = getConfig (context );
188- return { maxItems: config .app .myFeature .maxItems };
189- }
121+ const config = getConfig (context );
190122```
191123
124+ ** See ` config ` section for:** adding config, environment variables, security
125+
192126### Internationalization
193127
194128``` typescript
195- // In React components
129+ // Components
196130import { useTranslation } from ' react-i18next' ;
197131const { t } = useTranslation (' product' );
198- <h1 >{t(' title' )}< / h1 >
199132
200- // In loaders/actions
133+ // Loaders/Actions
201134import { getTranslation } from ' @/lib/i18next' ;
202- export function loader(args : LoaderFunctionArgs ) {
203- const { t } = getTranslation (args .context );
204- return { title: t (' product:title' ) };
205- }
206-
207- // ⚠️ CRITICAL: Use factory pattern for validation schemas
208- export const createSchema = (t : TFunction ) => z .object ({
209- email: z .string ().email (t (' validation:emailInvalid' ))
210- });
135+ const { t } = getTranslation (context );
211136```
212137
213- ## 🎯 Component Best Practices
138+ ** See ` i18n ` section for: ** validation schemas (factory pattern), language switching, extensions
214139
215- ### 1. shadcn/ui Components
140+ ### Components
216141
217- - ✅ Add via: ` npx shadcn@latest add <component-name> `
218- - ❌ DO NOT manually modify ` src/components/ui/ ` components
219- - ✅ Create custom components outside this directory
142+ ``` typescript
143+ // shadcn/ui: Add via npx shadcn@latest add <component-name>
144+ // DO NOT modify src/ components/ui/ directly
220145
221- ### 2. Suspense Boundaries
146+ // Suspense boundaries
147+ import { Suspense } from ' react' ;
148+ import { Await } from ' react-router' ;
222149
223- ``` typescript
224- // ✅ RECOMMENDED - Granular boundaries
225150< Suspense fallback = {<ProductSkeleton />}>
226151 < Await resolve = {product }>
227152 {(data ) => <ProductHeader product ={data} />}
228153 < / Await >
229154< / Suspense >
230- < Suspense fallback = {<ReviewsSkeleton />}>
231- < Await resolve = {reviews }>
232- {(data ) => <ProductReviews reviews ={data} />}
233- < / Await >
234- < / Suspense >
235155```
236156
237- ### 3. File Organization
157+ ** See ` components ` section for: ** createPage HOC, file organization, best practices
238158
239- ```
240- src/components/
241- ├── product-card/
242- │ ├── index.tsx # Component
243- │ ├── product-card.test.tsx # Tests
244- │ ├── product-card.stories.tsx # Storybook
245- │ └── skeleton.tsx # Loading state
246- ```
247-
248- ## ⚡ Performance Tips
249-
250- 1 . ** Parallel Data Fetching** : Return all promises simultaneously (don't await)
251- 2 . ** Image Optimization** : Use ` <DynamicImage format="webp" /> `
252- 3 . ** Monitor Metrics** : Enable performance metrics in config
253- 4 . ** Lazy Load** : Use Suspense for below-the-fold content
254-
255- ## 🧪 Testing Requirements
256-
257- - ✅ Unit tests with Vitest (` .test.ts ` / ` .test.tsx ` )
258- - ✅ Storybook stories for all reusable components
259- - ✅ Use viewport toolbar (not separate Mobile/Tablet stories)
260- - ✅ Test accessibility with a11y addon
159+ ---
261160
262- ## 🔍 Get Specific Guidelines
161+ ## 🔍 Get Detailed Guidelines
263162
264- Use the ` storefront_next_development_guidelines ` tool with section parameters for detailed guidance :
163+ Use the ` storefront_next_development_guidelines ` MCP tool with specific sections :
265164
165+ ``` json
166+ {
167+ "sections" : [" data-fetching" , " components" , " testing" ]
168+ }
266169```
267- storefront_next_development_guidelines --sections data-fetching
268- storefront_next_development_guidelines --sections state-management
269- storefront_next_development_guidelines --sections auth
270- storefront_next_development_guidelines --sections i18n
271- storefront_next_development_guidelines --sections page-designer
272- storefront_next_development_guidelines --sections pitfalls
273- ```
274-
275- Combine multiple sections for contextual learning:
276170
277- ```
278- storefront_next_development_guidelines --sections data-fetching --sections components
279- storefront_next_development_guidelines --sections data-fetching --sections state-management
280- ```
171+ ** Available sections:**
172+ - ` data-fetching ` - Loaders, actions, useScapiFetcher, data flow
173+ - ` components ` - createPage HOC, Suspense, file organization
174+ - ` testing ` - Vitest, Storybook, coverage requirements
175+ - ` auth ` - Authentication and session management
176+ - ` config ` - Configuration system
177+ - ` i18n ` - Internationalization patterns
178+ - ` state-management ` - Client-side state with Zustand
179+ - ` page-designer ` - Page Designer integration
180+ - ` performance ` - Optimization techniques
181+ - ` extensions ` - Extension development
182+ - ` pitfalls ` - Common mistakes to avoid
281183
282184---
283185
284- ** Remember** : These are the critical patterns. When in doubt:
285-
186+ ** When in doubt:**
2861871 . Check existing code for similar examples
287- 2 . Read the full documentation for your specific use case
288- 3 . Follow the architectural principles ( server-only, streaming, TypeScript)
188+ 2 . Use the MCP tool to get detailed section guidance
189+ 3 . Follow architectural principles: server-only, streaming, TypeScript
0 commit comments