create-content-sdk-app 2.0.0-canary.9 → 2.0.2-canary.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.
Files changed (24) hide show
  1. package/dist/templates/nextjs/CLAUDE.md +6 -170
  2. package/dist/templates/nextjs/Skills.md +1 -1
  3. package/dist/templates/nextjs/package.json +2 -2
  4. package/dist/templates/nextjs/src/Bootstrap.tsx +20 -13
  5. package/dist/templates/nextjs/src/byoc/index.tsx +1 -1
  6. package/dist/templates/nextjs/src/components/content-sdk/CdpPageView.tsx +1 -1
  7. package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-route-configuration/SKILL.md +2 -2
  8. package/dist/templates/nextjs-app-router/.sitecore/import-map.server.ts +2 -2
  9. package/dist/templates/nextjs-app-router/AGENTS.md +5 -6
  10. package/dist/templates/nextjs-app-router/CLAUDE.md +6 -271
  11. package/dist/templates/nextjs-app-router/README.md +0 -36
  12. package/dist/templates/nextjs-app-router/Skills.md +1 -1
  13. package/dist/templates/nextjs-app-router/package.json +3 -2
  14. package/dist/templates/nextjs-app-router/src/Bootstrap.tsx +20 -12
  15. package/dist/templates/nextjs-app-router/src/app/[site]/[locale]/[[...path]]/layout.tsx +19 -0
  16. package/dist/templates/nextjs-app-router/src/app/[site]/[locale]/[[...path]]/not-found.tsx +3 -28
  17. package/dist/templates/nextjs-app-router/src/app/[site]/[locale]/[[...path]]/page.tsx +6 -21
  18. package/dist/templates/nextjs-app-router/src/app/[site]/layout.tsx +5 -21
  19. package/dist/templates/nextjs-app-router/src/app/not-found.tsx +1 -23
  20. package/dist/templates/nextjs-app-router/src/byoc/index.tsx +1 -1
  21. package/dist/templates/nextjs-app-router/src/components/content-sdk/CdpPageView.tsx +1 -1
  22. package/package.json +2 -2
  23. package/dist/templates/nextjs/LLMs.txt +0 -179
  24. package/dist/templates/nextjs-app-router/LLMs.txt +0 -236
@@ -1,173 +1,9 @@
1
- # Claude Code Agent Guide for Sitecore Content SDK Next.js Project
1
+ # Claude Code Sitecore Content SDK Next.js (Pages Router) App
2
2
 
3
- ## Project Purpose and Tech Stack
3
+ At the start of every session, read these files for full project guidance:
4
4
 
