create-content-sdk-app 2.0.2 → 2.1.0-canary.2
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/LICENSE.MD +202 -202
- package/dist/templates/nextjs/.cursor/rules/general.mdc +81 -81
- package/dist/templates/nextjs/.cursor/rules/javascript.mdc +112 -112
- package/dist/templates/nextjs/.cursor/rules/project-setup.mdc +100 -100
- package/dist/templates/nextjs/.cursor/rules/sitecore.mdc +150 -150
- package/dist/templates/nextjs/.env.container.example +27 -27
- package/dist/templates/nextjs/.env.remote.example +51 -51
- package/dist/templates/nextjs/.gitattributes +11 -11
- package/dist/templates/nextjs/.prettierrc +8 -8
- package/dist/templates/nextjs/.vscode/extensions.json +8 -8
- package/dist/templates/nextjs/.vscode/launch.json +15 -15
- package/dist/templates/nextjs/.windsurfrules +186 -186
- package/dist/templates/nextjs/LICENSE.txt +202 -202
- package/dist/templates/nextjs/eslint.config.mjs +81 -81
- package/dist/templates/nextjs/gitignore +28 -28
- package/dist/templates/nextjs/package.json +68 -68
- package/dist/templates/nextjs/sitecore.config.ts.example +40 -40
- package/dist/templates/nextjs/src/proxy.ts +11 -3
- package/dist/templates/nextjs/tsconfig.json +40 -40
- package/dist/templates/nextjs-app-router/.cursor/rules/app-router-setup.mdc +116 -116
- package/dist/templates/nextjs-app-router/.cursor/rules/general.mdc +80 -80
- package/dist/templates/nextjs-app-router/.cursor/rules/javascript.mdc +112 -112
- package/dist/templates/nextjs-app-router/.cursor/rules/sitecore.mdc +174 -174
- package/dist/templates/nextjs-app-router/.env.container.example +27 -27
- package/dist/templates/nextjs-app-router/.env.remote.example +51 -51
- package/dist/templates/nextjs-app-router/.gitattributes +11 -11
- package/dist/templates/nextjs-app-router/.windsurfrules +290 -290
- package/dist/templates/nextjs-app-router/eslint.config.mjs +21 -29
- package/dist/templates/nextjs-app-router/gitignore +31 -31
- package/dist/templates/nextjs-app-router/package.json +54 -55
- package/dist/templates/nextjs-app-router/postcss.config.mjs +5 -5
- package/dist/templates/nextjs-app-router/sitecore.config.ts.example +40 -40
- package/dist/templates/nextjs-app-router/src/app/globals.css +1 -1
- package/dist/templates/nextjs-app-router/src/proxy.ts +11 -3
- package/dist/templates/nextjs-app-router/tsconfig.json +48 -48
- package/package.json +2 -2
|
@@ -1,290 +1,290 @@
|
|
|
1
|
-
# Sitecore Content SDK Next.js App Router Project - Windsurf AI Rules
|
|
2
|
-
|
|
3
|
-
## Project Purpose and Tech Stack
|
|
4
|
-
|
|
5
|
-
This is a **Sitecore Content SDK** application built with **Next.js App Router** and **TypeScript**. The project follows Sitecore best practices for XM Cloud development and leverages the latest Next.js App Router features for improved performance and developer experience.
|
|
6
|
-
|
|
7
|
-
### Key Technologies
|
|
8
|
-
|
|
9
|
-
- **Next.js App Router** - React framework with Server Components and modern routing
|
|
10
|
-
- **Sitecore Content SDK** - Official SDK for Sitecore XM Cloud integration
|
|
11
|
-
- **TypeScript** - Type-safe JavaScript development
|
|
12
|
-
- **Sitecore XM Cloud** - Headless CMS platform
|
|
13
|
-
- **React Server Components** - Server-side rendering for better performance
|
|
14
|
-
- **next-intl** - Internationalization support
|
|
15
|
-
|
|
16
|
-
## Coding Standards
|
|
17
|
-
|
|
18
|
-
### TypeScript Standards
|
|
19
|
-
|
|
20
|
-
- Use **strict mode** in tsconfig.json
|
|
21
|
-
- Prefer type assertions over `any`: `value as ContentItem`
|
|
22
|
-
- Use discriminated unions for complex state management
|
|
23
|
-
- Enable strict null checks and strict function types
|
|
24
|
-
|
|
25
|
-
### Naming Conventions
|
|
26
|
-
|
|
27
|
-
- **Variables/Functions**: camelCase (`getUserData()`, `isLoading`, `currentUser`)
|
|
28
|
-
- **Components**: PascalCase (`SitecoreComponent`, `PageLayout`, `ContentBlock`)
|
|
29
|
-
- **Constants**: UPPER_SNAKE_CASE (`API_ENDPOINT`, `DEFAULT_TIMEOUT`)
|
|
30
|
-
- **Directories**: kebab-case (`src/components`, `src/api-clients`)
|
|
31
|
-
- **Types/Interfaces**: PascalCase (`ContentItem`, `LayoutProps`, `SitecoreConfig`)
|
|
32
|
-
|
|
33
|
-
### Modular Layout (App Router)
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
src/
|
|
37
|
-
app/ # App Router pages and layouts
|
|
38
|
-
components/ # UI components (React)
|
|
39
|
-
lib/ # Configuration and utilities
|
|
40
|
-
i18n/ # Internationalization setup
|
|
41
|
-
types/ # TypeScript type definitions
|
|
42
|
-
hooks/ # Custom React hooks
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Library Usage
|
|
46
|
-
|
|
47
|
-
### @sitecore-content-sdk
|
|
48
|
-
|
|
49
|
-
- Use `SitecoreClient` for content fetching
|
|
50
|
-
- Implement proper error handling with try/catch blocks
|
|
51
|
-
- Cache API responses using React Query or SWR
|
|
52
|
-
- Handle content preview vs. published content scenarios
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
import { SitecoreClient } from '@sitecore-content-sdk/nextjs/client';
|
|
56
|
-
import scConfig from 'sitecore.config';
|
|
57
|
-
|
|
58
|
-
const client = new SitecoreClient({
|
|
59
|
-
...scConfig,
|
|
60
|
-
});
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### React App Router Patterns
|
|
64
|
-
|
|
65
|
-
- Use **Server Components** for data fetching and static content (default)
|
|
66
|
-
- Use **Client Components** for interactivity (use 'use client' directive)
|
|
67
|
-
- Implement proper error boundaries with error.tsx
|
|
68
|
-
- Use loading.tsx for loading states
|
|
69
|
-
- Leverage layout.tsx for shared page structure
|
|
70
|
-
|
|
71
|
-
### Sitecore Field Components
|
|
72
|
-
|
|
73
|
-
- Always use Sitecore field components: `<Text>`, `<RichText>`, `<Image>`
|
|
74
|
-
- Validate field existence before rendering
|
|
75
|
-
- Handle empty/null fields gracefully
|
|
76
|
-
- Prefer Sitecore field components over manual rendering
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
// Good: Using Sitecore field components
|
|
80
|
-
<Text field={fields?.title} tag="h1" />
|
|
81
|
-
<RichText field={fields?.content} />
|
|
82
|
-
<Image field={fields?.backgroundImage} />
|
|
83
|
-
|
|
84
|
-
// Avoid: Manual field value extraction unless necessary
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## Example Patterns and Prompts
|
|
88
|
-
|
|
89
|
-
### Server Component Development
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
// Server Component example (default in App Router)
|
|
93
|
-
import { SitecoreClient } from '@sitecore-content-sdk/nextjs/client';
|
|
94
|
-
import scConfig from 'sitecore.config';
|
|
95
|
-
|
|
96
|
-
const client = new SitecoreClient({
|
|
97
|
-
...scConfig,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
export default async function SitecorePage({ params }: { params: { path: string[] } }) {
|
|
101
|
-
try {
|
|
102
|
-
const pageData = await client.getPage(params.path.join('/'));
|
|
103
|
-
return <SitecoreLayout layoutData={pageData?.layout} />;
|
|
104
|
-
} catch (error) {
|
|
105
|
-
return <div>Content not found</div>;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Client Component Integration
|
|
111
|
-
|
|
112
|
-
Interactive Sitecore Components:
|
|
113
|
-
|
|
114
|
-
- Use 'use client' directive when needed
|
|
115
|
-
- Keep client components focused on interactivity
|
|
116
|
-
- Pass server-fetched data as props
|
|
117
|
-
- Handle hydration mismatches carefully
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
'use client';
|
|
121
|
-
|
|
122
|
-
interface InteractiveSitecoreComponentProps {
|
|
123
|
-
fields: {
|
|
124
|
-
title: Field;
|
|
125
|
-
content: Field;
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export default function InteractiveSitecoreComponent({
|
|
130
|
-
fields,
|
|
131
|
-
}: InteractiveSitecoreComponentProps) {
|
|
132
|
-
// Client-side interactivity here
|
|
133
|
-
return (
|
|
134
|
-
<div>
|
|
135
|
-
<Text field={fields?.title} tag="h2" />
|
|
136
|
-
<RichText field={fields?.content} />
|
|
137
|
-
</div>
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Component Development
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
// Component props interface
|
|
146
|
-
interface HeroProps {
|
|
147
|
-
fields: {
|
|
148
|
-
title: Field;
|
|
149
|
-
subtitle: Field;
|
|
150
|
-
backgroundImage: Field;
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export default function Hero({ fields }: HeroProps) {
|
|
155
|
-
return (
|
|
156
|
-
<div>
|
|
157
|
-
<Text field={fields?.title} tag="h1" />
|
|
158
|
-
<Text field={fields?.subtitle} tag="p" />
|
|
159
|
-
<Image field={fields?.backgroundImage} />
|
|
160
|
-
</div>
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### Error Handling
|
|
166
|
-
|
|
167
|
-
API Calls:
|
|
168
|
-
|
|
169
|
-
- Always wrap in try/catch blocks
|
|
170
|
-
- Throw custom errors with context: `SitecoreFetchError`, `ConfigurationError`
|
|
171
|
-
- Handle edge cases with guard clauses
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
async function fetchPageData(path: string): Promise<Page | null> {
|
|
175
|
-
if (!path) {
|
|
176
|
-
throw new Error('Page path is required');
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
const pageData = await client.getPage(path);
|
|
181
|
-
return pageData;
|
|
182
|
-
} catch (error) {
|
|
183
|
-
throw new SitecoreFetchError(`Failed to fetch page data for ${path}`, error);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Configuration
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
// sitecore.config.ts
|
|
192
|
-
import { defineConfig } from '@sitecore-content-sdk/nextjs/config';
|
|
193
|
-
|
|
194
|
-
export default defineConfig({
|
|
195
|
-
api: {
|
|
196
|
-
edge: {
|
|
197
|
-
contextId: process.env.SITECORE_EDGE_CONTEXT_ID || '',
|
|
198
|
-
clientContextId: process.env.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID,
|
|
199
|
-
edgeUrl:
|
|
200
|
-
process.env.NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME ||
|
|
201
|
-
process.env.SITECORE_EDGE_PLATFORM_HOSTNAME ||
|
|
202
|
-
'https://edge-platform.sitecorecloud.io',
|
|
203
|
-
},
|
|
204
|
-
local: {
|
|
205
|
-
apiKey: process.env.SITECORE_API_KEY || '',
|
|
206
|
-
apiHost: process.env.SITECORE_API_HOST || '',
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
defaultSite: process.env.NEXT_PUBLIC_DEFAULT_SITE_NAME || 'default',
|
|
210
|
-
defaultLanguage: process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE || 'en',
|
|
211
|
-
editingSecret: process.env.SITECORE_EDITING_SECRET,
|
|
212
|
-
});
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Internationalization
|
|
216
|
-
|
|
217
|
-
Multi-language Support:
|
|
218
|
-
|
|
219
|
-
- Configure next-intl for language routing
|
|
220
|
-
- Handle Sitecore language contexts
|
|
221
|
-
- Implement language switching
|
|
222
|
-
- Use proper locale-based data fetching
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// Language-aware data fetching
|
|
226
|
-
import { getTranslations } from 'next-intl/server';
|
|
227
|
-
|
|
228
|
-
export default async function LocalizedPage() {
|
|
229
|
-
const t = await getTranslations('common');
|
|
230
|
-
// Fetch Sitecore content for current locale
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
## Development Workflow
|
|
235
|
-
|
|
236
|
-
1. **Install dependencies**: `npm install`
|
|
237
|
-
2. **Configure environment**: Copy `.env.example` to `.env.local`
|
|
238
|
-
3. **Start development**: `npm run dev`
|
|
239
|
-
4. **Build for production**: `npm run build`
|
|
240
|
-
|
|
241
|
-
## App Router Best Practices
|
|
242
|
-
|
|
243
|
-
### Server vs Client Components
|
|
244
|
-
|
|
245
|
-
- Use Server Components for Sitecore content rendering (default)
|
|
246
|
-
- Use Client Components for user interactions
|
|
247
|
-
- Minimize client-side JavaScript
|
|
248
|
-
- Leverage server-side data fetching
|
|
249
|
-
|
|
250
|
-
### Routing and Layouts
|
|
251
|
-
|
|
252
|
-
- Use layout.tsx for shared page structure
|
|
253
|
-
- Implement loading.tsx for loading states
|
|
254
|
-
- Create error.tsx for error boundaries
|
|
255
|
-
- Use page.tsx for route content
|
|
256
|
-
- Use [...path] for Sitecore catch-all routes
|
|
257
|
-
|
|
258
|
-
### Performance Optimization
|
|
259
|
-
|
|
260
|
-
- Leverage Server Components for better performance
|
|
261
|
-
- Use streaming for improved loading experience
|
|
262
|
-
- Implement proper caching strategies
|
|
263
|
-
- Optimize images with Next.js Image component
|
|
264
|
-
|
|
265
|
-
## Best Practices
|
|
266
|
-
|
|
267
|
-
### Performance
|
|
268
|
-
|
|
269
|
-
- Optimize images using Next.js Image component
|
|
270
|
-
- Implement proper loading states
|
|
271
|
-
- Cache expensive operations appropriately
|
|
272
|
-
- Consider server-side rendering implications
|
|
273
|
-
- Lazy-load non-critical modules
|
|
274
|
-
- Use Server Components for better performance
|
|
275
|
-
|
|
276
|
-
### Security
|
|
277
|
-
|
|
278
|
-
- Sanitize user inputs before processing
|
|
279
|
-
- Validate data at application boundaries
|
|
280
|
-
- Use HTTPS for all Sitecore connections
|
|
281
|
-
- Never expose sensitive configuration in client-side code
|
|
282
|
-
- Escape content when rendering to prevent XSS
|
|
283
|
-
|
|
284
|
-
### Code Quality
|
|
285
|
-
|
|
286
|
-
- Follow DRY principle - extract common functionality
|
|
287
|
-
- Use SOLID principles for maintainable code
|
|
288
|
-
- Write self-documenting code with clear intent
|
|
289
|
-
- Implement proper error boundaries
|
|
290
|
-
- Test behavior, not implementation details
|
|
1
|
+
# Sitecore Content SDK Next.js App Router Project - Windsurf AI Rules
|
|
2
|
+
|
|
3
|
+
## Project Purpose and Tech Stack
|
|
4
|
+
|
|
5
|
+
This is a **Sitecore Content SDK** application built with **Next.js App Router** and **TypeScript**. The project follows Sitecore best practices for XM Cloud development and leverages the latest Next.js App Router features for improved performance and developer experience.
|
|
6
|
+
|
|
7
|
+
### Key Technologies
|
|
8
|
+
|
|
9
|
+
- **Next.js App Router** - React framework with Server Components and modern routing
|
|
10
|
+
- **Sitecore Content SDK** - Official SDK for Sitecore XM Cloud integration
|
|
11
|
+
- **TypeScript** - Type-safe JavaScript development
|
|
12
|
+
- **Sitecore XM Cloud** - Headless CMS platform
|
|
13
|
+
- **React Server Components** - Server-side rendering for better performance
|
|
14
|
+
- **next-intl** - Internationalization support
|
|
15
|
+
|
|
16
|
+
## Coding Standards
|
|
17
|
+
|
|
18
|
+
### TypeScript Standards
|
|
19
|
+
|
|
20
|
+
- Use **strict mode** in tsconfig.json
|
|
21
|
+
- Prefer type assertions over `any`: `value as ContentItem`
|
|
22
|
+
- Use discriminated unions for complex state management
|
|
23
|
+
- Enable strict null checks and strict function types
|
|
24
|
+
|
|
25
|
+
### Naming Conventions
|
|
26
|
+
|
|
27
|
+
- **Variables/Functions**: camelCase (`getUserData()`, `isLoading`, `currentUser`)
|
|
28
|
+
- **Components**: PascalCase (`SitecoreComponent`, `PageLayout`, `ContentBlock`)
|
|
29
|
+
- **Constants**: UPPER_SNAKE_CASE (`API_ENDPOINT`, `DEFAULT_TIMEOUT`)
|
|
30
|
+
- **Directories**: kebab-case (`src/components`, `src/api-clients`)
|
|
31
|
+
- **Types/Interfaces**: PascalCase (`ContentItem`, `LayoutProps`, `SitecoreConfig`)
|
|
32
|
+
|
|
33
|
+
### Modular Layout (App Router)
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
src/
|
|
37
|
+
app/ # App Router pages and layouts
|
|
38
|
+
components/ # UI components (React)
|
|
39
|
+
lib/ # Configuration and utilities
|
|
40
|
+
i18n/ # Internationalization setup
|
|
41
|
+
types/ # TypeScript type definitions
|
|
42
|
+
hooks/ # Custom React hooks
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Library Usage
|
|
46
|
+
|
|
47
|
+
### @sitecore-content-sdk
|
|
48
|
+
|
|
49
|
+
- Use `SitecoreClient` for content fetching
|
|
50
|
+
- Implement proper error handling with try/catch blocks
|
|
51
|
+
- Cache API responses using React Query or SWR
|
|
52
|
+
- Handle content preview vs. published content scenarios
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { SitecoreClient } from '@sitecore-content-sdk/nextjs/client';
|
|
56
|
+
import scConfig from 'sitecore.config';
|
|
57
|
+
|
|
58
|
+
const client = new SitecoreClient({
|
|
59
|
+
...scConfig,
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### React App Router Patterns
|
|
64
|
+
|
|
65
|
+
- Use **Server Components** for data fetching and static content (default)
|
|
66
|
+
- Use **Client Components** for interactivity (use 'use client' directive)
|
|
67
|
+
- Implement proper error boundaries with error.tsx
|
|
68
|
+
- Use loading.tsx for loading states
|
|
69
|
+
- Leverage layout.tsx for shared page structure
|
|
70
|
+
|
|
71
|
+
### Sitecore Field Components
|
|
72
|
+
|
|
73
|
+
- Always use Sitecore field components: `<Text>`, `<RichText>`, `<Image>`
|
|
74
|
+
- Validate field existence before rendering
|
|
75
|
+
- Handle empty/null fields gracefully
|
|
76
|
+
- Prefer Sitecore field components over manual rendering
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// Good: Using Sitecore field components
|
|
80
|
+
<Text field={fields?.title} tag="h1" />
|
|
81
|
+
<RichText field={fields?.content} />
|
|
82
|
+
<Image field={fields?.backgroundImage} />
|
|
83
|
+
|
|
84
|
+
// Avoid: Manual field value extraction unless necessary
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Example Patterns and Prompts
|
|
88
|
+
|
|
89
|
+
### Server Component Development
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// Server Component example (default in App Router)
|
|
93
|
+
import { SitecoreClient } from '@sitecore-content-sdk/nextjs/client';
|
|
94
|
+
import scConfig from 'sitecore.config';
|
|
95
|
+
|
|
96
|
+
const client = new SitecoreClient({
|
|
97
|
+
...scConfig,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
export default async function SitecorePage({ params }: { params: { path: string[] } }) {
|
|
101
|
+
try {
|
|
102
|
+
const pageData = await client.getPage(params.path.join('/'));
|
|
103
|
+
return <SitecoreLayout layoutData={pageData?.layout} />;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return <div>Content not found</div>;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Client Component Integration
|
|
111
|
+
|
|
112
|
+
Interactive Sitecore Components:
|
|
113
|
+
|
|
114
|
+
- Use 'use client' directive when needed
|
|
115
|
+
- Keep client components focused on interactivity
|
|
116
|
+
- Pass server-fetched data as props
|
|
117
|
+
- Handle hydration mismatches carefully
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
'use client';
|
|
121
|
+
|
|
122
|
+
interface InteractiveSitecoreComponentProps {
|
|
123
|
+
fields: {
|
|
124
|
+
title: Field;
|
|
125
|
+
content: Field;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export default function InteractiveSitecoreComponent({
|
|
130
|
+
fields,
|
|
131
|
+
}: InteractiveSitecoreComponentProps) {
|
|
132
|
+
// Client-side interactivity here
|
|
133
|
+
return (
|
|
134
|
+
<div>
|
|
135
|
+
<Text field={fields?.title} tag="h2" />
|
|
136
|
+
<RichText field={fields?.content} />
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Component Development
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Component props interface
|
|
146
|
+
interface HeroProps {
|
|
147
|
+
fields: {
|
|
148
|
+
title: Field;
|
|
149
|
+
subtitle: Field;
|
|
150
|
+
backgroundImage: Field;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default function Hero({ fields }: HeroProps) {
|
|
155
|
+
return (
|
|
156
|
+
<div>
|
|
157
|
+
<Text field={fields?.title} tag="h1" />
|
|
158
|
+
<Text field={fields?.subtitle} tag="p" />
|
|
159
|
+
<Image field={fields?.backgroundImage} />
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Error Handling
|
|
166
|
+
|
|
167
|
+
API Calls:
|
|
168
|
+
|
|
169
|
+
- Always wrap in try/catch blocks
|
|
170
|
+
- Throw custom errors with context: `SitecoreFetchError`, `ConfigurationError`
|
|
171
|
+
- Handle edge cases with guard clauses
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
async function fetchPageData(path: string): Promise<Page | null> {
|
|
175
|
+
if (!path) {
|
|
176
|
+
throw new Error('Page path is required');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const pageData = await client.getPage(path);
|
|
181
|
+
return pageData;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
throw new SitecoreFetchError(`Failed to fetch page data for ${path}`, error);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Configuration
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
// sitecore.config.ts
|
|
192
|
+
import { defineConfig } from '@sitecore-content-sdk/nextjs/config';
|
|
193
|
+
|
|
194
|
+
export default defineConfig({
|
|
195
|
+
api: {
|
|
196
|
+
edge: {
|
|
197
|
+
contextId: process.env.SITECORE_EDGE_CONTEXT_ID || '',
|
|
198
|
+
clientContextId: process.env.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID,
|
|
199
|
+
edgeUrl:
|
|
200
|
+
process.env.NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME ||
|
|
201
|
+
process.env.SITECORE_EDGE_PLATFORM_HOSTNAME ||
|
|
202
|
+
'https://edge-platform.sitecorecloud.io',
|
|
203
|
+
},
|
|
204
|
+
local: {
|
|
205
|
+
apiKey: process.env.SITECORE_API_KEY || '',
|
|
206
|
+
apiHost: process.env.SITECORE_API_HOST || '',
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
defaultSite: process.env.NEXT_PUBLIC_DEFAULT_SITE_NAME || 'default',
|
|
210
|
+
defaultLanguage: process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE || 'en',
|
|
211
|
+
editingSecret: process.env.SITECORE_EDITING_SECRET,
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Internationalization
|
|
216
|
+
|
|
217
|
+
Multi-language Support:
|
|
218
|
+
|
|
219
|
+
- Configure next-intl for language routing
|
|
220
|
+
- Handle Sitecore language contexts
|
|
221
|
+
- Implement language switching
|
|
222
|
+
- Use proper locale-based data fetching
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// Language-aware data fetching
|
|
226
|
+
import { getTranslations } from 'next-intl/server';
|
|
227
|
+
|
|
228
|
+
export default async function LocalizedPage() {
|
|
229
|
+
const t = await getTranslations('common');
|
|
230
|
+
// Fetch Sitecore content for current locale
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Development Workflow
|
|
235
|
+
|
|
236
|
+
1. **Install dependencies**: `npm install`
|
|
237
|
+
2. **Configure environment**: Copy `.env.example` to `.env.local`
|
|
238
|
+
3. **Start development**: `npm run dev`
|
|
239
|
+
4. **Build for production**: `npm run build`
|
|
240
|
+
|
|
241
|
+
## App Router Best Practices
|
|
242
|
+
|
|
243
|
+
### Server vs Client Components
|
|
244
|
+
|
|
245
|
+
- Use Server Components for Sitecore content rendering (default)
|
|
246
|
+
- Use Client Components for user interactions
|
|
247
|
+
- Minimize client-side JavaScript
|
|
248
|
+
- Leverage server-side data fetching
|
|
249
|
+
|
|
250
|
+
### Routing and Layouts
|
|
251
|
+
|
|
252
|
+
- Use layout.tsx for shared page structure
|
|
253
|
+
- Implement loading.tsx for loading states
|
|
254
|
+
- Create error.tsx for error boundaries
|
|
255
|
+
- Use page.tsx for route content
|
|
256
|
+
- Use [...path] for Sitecore catch-all routes
|
|
257
|
+
|
|
258
|
+
### Performance Optimization
|
|
259
|
+
|
|
260
|
+
- Leverage Server Components for better performance
|
|
261
|
+
- Use streaming for improved loading experience
|
|
262
|
+
- Implement proper caching strategies
|
|
263
|
+
- Optimize images with Next.js Image component
|
|
264
|
+
|
|
265
|
+
## Best Practices
|
|
266
|
+
|
|
267
|
+
### Performance
|
|
268
|
+
|
|
269
|
+
- Optimize images using Next.js Image component
|
|
270
|
+
- Implement proper loading states
|
|
271
|
+
- Cache expensive operations appropriately
|
|
272
|
+
- Consider server-side rendering implications
|
|
273
|
+
- Lazy-load non-critical modules
|
|
274
|
+
- Use Server Components for better performance
|
|
275
|
+
|
|
276
|
+
### Security
|
|
277
|
+
|
|
278
|
+
- Sanitize user inputs before processing
|
|
279
|
+
- Validate data at application boundaries
|
|
280
|
+
- Use HTTPS for all Sitecore connections
|
|
281
|
+
- Never expose sensitive configuration in client-side code
|
|
282
|
+
- Escape content when rendering to prevent XSS
|
|
283
|
+
|
|
284
|
+
### Code Quality
|
|
285
|
+
|
|
286
|
+
- Follow DRY principle - extract common functionality
|
|
287
|
+
- Use SOLID principles for maintainable code
|
|
288
|
+
- Write self-documenting code with clear intent
|
|
289
|
+
- Implement proper error boundaries
|
|
290
|
+
- Test behavior, not implementation details
|
|
@@ -1,29 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"out/**",
|
|
23
|
-
"build/**",
|
|
24
|
-
"next-env.d.ts",
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
export default eslintConfig;
|
|
1
|
+
import { defineConfig, globalIgnores } from "eslint/config";
|
|
2
|
+
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
3
|
+
import nextTs from "eslint-config-next/typescript";
|
|
4
|
+
|
|
5
|
+
export default defineConfig([
|
|
6
|
+
...nextVitals,
|
|
7
|
+
...nextTs,
|
|
8
|
+
{
|
|
9
|
+
rules: {
|
|
10
|
+
// Don't force alt for <Image/> (sourced from Sitecore media)
|
|
11
|
+
"jsx-a11y/alt-text": "off",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
globalIgnores([
|
|
15
|
+
"node_modules/**",
|
|
16
|
+
".next/**",
|
|
17
|
+
"out/**",
|
|
18
|
+
"build/**",
|
|
19
|
+
"next-env.d.ts",
|
|
20
|
+
]),
|
|
21
|
+
]);
|