Skip to content

Commit 41ce193

Browse files
bookernathCopilotmatthewvolkchanceaclark
authored
Create AGENTS.md (#2561)
* Create AGENTS.md Co-Authored-By: Copilot <[email protected]> * Apply suggestion from @matthewvolk Co-authored-by: Matthew Volk <[email protected]> * Apply suggestion from @matthewvolk Co-authored-by: Matthew Volk <[email protected]> * Update AGENTS.md * Apply suggestions from code review Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Matthew Volk <[email protected]> Co-authored-by: Chancellor Clark <[email protected]>
1 parent 8412b5d commit 41ce193

File tree

1 file changed

+280
-0
lines changed

1 file changed

+280
-0
lines changed

core/AGENTS.md

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
# AGENTS.md
2+
3+
## BigCommerce Catalyst Codebase Overview
4+
5+
This document provides guidance for Large Language Models (LLMs) working with the BigCommerce Catalyst codebase, focusing on the **Next.js App Router application** architecture, data fetching patterns, and key design principles.
6+
7+
**Catalyst is built as a Next.js App Router application** with React Server Components, enabling server-side data fetching, automatic code splitting, and optimal performance for e-commerce workloads.
8+
9+
## Repository Structure
10+
11+
The main Next.js application is located in the `/core` directory, which contains the complete e-commerce storefront implementation. Other packages exist outside of `/core` but are not the primary focus for most development work.
12+
13+
## Middleware Architecture
14+
15+
The application uses a composed middleware stack that significantly alters the default Next.js routing behavior. The middleware composition includes authentication, internationalization, analytics, channel handling, and most importantly, custom routing.
16+
17+
### Custom Routing with `with-routes` Middleware
18+
19+
The `with-routes` middleware is the most critical component that overrides Next.js's default path-based routing. Instead of relying on file-based routing, this middleware:
20+
21+
1. **Queries the BigCommerce GraphQL API** to resolve incoming URL paths to specific entity types (products, categories, brands, blog posts, pages).
22+
23+
2. **Rewrites requests** to internal Next.js routes based on the resolved entity type.
24+
25+
3. **Handles redirects** automatically based on BigCommerce's redirect configuration.
26+
27+
This means that URLs like `/my-product-name` can resolve to `/en/product/123` internally, providing flexible URL structure while maintaining SEO-friendly paths.
28+
29+
## Data Fetching and Partial Prerendering (PPR)
30+
31+
### PPR Configuration
32+
33+
The application uses Next.js Partial Prerendering with incremental adoption. This allows static parts of pages to be prerendered while dynamic content streams in.
34+
35+
### Streamable Pattern
36+
37+
The `Streamable<T>` pattern is a core architectural concept that enables efficient data streaming and React Server Component compatibility.
38+
39+
#### What is Streamable?
40+
41+
```typescript
42+
export type Streamable<T> = T | Promise<T>;
43+
```
44+
45+
A `Streamable<T>` represents data that can be either:
46+
- **Immediate**: Already resolved data of type `T`
47+
- **Deferred**: A Promise that will resolve to type `T`
48+
49+
#### Core Streamable API
50+
51+
Located in `core/vibes/soul/lib/streamable.tsx`, the Streamable system provides:
52+
53+
**`Streamable.from()`** - Creates a streamable from a lazy promise factory:
54+
```typescript
55+
const streamableProducts = Streamable.from(async () => {
56+
const customerToken = await getSessionCustomerAccessToken();
57+
const currencyCode = await getPreferredCurrencyCode();
58+
return getProducts(customerToken, currencyCode);
59+
});
60+
```
61+
62+
**`Streamable.all()`** - Combines multiple streamables with automatic caching:
63+
```typescript
64+
const combined = Streamable.all([
65+
streamableProducts,
66+
streamableCategories,
67+
streamableUser
68+
]);
69+
```
70+
71+
**`useStreamable()`** - Hook for consuming streamables in components:
72+
```typescript
73+
function MyComponent({ data }: { data: Streamable<Product[]> }) {
74+
const products = useStreamable(data);
75+
return <div>{products.map(...)}</div>;
76+
}
77+
```
78+
79+
**`<Stream>` Component** - Provides Suspense boundary for streamable data:
80+
```tsx
81+
<Stream value={streamableProducts} fallback={<ProductSkeleton />}>
82+
{(products) => <ProductList products={products} />}
83+
</Stream>
84+
```
85+
86+
#### Streamable Benefits
87+
88+
- **Performance**: Enables concurrent data fetching and streaming
89+
- **Caching**: Automatic promise deduplication and stability
90+
- **Flexibility**: Works with both sync and async data
91+
- **Suspense Integration**: Built-in React Suspense support
92+
- **Composition**: Easy chaining and combination of data sources
93+
94+
### Data Fetching Best Practices
95+
96+
1. **Use React's `cache()` function** for server-side data fetching to memoize function results and prevent repeated fetches or computations **per request** (React will invalidate the cache for all memoized functions for each server request).
97+
98+
2. **Implement proper cache strategies** based on whether user authentication is present.
99+
100+
3. **Leverage Streamable for progressive enhancement** where static content loads immediately and dynamic content streams in.
101+
102+
## GraphQL API Client
103+
104+
### Centralized Client Configuration
105+
106+
All interactions with the BigCommerce Storefront GraphQL API should use the centralized GraphQL client. This client provides:
107+
108+
- Automatic channel ID resolution based on locale
109+
- Proper authentication token handling
110+
- Request/response logging in development
111+
- Error handling with automatic auth redirects
112+
- IP address forwarding for personalization
113+
114+
### Usage Pattern
115+
116+
Always import and use the configured client rather than making direct API calls. The client handles all the necessary headers, authentication, and channel context automatically.
117+
118+
## UI Design System (Vibes)
119+
120+
### Architecture Overview
121+
122+
The `vibes/` directory contains the **highly customizable and styleable UI layer** that is completely separate from data fetching and business logic. This separation enables:
123+
124+
- **Complete visual customization** without touching data logic
125+
- **Theme-based styling** through CSS variables
126+
- **Reusable components** across different page contexts
127+
- **Clear separation of concerns** between data and presentation
128+
129+
### Vibes vs Pages Architecture
130+
131+
**`vibes/` folder**: Contains presentation components that are meant to be highly customizable and styleable to change the UI:
132+
- Accept `Streamable<T>` data as props
133+
- Handle rendering, styling, and user interactions
134+
- Support theming through CSS variables
135+
- No direct data fetching or business logic
136+
137+
**`page.tsx` files**: Where data fetching patterns should live:
138+
- Handle authentication and authorization
139+
- Create `Streamable` data sources
140+
- Transform API responses for vibes components
141+
- Manage routing and server-side logic
142+
143+
### Component Hierarchy
144+
145+
```
146+
vibes/soul/
147+
├── lib/
148+
│ └── streamable.tsx # Streamable utilities
149+
├── primitives/ # Basic UI components
150+
│ ├── button/
151+
│ ├── product-card/
152+
│ └── navigation/
153+
└── sections/ # Complex UI sections
154+
├── product-list/
155+
├── featured-product-carousel/
156+
└── footer/
157+
```
158+
159+
1. **Primitives** (`vibes/soul/primitives/`) - Basic reusable UI components like buttons, cards, forms.
160+
161+
2. **Sections** (`vibes/soul/sections/`) - Page-level components that compose primitives into complete page sections.
162+
163+
3. **Library** (`vibes/soul/lib/`) - Utility functions and patterns like the Streamable implementation.
164+
165+
### Data Flow Pattern
166+
167+
```
168+
page.tsx → Streamable data → Vibes components → User interaction
169+
```
170+
171+
**Example Pattern:**
172+
```typescript
173+
// app/[locale]/(default)/page.tsx - Data fetching
174+
export default async function HomePage({ params }: Props) {
175+
const streamableProducts = Streamable.from(async () => {
176+
const customerToken = await getSessionCustomerAccessToken();
177+
return getProducts(customerToken);
178+
});
179+
180+
return (
181+
<FeaturedProductList
182+
products={streamableProducts} // Pass streamable to vibes
183+
title="Featured Products"
184+
/>
185+
);
186+
}
187+
188+
// vibes/soul/sections/featured-product-list/index.tsx - Presentation
189+
export function FeaturedProductList({
190+
products,
191+
title
192+
}: {
193+
products: Streamable<Product[]>; // Accept streamable
194+
title: string;
195+
}) {
196+
return (
197+
<section>
198+
<h2>{title}</h2>
199+
<Stream value={products} fallback={<ProductSkeleton />}>
200+
{(productList) => (
201+
<div className="grid">
202+
{productList.map(product => <ProductCard key={product.id} product={product} />)}
203+
</div>
204+
)}
205+
</Stream>
206+
</section>
207+
);
208+
}
209+
```
210+
211+
### Import Patterns
212+
213+
Components should be imported from the vibes design system using the `@/vibes/soul/` alias, maintaining clear separation between business logic in `/components` and design system components in `/vibes`.
214+
215+
## App Router Data Fetching Patterns
216+
217+
### Server Components by Default
218+
219+
All pages are React Server Components, enabling:
220+
- Server-side data fetching with zero client JavaScript
221+
- Automatic code splitting and optimization
222+
- SEO-friendly content rendering
223+
- Direct database/API access
224+
225+
### File-based Routing Structure
226+
227+
```
228+
app/[locale]/(default)/
229+
├── page.tsx # Homepage with data fetching
230+
├── layout.tsx # Shared layout components
231+
├── product/[slug]/
232+
│ ├── page.tsx # Product detail page
233+
│ └── page-data.ts # Product data fetching logic
234+
├── (faceted)/category/[slug]/
235+
│ └── page.tsx # Category page
236+
└── cart/
237+
└── page.tsx # Cart page
238+
```
239+
240+
### Data Fetching Example
241+
242+
```typescript
243+
// page.tsx - Server Component with async data fetching
244+
export default async function ProductPage({ params, searchParams }: Props) {
245+
const { slug } = await params;
246+
const customerAccessToken = await getSessionCustomerAccessToken();
247+
248+
// Create streamables for concurrent data loading
249+
const streamableProduct = Streamable.from(async () => {
250+
return getProduct(slug, customerAccessToken);
251+
});
252+
253+
const streamableReviews = Streamable.from(async () => {
254+
const product = await streamableProduct; // Reuses cached promise
255+
return getProductReviews(product.id);
256+
});
257+
258+
return (
259+
<ProductDetail
260+
product={streamableProduct}
261+
reviews={streamableReviews}
262+
/>
263+
);
264+
}
265+
```
266+
267+
## Key Architectural Principles
268+
269+
1. **App Router Architecture**: Built on Next.js App Router with React Server Components for optimal performance
270+
2. **Routing Flexibility**: Unlike typical Next.js applications, URLs are resolved dynamically via GraphQL rather than file structure
271+
3. **Progressive Enhancement**: Static content loads immediately with dynamic content streaming via PPR and Streamable
272+
4. **Vibes Separation**: Complete separation between data fetching (`page.tsx`) and presentation (`vibes/`) concerns
273+
5. **Centralized API Access**: All BigCommerce API interactions go through the configured GraphQL client
274+
6. **Middleware-First**: Critical functionality like routing, auth, and internationalization handled at the middleware layer
275+
276+
## Notes
277+
278+
This codebase differs significantly from typical Next.js applications due to the custom routing middleware and e-commerce-specific patterns. The `with-routes` middleware essentially turns Next.js into a headless CMS router, where content structure is determined by the BigCommerce backend rather than the filesystem. Understanding this fundamental difference is crucial for working effectively with the codebase.
279+
280+
The Streamable pattern and PPR integration provide excellent user experience through progressive loading, but require understanding of React's newer concurrent features like the `use()` hook and Suspense boundaries.

0 commit comments

Comments
 (0)