5
- This is a **Sitecore Content SDK** application built with **Next.js** and **TypeScript**. The project follows Sitecore best practices for XM Cloud development and provides a modern, performant web application framework.
5
+ 1. **`AGENTS.md`** Canonical source of truth for this app: overview, commands, application structure, middleware, SitecoreClient, catch-all route, i18n, DO/DON'T, guardrails, boundaries
6
+ 2. **`.cursor/rules/`** — Coding rules for this template: general, javascript, sitecore, project-setup
7
+ 3. **`Skills.md`** and **`.agents/skills/`** — Capability-specific guidance (component registration, data fetching, editing, i18n, etc.) for tools that support the [Agent Skills](https://agentskills.io) standard.
6
8
 
7
- ### Key Technologies
8
- - **Next.js** - React framework with SSR/SSG capabilities
9
- - **Sitecore Content SDK** - Official SDK for Sitecore XM Cloud integration
10
- - **TypeScript** - Type-safe JavaScript development
11
- - **Sitecore XM Cloud** - Headless CMS platform
12
- - **React** - Component-based UI library
13
-
14
- ## Coding Standards
15
-
16
- ### TypeScript Standards
17
- - Use **strict mode** in tsconfig.json
18
- - Prefer type assertions over `any`: `value as ContentItem`
19
- - Use discriminated unions for complex state management
20
- - Enable strict null checks and strict function types
21
-
22
- ### Naming Conventions
23
- - **Variables/Functions**: camelCase (`getUserData()`, `isLoading`, `currentUser`)
24
- - **Components**: PascalCase (`SitecoreComponent`, `PageLayout`, `ContentBlock`)
25
- - **Constants**: UPPER_SNAKE_CASE (`API_ENDPOINT`, `DEFAULT_TIMEOUT`)
26
- - **Directories**: kebab-case (`src/components`, `src/api-clients`)
27
- - **Types/Interfaces**: PascalCase (`ContentItem`, `LayoutProps`, `SitecoreConfig`)
28
-
29
- ### Modular Layout
30
- ```
31
- src/
32
- components/ # UI components (React)
33
- lib/ # Configuration and utilities
34
- pages/ # Next.js pages
35
- assets/ # Static assets and styles
36
- types/ # TypeScript type definitions
37
- hooks/ # Custom React hooks
38
- ```
39
-
40
- ## Library Usage
41
-
42
- ### @sitecore-content-sdk
43
- - Use `SitecoreClient` for content fetching
44
- - Implement proper error handling with try/catch blocks
45
- - Cache API responses using React Query or SWR
46
- - Handle content preview vs. published content scenarios
47
-
48
- ```typescript
49
- import { SitecoreClient } from '@sitecore-content-sdk/nextjs/client';
50
- import scConfig from 'sitecore.config';
51
-
52
- const client = new SitecoreClient({
53
- ...scConfig,
54
- });
55
- ```
56
-
57
- ### React Patterns
58
- - Use **Server Components** for data fetching and static content
59
- - Use **Client Components** for interactivity (use 'use client')
60
- - Implement proper error boundaries
61
- - Use React.memo for expensive components
62
- - Leverage useCallback and useMemo for performance optimization
63
-
64
- ### Sitecore Field Components
65
- - Always use Sitecore field components: `<Text>`, `<RichText>`, `<Image>`
66
- - Validate field existence before rendering
67
- - Handle empty/null fields gracefully
68
- - Prefer Sitecore field components over manual rendering
69
-
70
- ```typescript
71
- // Good: Using Sitecore field components
72
- <Text field={fields?.title} tag="h1" />
73
- <RichText field={fields?.content} />
74
- <Image field={fields?.backgroundImage} />
75
-
76
- // Avoid: Manual field value extraction unless necessary
77
- ```
78
-
79
- ## Example Patterns and Prompts
80
-
81
- ### Component Development
82
- ```typescript
83
- // Component props interface
84
- interface HeroProps {
85
- fields: {
86
- title: Field;
87
- subtitle: Field;
88
- backgroundImage: Field;
89
- };
90
- }
91
-
92
- export default function Hero({ fields }: HeroProps) {
93
- return (
94
- <div>
95
- <Text field={fields?.title} tag="h1" />
96
- <Text field={fields?.subtitle} tag="p" />
97
- <Image field={fields?.backgroundImage} />
98
- </div>
99
- );
100
- }
101
- ```
102
-
103
- ### Error Handling
104
- ```typescript
105
- async function fetchPageData(path: string): Promise<Page | null> {
106
- if (!path) {
107
- throw new Error('Page path is required');
108
- }
109
-
110
- try {
111
- const pageData = await client.getPage(path);
112
- return pageData;
113
- } catch (error) {
114
- throw new SitecoreFetchError(`Failed to fetch page data for ${path}`, error);
115
- }
116
- }
117
- ```
118
-
119
- ### Configuration
120
- ```typescript
121
- // sitecore.config.ts
122
- import { defineConfig } from '@sitecore-content-sdk/nextjs/config';
123
-
124
- export default defineConfig({
125
- api: {
126
- edge: {
127
- contextId: process.env.SITECORE_EDGE_CONTEXT_ID || '',
128
- clientContextId: process.env.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID,
129
- edgeUrl:
130
- process.env.NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME ||
131
- process.env.SITECORE_EDGE_PLATFORM_HOSTNAME ||
132
- 'https://edge-platform.sitecorecloud.io',
133
- },
134
- local: {
135
- apiKey: process.env.SITECORE_API_KEY || '',
136
- apiHost: process.env.SITECORE_API_HOST || '',
137
- },
138
- },
139
- defaultSite: process.env.NEXT_PUBLIC_DEFAULT_SITE_NAME || 'default',
140
- defaultLanguage: process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE || 'en',
141
- editingSecret: process.env.SITECORE_EDITING_SECRET,
142
- });
143
- ```
144
-
145
- ## Development Workflow
146
-
147
- 1. **Install dependencies**: `npm install`
148
- 2. **Configure environment**: Copy `.env.example` to `.env.local`
149
- 3. **Start development**: `npm run dev`
150
- 4. **Build for production**: `npm run build`
151
-
152
- ## Best Practices
153
-
154
- ### Performance
155
- - Optimize images using Next.js Image component
156
- - Implement proper loading states
157
- - Cache expensive operations appropriately
158
- - Consider server-side rendering implications
159
- - Lazy-load non-critical modules
160
-
161
- ### Security
162
- - Sanitize user inputs before processing
163
- - Validate data at application boundaries
164
- - Use HTTPS for all Sitecore connections
165
- - Never expose sensitive configuration in client-side code
166
- - Escape content when rendering to prevent XSS
167
-
168
- ### Code Quality
169
- - Follow DRY principle - extract common functionality
170
- - Use SOLID principles for maintainable code
171
- - Write self-documenting code with clear intent
172
- - Implement proper error boundaries
173
- - Test behavior, not implementation details
9
+ This file applies to **this scaffolded head application only**. For the Content SDK monorepo (packages, CLI, templates source), use that repo's root `AGENTS.md` and `.cursor/rules/`.
@@ -2,7 +2,7 @@
2
2
 
3
3
  This file describes **this application** in terms of **capability-style groupings**: high-level areas that help AI tools and developers map tasks to the right part of the app. This is a Pages Router app with `pages/[[...path]].tsx`, Next.js i18n, and a single component map. For concrete steps and patterns, see [AGENTS.md](AGENTS.md) and the [official Content SDK documentation](https://doc.sitecore.com/xmc/en/developers/content-sdk/sitecore-content-sdk-for-xm-cloud.html).
4
4
 
5
- **Agent Skills:** Each grouping is also available as a skill in [.agents/skills/](.agents/skills/) in the standard [Agent Skills](https://agentskills.io) format (`SKILL.md` per capability). Tools that support this standard can discover and load these skills automatically; the skills are tailored for **Pages Router** (e.g. extractPath, context.locale, getComponentData, single component-map.ts).
5
+ **Agent Skills:** Each grouping is also available as a skill in [.agents/skills/](.agents/skills/) in the standard [Agent Skills](https://agentskills.io) format (`SKILL.md` per capability). Tools that support this standard load skills from `.agents/skills/`; Cursor's built-in skills use `.cursor/skills/` unless it also supports the Agent Skills standard. The skills here are tailored for **Pages Router** (e.g. extractPath, context.locale, getComponentData, single component-map.ts).
6
6
 
7
7
  ---
8
8
 
@@ -22,9 +22,9 @@
22
22
  },
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@sitecore-cloudsdk/core": "^0.5.1",
26
- "@sitecore-cloudsdk/events": "^0.5.1",
27
25
  "@sitecore-content-sdk/nextjs": "<%- version %>",
26
+ "@sitecore-content-sdk/analytics-core": "<%- version %>",
27
+ "@sitecore-content-sdk/events": "<%- version %>",
28
28
  "@sitecore-feaas/clientside": "^0.6.0",
29
29
  "@sitecore/components": "~2.1.0",
30
30
  "next": "^16.1.1",
@@ -1,8 +1,8 @@
1
1
  import { useEffect, JSX } from 'react';
2
- import { CloudSDK } from '@sitecore-cloudsdk/core/browser';
3
- import { SitecorePageProps } from '@sitecore-content-sdk/nextjs';
4
- import '@sitecore-cloudsdk/events/browser';
2
+ import { SitecorePageProps, initContentSdk } from '@sitecore-content-sdk/nextjs';
5
3
  import config from 'sitecore.config';
4
+ import { eventsPlugin } from '@sitecore-content-sdk/events';
5
+ import { analyticsBrowserAdapter, analyticsPlugin } from '@sitecore-content-sdk/analytics-core';
6
6
 
7
7
  /**
8
8
  * The Bootstrap component is the entry point for performing any initialization logic
@@ -26,16 +26,23 @@ const Bootstrap = (props: SitecorePageProps): JSX.Element | null => {
26
26
  console.debug('Browser Events SDK is not initialized in edit and preview modes');
27
27
  } else {
28
28
  if (config.api.edge?.clientContextId) {
29
- CloudSDK({
30
- sitecoreEdgeUrl: config.api.edge.edgeUrl,
31
- sitecoreEdgeContextId: config.api.edge.clientContextId,
32
- siteName: page.siteName || config.defaultSite,
33
- enableBrowserCookie: true,
34
- // Replace with the top level cookie domain of the website that is being integrated e.g ".example.com" and not "www.example.com"
35
- cookieDomain: window.location.hostname.replace(/^www\./, ''),
36
- })
37
- .addEvents()
38
- .initialize();
29
+ initContentSdk({
30
+ config: {
31
+ contextId: config.api.edge.clientContextId,
32
+ edgeUrl: config.api.edge.edgeUrl,
33
+ siteName: page.siteName || config.defaultSite,
34
+ },
35
+ plugins: [
36
+ analyticsPlugin({
37
+ options: {
38
+ enableCookie: true,
39
+ cookieDomain: window.location.hostname.replace(/^www\./, ''),
40
+ },
41
+ adapter: analyticsBrowserAdapter(),
42
+ }),
43
+ eventsPlugin(),
44
+ ],
45
+ });
39
46
  } else {
40
47
  console.error('Client Edge API settings missing from configuration');
41
48
  }
@@ -1,6 +1,6 @@
1
1
  import React, { JSX } from 'react';
2
2
  import * as FEAAS from '@sitecore-feaas/clientside/react';
3
- import * as Events from '@sitecore-cloudsdk/events/browser';
3
+ import * as Events from '@sitecore-content-sdk/events';
4
4
  import { LayoutServicePageState, SitecoreProviderReactContext } from '@sitecore-content-sdk/nextjs';
5
5
  import '@sitecore/components/context';
6
6
  import dynamic from 'next/dynamic';
@@ -1,6 +1,6 @@
1
1
  import { CdpHelper, useSitecore } from '@sitecore-content-sdk/nextjs';
2
2
  import { useEffect, JSX } from 'react';
3
- import { pageView } from '@sitecore-cloudsdk/events/browser';
3
+ import { pageView } from '@sitecore-content-sdk/events';
4
4
  import config from 'sitecore.config';
5
5
 
6
6
  /**
@@ -15,7 +15,7 @@ Single catch-all route and layout hierarchy. Site and locale are **in the path**
15
15
 
16
16
  ## How to perform
17
17
 
18
- - Single Sitecore page: `src/app/[site]/[locale]/[[...path]]/page.tsx`. Use `await params` for `{ site, locale, path? }`; pass to getPage and call `setRequestLocale(\`${site}_${locale}\`)` at the top. Layout: app/layout.tsx → app/[site]/layout.tsx (Bootstrap, draftMode) → page. Not-found: use parseRewriteHeader and getErrorPage in the route's not-found.tsx.
18
+ - Single Sitecore page: `src/app/[site]/[locale]/[[...path]]/page.tsx`. Use `await params` for `{ site, locale, path? }`; pass to getPage and call `setRequestLocale(\`${site}_${locale}\`)` at the top. Layout: app/layout.tsx → app/[site]/layout.tsx (Bootstrap, draftMode) → page. Not-found: use getCachedPageParams and getErrorPage in the route's not-found.tsx.
19
19
 
20
20
  ## Hard Rules
21
21
 
@@ -24,7 +24,7 @@ Single catch-all route and layout hierarchy. Site and locale are **in the path**
24
24
  - **Locale for next-intl:** Call `setRequestLocale(\`${site}_${locale}\`)` at the **top** of the page so next-intl and `src/i18n/request.ts` see the correct locale. Do not omit when adding new page branches.
25
25
  - **Layout hierarchy:** `app/layout.tsx` → `app/[site]/layout.tsx` (Bootstrap with `siteName={site}` and `draftMode()`) → page. Do not put site/locale-specific data fetching in the root layout.
26
26
  - Placeholders are rendered by the layout (e.g. Placeholder component); do not change placeholder names or structure without aligning with Sitecore layout definition.
27
- - **Not-found:** `src/app/[site]/[locale]/[[...path]]/not-found.tsx`. For Sitecore-driven 404 use `parseRewriteHeader(headers())` for site/locale, then `client.getErrorPage(ErrorPage.NotFound, { site, locale })`. Wrap in Suspense if using async logic.
27
+ - **Not-found:** `src/app/[site]/[locale]/[[...path]]/not-found.tsx`. For Sitecore-driven 404 use `getCachedPageParams()` from `@sitecore-content-sdk/nextjs` for site/locale, then `client.getErrorPage(ErrorPage.NotFound, { site, locale })`.
28
28
 
29
29
  ## Stop Conditions
30
30
 
@@ -16,7 +16,7 @@ import { Suspense } from 'react';
16
16
  import React from 'react';
17
17
  import { componentMap } from '.sitecore/component-map';
18
18
  import client from 'src/lib/sitecore-client';
19
- import { pageView } from '@sitecore-cloudsdk/events/browser';
19
+ import { pageView } from '@sitecore-content-sdk/events';
20
20
  import config from 'sitecore.config';
21
21
 
22
22
  const importMapServer = [
@@ -48,7 +48,7 @@ const importMapServer = [
48
48
  exports: [{ name: 'default', value: client }],
49
49
  },
50
50
  {
51
- module: '@sitecore-cloudsdk/events/browser',
51
+ module: '@sitecore-content-sdk/events',
52
52
  exports: [{ name: 'pageView', value: pageView }],
53
53
  },
54
54
  {
@@ -120,15 +120,14 @@ These are the main head-app–specific concepts. Details are in the sections bel
120
120
  - **SSG:** `generateStaticParams` — use `client.getAppRouterStaticParams(sites, routing.locales)` (sites from `.sitecore/sites.json`). Return at least one default param when not generating full paths (e.g. dev or when `generateStaticPaths` is off).
121
121
  - **Metadata:** `generateMetadata` in the same segment can call `client.getPage(path ?? [], { site, locale })` and derive `title` (e.g. from route fields). Next.js will cache as appropriate.
122
122
 
123
- ### Server vs Client components and PPR
123
+ ### Server vs Client components
124
124
 
125
125
  - **Default:** Components are Server Components. Use `'use client'` only for interactivity (e.g. hooks, event handlers).
126
- - **PPR (Partial Prerendering):** Dynamic work (e.g. `draftMode()`, data fetching) is wrapped in `<Suspense>` (e.g. `DynamicPageContent`, `DynamicLayoutContent`, `DynamicNotFoundContent`). Keep the same pattern when adding new dynamic branches so PPR and caching behave correctly.
127
126
  - **draftMode:** Used in layout and page; call `await draftMode()` in Server Components that need to know preview state.
128
127
 
129
128
  ### Not-found and error page
130
129
 
131
- - **Segment not-found:** `src/app/[site]/[locale]/[[...path]]/not-found.tsx`. For Sitecore-driven 404, read site/locale from the rewrite header: `parseRewriteHeader(headers())` from `@sitecore-content-sdk/nextjs/utils`, then `client.getErrorPage(ErrorPage.NotFound, { site, locale })` and render layout if a page is returned. Wrap in `Suspense` if using async logic.
130
+ - **Segment not-found:** `src/app/[site]/[locale]/[[...path]]/not-found.tsx`. Uses `getCachedPageParams()` from `@sitecore-content-sdk/nextjs` for site/locale, then `client.getErrorPage(ErrorPage.NotFound, { site, locale })` and renders layout if a page is returned.
132
131
  - **Root not-found:** `src/app/not-found.tsx` — minimal fallback when no segment handles the route.
133
132
 
134
133
  ### API route handlers
@@ -154,7 +153,7 @@ These are the main head-app–specific concepts. Details are in the sections bel
154
153
 
155
154
  - **Quick checks:** If locale or dictionary is wrong, ensure `setRequestLocale(\`${site}_${locale}\`)` is called at the top of the page and `src/i18n/request.ts` parses `requestLocale` and calls `client.getDictionary`. If not-found doesn't show Sitecore content, use `parseRewriteHeader(headers())` for site/locale. Always `await params` (Next.js 15+).
156
155
  - **Security:** Use only environment variables in `sitecore.config.ts`; never hardcode API keys, editing secret, or host URLs. Do not expose secrets in client-side code or in logs. Validate and sanitize user input at boundaries.
157
- - **Performance:** Keep middleware lightweight; use the proxy `matcher` so it does not run on API routes, `_next`, sitemap, robots, or static assets. Use Server Components and Suspense for dynamic content; add `'use client'` only where interactivity is needed. Use `generateStaticParams` and caching as in the existing page.
156
+ - **Performance:** Keep middleware lightweight; use the proxy `matcher` so it does not run on API routes, `_next`, sitemap, robots, or static assets. Use Server Components for data fetching; add `'use client'` only where interactivity is needed. Use `generateStaticParams` and caching as in the existing page.
158
157
  - **Sitecore patterns:** Use SDK field components (`<Text>`, `<RichText>`, `<Image>`) and validate field existence before render. Register new components in `.sitecore/component-map.ts` and `.sitecore/component-map.client.ts` as appropriate. Use the single Sitecore client in `lib/sitecore-client.ts` for all data fetching.
159
158
  - **Consistency:** Follow the existing patterns in `[site]/[locale]/[[...path]]/page.tsx`, layout hierarchy, `i18n/request.ts` (site_locale), and API route handlers. When adding routes or rewrites, keep the middleware matcher and next-intl config in sync.
160
159
 
@@ -168,7 +167,7 @@ These are the main head-app–specific concepts. Details are in the sections bel
168
167
  | Pass `{ site, locale }` to `client.getPage` and `getDictionary` | Assume site/locale from headers inside page without using params |
169
168
  | Run LocaleProxy before AppRouterMultisiteProxy in middleware | Change proxy order (locale must run first for i18n) |
170
169
  | Call `setRequestLocale(\`${site}_${locale}\`)` in the page for next-intl | Omit setRequestLocale when adding new page branches |
171
- | Use Suspense around async Server Components that use draftMode or fetch | Put async data fetching in client components when SSR is intended |
170
+ | Use Server Components for async data fetching | Put async data fetching in client components when SSR is intended |
172
171
  | Use `parseRewriteHeader(headers())` in not-found for site/locale | Hardcode site/locale in not-found or error pages |
173
172
  | Use createXRouteHandler and `.sitecore/sites.json` for sitemap/robots | Hardcode site list or commit `.env` |
174
173
  | Use Sitecore field components and validate fields | Expose API keys or editing secret in client code |
@@ -179,7 +178,7 @@ These are the main head-app–specific concepts. Details are in the sections bel
179
178
 
180
179
  ## Guardrails for agentic AI
181
180
 
182
- - **Preserve behavior:** Do not change the proxy order (LocaleProxy → AppRouterMultisiteProxy → …), the `[site]/[locale]/[[...path]]` route shape, or the way `setRequestLocale` and `i18n/request.ts` use `{site}_{locale}`. Preserve PPR/Suspense boundaries and draftMode handling.
181
+ - **Preserve behavior:** Do not change the proxy order (LocaleProxy → AppRouterMultisiteProxy → …), the `[site]/[locale]/[[...path]]` route shape, or the way `setRequestLocale` and `i18n/request.ts` use `{site}_{locale}`. Preserve draftMode handling in layout and page.
183
182
  - **Do not expand scope:** Limit edits to the app (app router, components, API routes, i18n, config). Do not modify SDK packages or monorepo tooling unless explicitly asked. Do not change CI, lockfiles, or root config.
184
183
  - **Follow existing patterns:** When adding routes, layouts, or components, mirror the existing structure. Use the same Sitecore client, component maps, and env-based config. Do not introduce a different way to resolve site/locale or a second client without clear need.
185
184
  - **Verify and stay safe:** After edits, the app should build with `npm run build`. Do not commit secrets or `.env`; only document variables in `.env.example`. Do not add npm dependencies without explicit approval. When in doubt, prefer the existing implementation and ask for clarification.
@@ -1,274 +1,9 @@
1
- # Claude Code Agent Guide for Sitecore Content SDK Next.js App Router Project
1
+ # Claude Code Sitecore Content SDK Next.js (App Router) App
2
2
 
3
- ## Project Purpose and Tech Stack
3
+ At the start of every session, read these files for full project guidance:
4
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.
5
+ 1. **`AGENTS.md`** Canonical source of truth for this app: overview, commands, App Router structure, middleware, SitecoreClient, [site]/[locale]/[[...path]], next-intl, DO/DON'T, guardrails, boundaries
6
+ 2. **`.cursor/rules/`** — Coding rules for this template: general, javascript, sitecore, app-router-setup
7
+ 3. **`Skills.md`** and **`.agents/skills/`** — Capability-specific guidance (component registration, data fetching, editing, i18n, etc.) for tools that support the [Agent Skills](https://agentskills.io) standard.
6
8
 
7
- ### Key Technologies
8
- - **Next.js App Router** - React framework with Server Components and modern routing
9
- - **Sitecore Content SDK** - Official SDK for Sitecore XM Cloud integration
10
- - **TypeScript** - Type-safe JavaScript development
11
- - **Sitecore XM Cloud** - Headless CMS platform
12
- - **React Server Components** - Server-side rendering for better performance
13
- - **next-intl** - Internationalization support
14
-
15
- ## Coding Standards
16
-
17
- ### TypeScript Standards
18
- - Use **strict mode** in tsconfig.json
19
- - Prefer type assertions over `any`: `value as ContentItem`
20
- - Use discriminated unions for complex state management
21
- - Enable strict null checks and strict function types
22
-
23
- ### Naming Conventions
24
- - **Variables/Functions**: camelCase (`getUserData()`, `isLoading`, `currentUser`)
25
- - **Components**: PascalCase (`SitecoreComponent`, `PageLayout`, `ContentBlock`)
26
- - **Constants**: UPPER_SNAKE_CASE (`API_ENDPOINT`, `DEFAULT_TIMEOUT`)
27
- - **Directories**: kebab-case (`src/components`, `src/api-clients`)
28
- - **Types/Interfaces**: PascalCase (`ContentItem`, `LayoutProps`, `SitecoreConfig`)
29
-
30
- ### Modular Layout (App Router)
31
- ```
32
- src/
33
- app/ # App Router pages and layouts
34
- components/ # UI components (React)
35
- lib/ # Configuration and utilities
36
- i18n/ # Internationalization setup
37
- types/ # TypeScript type definitions
38
- hooks/ # Custom React hooks
39
- ```
40
-
41
- ## Library Usage
42
-
43
- ### @sitecore-content-sdk
44
- - Use `SitecoreClient` for content fetching
45
- - Implement proper error handling with try/catch blocks
46
- - Cache API responses using React Query or SWR
47
- - Handle content preview vs. published content scenarios
48
-
49
- ```typescript
50
- import { SitecoreClient } from '@sitecore-content-sdk/nextjs/client';
51
- import scConfig from 'sitecore.config';
52
-
53
- const client = new SitecoreClient({
54
- ...scConfig,
55
- });
56
- ```
57
-
58
- ### React App Router Patterns
59
- - Use **Server Components** for data fetching and static content (default)
60
- - Use **Client Components** for interactivity (use 'use client' directive)
61
- - Implement proper error boundaries with error.tsx
62
- - Use loading.tsx for loading states
63
- - Leverage layout.tsx for shared page structure
64
-
65
- ### Sitecore Field Components
66
- - Always use Sitecore field components: `<Text>`, `<RichText>`, `<Image>`
67
- - Validate field existence before rendering
68
- - Handle empty/null fields gracefully
69
- - Prefer Sitecore field components over manual rendering
70
-
71
- ```typescript
72
- // Good: Using Sitecore field components
73
- <Text field={fields?.title} tag="h1" />
74
- <RichText field={fields?.content} />
75
- <Image field={fields?.backgroundImage} />
76
-
77
- // Avoid: Manual field value extraction unless necessary
78
- ```
79
-
80
- ## Example Patterns and Prompts
81
-
82
- ### Server Component Development
83
- ```typescript
84
- // Server Component example (default in App Router)
85
- import { SitecoreClient } from '@sitecore-content-sdk/nextjs/client';
86
- import scConfig from 'sitecore.config';
87
-
88
- const client = new SitecoreClient({
89
- ...scConfig,
90
- });
91
-
92
- export default async function SitecorePage({ params }: { params: { path: string[] } }) {
93
- try {
94
- const pageData = await client.getPage(params.path.join('/'));
95
- return <SitecoreLayout layoutData={pageData?.layout} />;
96
- } catch (error) {
97
- return <div>Content not found</div>;
98
- }
99
- }
100
- ```
101
-
102
- ### Client Component Integration
103
-
104
- Interactive Sitecore Components:
105
-
106
- - Use 'use client' directive when needed
107
- - Keep client components focused on interactivity
108
- - Pass server-fetched data as props
109
- - Handle hydration mismatches carefully
110
-
111
- ```typescript
112
- 'use client';
113
-
114
- interface InteractiveSitecoreComponentProps {
115
- fields: {
116
- title: Field;
117
- content: Field;
118
- };
119
- }
120
-
121
- export default function InteractiveSitecoreComponent({
122
- fields,
123
- }: InteractiveSitecoreComponentProps) {
124
- // Client-side interactivity here
125
- return (
126
- <div>
127
- <Text field={fields?.title} tag="h2" />
128
- <RichText field={fields?.content} />
129
- </div>
130
- );
131
- }
132
- ```
133
-
134
- ### Component Development
135
- ```typescript
136
- // Component props interface
137
- interface HeroProps {
138
- fields: {
139
- title: Field;
140
- subtitle: Field;
141
- backgroundImage: Field;
142
- };
143
- }
144
-
145
- export default function Hero({ fields }: HeroProps) {
146
- return (
147
- <div>
148
- <Text field={fields?.title} tag="h1" />
149
- <Text field={fields?.subtitle} tag="p" />
150
- <Image field={fields?.backgroundImage} />
151
- </div>
152
- );
153
- }
154
- ```
155
-
156
- ### Error Handling
157
-
158
- API Calls:
159
-
160
- - Always wrap in try/catch blocks
161
- - Throw custom errors with context: `SitecoreFetchError`, `ConfigurationError`
162
- - Handle edge cases with guard clauses
163
-
164
- ```typescript
165
- async function fetchPageData(path: string): Promise<Page | null> {
166
- if (!path) {
167
- throw new Error('Page path is required');
168
- }
169
-
170
- try {
171
- const pageData = await client.getPage(path);
172
- return pageData;
173
- } catch (error) {
174
- throw new SitecoreFetchError(`Failed to fetch page data for ${path}`, error);
175
- }
176
- }
177
- ```
178
-
179
- ### Configuration
180
- ```typescript
181
- // sitecore.config.ts
182
- import { defineConfig } from '@sitecore-content-sdk/nextjs/config';
183
-
184
- export default defineConfig({
185
- api: {
186
- edge: {
187
- contextId: process.env.SITECORE_EDGE_CONTEXT_ID || '',
188
- clientContextId: process.env.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID,
189
- edgeUrl:
190
- process.env.NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME ||
191
- process.env.SITECORE_EDGE_PLATFORM_HOSTNAME ||
192
- 'https://edge-platform.sitecorecloud.io',
193
- },
194
- local: {
195
- apiKey: process.env.SITECORE_API_KEY || '',
196
- apiHost: process.env.SITECORE_API_HOST || '',
197
- },
198
- },
199
- defaultSite: process.env.NEXT_PUBLIC_DEFAULT_SITE_NAME || 'default',
200
- defaultLanguage: process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE || 'en',
201
- editingSecret: process.env.SITECORE_EDITING_SECRET,
202
- });
203
- ```
204
-
205
- ### Internationalization
206
-
207
- Multi-language Support:
208
-
209
- - Configure next-intl for language routing
210
- - Handle Sitecore language contexts
211
- - Implement language switching
212
- - Use proper locale-based data fetching
213
-
214
- ```typescript
215
- // Language-aware data fetching
216
- import { getTranslations } from 'next-intl/server';
217
-
218
- export default async function LocalizedPage() {
219
- const t = await getTranslations('common');
220
- // Fetch Sitecore content for current locale
221
- }
222
- ```
223
-
224
- ## Development Workflow
225
-
226
- 1. **Install dependencies**: `npm install`
227
- 2. **Configure environment**: Copy `.env.example` to `.env.local`
228
- 3. **Start development**: `npm run dev`
229
- 4. **Build for production**: `npm run build`
230
-
231
- ## App Router Best Practices
232
-
233
- ### Server vs Client Components
234
- - Use Server Components for Sitecore content rendering (default)
235
- - Use Client Components for user interactions
236
- - Minimize client-side JavaScript
237
- - Leverage server-side data fetching
238
-
239
- ### Routing and Layouts
240
- - Use layout.tsx for shared page structure
241
- - Implement loading.tsx for loading states
242
- - Create error.tsx for error boundaries
243
- - Use page.tsx for route content
244
- - Use [...path] for Sitecore catch-all routes
245
-
246
- ### Performance Optimization
247
- - Leverage Server Components for better performance
248
- - Use streaming for improved loading experience
249
- - Implement proper caching strategies
250
- - Optimize images with Next.js Image component
251
-
252
- ## Best Practices
253
-
254
- ### Performance
255
- - Optimize images using Next.js Image component
256
- - Implement proper loading states
257
- - Cache expensive operations appropriately
258
- - Consider server-side rendering implications
259
- - Lazy-load non-critical modules
260
- - Use Server Components for better performance
261
-
262
- ### Security
263
- - Sanitize user inputs before processing
264
- - Validate data at application boundaries
265
- - Use HTTPS for all Sitecore connections
266
- - Never expose sensitive configuration in client-side code
267
- - Escape content when rendering to prevent XSS
268
-
269
- ### Code Quality
270
- - Follow DRY principle - extract common functionality
271
- - Use SOLID principles for maintainable code
272
- - Write self-documenting code with clear intent
273
- - Implement proper error boundaries
274
- - Test behavior, not implementation details
9
+ This file applies to **this scaffolded head application only**. For the Content SDK monorepo (packages, CLI, templates source), use that repo's root `AGENTS.md` and `.cursor/rules/`.