Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AGENTS.md — AI Guidance for Sitecore Content SDK

> **Claude Code users:** This file does not include detailed coding rules. Read all `.cursor/rules/*.mdc` files at the start of your session for code style, naming conventions, Sitecore patterns, testing, and safety rules.
> **Claude Code users:** Start with this file. Open `.cursor/rules/*.mdc` **when a task touches that area** (e.g. `safety.mdc`, `testing.mdc`) — do not load every rule file by default. See root [`CLAUDE.md`](CLAUDE.md).

## Project Overview

Expand Down
21 changes: 7 additions & 14 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
# Claude Code — Sitecore Content SDK

At the start of every session, read these files for full project guidance:
**Start here:** [`AGENTS.md`](AGENTS.md) — monorepo overview, commands, boundaries, and where to edit.

1. **`AGENTS.md`** — Canonical source of truth: project overview, commands, package structure, boundaries, DO/DON'T rules, example tasks, git workflow
2. **`.cursor/rules/`** — Detailed coding rules (not auto-loaded by Claude Code):
- `code-style.mdc` — Vibe-coding principles, code quality, error handling, imports, lint
- `javascript.mdc` — Naming conventions, code layout, security, performance, JSDoc
- `sitecore.mdc` — XM Cloud integration, component development, content management
- `general.mdc` — DRY, SOLID, architecture patterns, development standards
- `testing.mdc` — Mocha/Sinon/Chai, test commands
- `safety.mdc` — Safety rules for compiled artifacts and secrets
- `cli.mdc` — CLI behavior, init flow, backwards compatibility
- `project-context.mdc` — Project-wide context and constraints
- `repo-structure.mdc` — Repository structure and templates policy
- `agent-tasks.mdc` — Example workflows (add utility, fix test, change template)
3. **`Skills.md`** and **`.agents/skills/`** — For capability-specific guidance (component registration, data fetching, editing, i18n, etc.), when your tool supports the [Agent Skills](https://agentskills.io) standard.
**Add detail only when needed:**

- **Coding rules:** [`.cursor/rules/`](.cursor/rules/) — open the relevant `.mdc` file for the task (e.g. `safety.mdc`, `sitecore.mdc`, `testing.mdc`). Do **not** load every rule file by default.
- **Capabilities:** [`Skills.md`](Skills.md) lists task → skill names. If your tool supports [Agent Skills](https://agentskills.io), read **one** matching skill under `.agents/skills/<name>/SKILL.md` (skills for scaffolded apps live in the Next.js templates under `packages/create-content-sdk-app/src/templates/`).

This repo is the **Content SDK monorepo**. For a **generated head app**, use that app’s `AGENTS.md` (not this file’s folder) as the primary guide.
2 changes: 1 addition & 1 deletion Skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ Capability groupings and Agent Skills are **maintained in the scaffolding templa
| **App Router** | [Skills.md](packages/create-content-sdk-app/src/templates/nextjs-app-router/Skills.md) · [.agents/skills/](packages/create-content-sdk-app/src/templates/nextjs-app-router/.agents/skills/) |
| **Pages Router** | [Skills.md](packages/create-content-sdk-app/src/templates/nextjs/Skills.md) · [.agents/skills/](packages/create-content-sdk-app/src/templates/nextjs/.agents/skills/) |

Each template’s `Skills.md` lists the same capability groupings (component scaffold, registration, data fetching, editing, i18n, etc.) with template-specific details. Each template’s `.agents/skills/` contains one folder per capability with a `SKILL.md` (when-to-use, how to perform, hard rules, stop conditions). Tools that support [Agent Skills](https://agentskills.io) can load skills from the template path when working in a generated app or in the template source.
Each template’s `Skills.md` lists capability groupings (component scaffold, registration, data fetching, editing, i18n, etc.) with template-specific details. Each template’s `.agents/skills/` has one folder per capability with a compact `SKILL.md` that points to that template’s `AGENTS.md` for full detail. Tools that support [Agent Skills](https://agentskills.io) should load **one** skill that matches the task, not the whole tree.

For monorepo-level instructions (commands, structure, DO/DON’T), see [AGENTS.md](AGENTS.md). For official APIs and guides, see the [Content SDK documentation](https://doc.sitecore.com/xmc/en/developers/content-sdk/sitecore-content-sdk-for-xm-cloud.html).
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Key concepts (App Router)

Optional, on-demand detail for this scaffolded head app. The compact guide is [AGENTS.md](../../AGENTS.md); open this file when you need middleware, client, catch-all, locale, and related concepts.

## Key concepts for this app

These are the main head-app–specific concepts. Details are in the sections below.

### Middleware (Edge proxy)

- **Where:** `src/proxy.ts`. Next.js runs middleware from `middleware.ts` at root or in `src/` — if the app only has `proxy.ts`, add `src/middleware.ts` that re-exports it.
- **What it does:** Runs on each request (respecting the `matcher`). Chain order is **fixed:** LocaleProxy → AppRouterMultisiteProxy → RedirectsProxy → PersonalizeProxy. Locale must run first so i18n and multisite see the correct locale.
- **Config:** Uses `sitecore.config.ts` (multisite, redirects, personalize), `.sitecore/sites.json`, and `src/i18n/routing.ts` (locales). **Do not change proxy order.** Keep the matcher excluding API, `_next/`, sitemap, robots, and static assets so the proxy stays lightweight.

### SitecoreClient

- **Where:** Single shared instance in `src/lib/sitecore-client.ts` — `new SitecoreClient({ ...scConfig })` with config from `sitecore.config.ts`.
- **Use for:** `getPage`, `getDictionary`, `getErrorPage`, `getPreview`, `getDesignLibraryData`, `getAppRouterStaticParams`. All Sitecore data fetching in the app goes through this client.
- **Do not:** Create a second client or instantiate SitecoreClient elsewhere. Pass `site` and `locale` from route params (or `parseRewriteHeader` in not-found), not from global state.

### Catch-all route

- **Where:** `src/app/[site]/[locale]/[[...path]]/page.tsx`. This is the **only** page component that renders Sitecore content; the optional `[[...path]]` segment captures the content path.
- **Flow:** `params` is a Promise (Next.js 15+) — `await params` to get `{ site, locale, path? }`. Call `client.getPage(path ?? [], { site, locale })`. For preview, use `draftMode()` and `client.getPreview(editingParams)` or `client.getDesignLibraryData(editingParams)` from `searchParams`. Call `setRequestLocale(\`${site}_${locale}\`)` at the top of the page for next-intl.
- **Do not:** Add another catch-all or page at a different path for Sitecore pages; keep this single entry point.

### How locale works

- **In the URL:** All content routes are `/[site]/[locale]/...path` (e.g. `/default/en`, `/default/en/about`). Middleware (LocaleProxy, then AppRouterMultisiteProxy) rewrites incoming requests into this shape.
- **In the app:** next-intl uses a single `requestLocale` per request. This app encodes both site and locale as `requestLocale = \`${site}_${locale}\``. In the page, call `setRequestLocale(\`${site}_${locale}\`)` so next-intl and `src/i18n/request.ts` see it. In `request.ts`, parse `requestLocale` (e.g. `split('_')`) to get site and locale, then load the dictionary with `client.getDictionary({ locale, site })`.
- **Config:** `src/i18n/routing.ts` defines `locales` and `defaultLocale`; align these with Sitecore languages (e.g. from `sitecore.config.ts`). **Do not** change the `{site}_{locale}` convention without updating request.ts and all pages that call `setRequestLocale`.

### More (component maps, editing, env)

- **Component maps:** `.sitecore/component-map.ts` (Server) and `.sitecore/component-map.client.ts` (Client). Register every Sitecore component here; keep in sync with `src/components/`.
- **Editing/preview:** Use `draftMode()` in Server Components; when enabled, use `client.getPreview(searchParams)` or `client.getDesignLibraryData(searchParams)`. Editing API routes live under `src/app/api/editing/`.
- **Env:** All config via environment variables in `sitecore.config.ts`. Document vars in `.env.example` (or `.env.remote.example` / `.env.container.example`); never commit `.env` or `.env.local`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Project overview (App Router)

Optional, on-demand detail for this scaffolded head app. The compact guide is [AGENTS.md](../../AGENTS.md); open this file when you need scope and orientation beyond that file.

## Project Overview

This is a **Sitecore Content SDK** application built with **Next.js (App Router)** and **TypeScript**. AI agents work as developer assistants within this scaffolded head application. The app integrates with Sitecore XM Cloud for content, uses **file-based routing with `[site]` and `[locale]`**, next-intl for i18n, and Edge middleware for multisite, redirects, and personalization.

**Scope:** This file applies to **this application only** (a scaffolded head app). Here we edit app code and config (app router, components, API routes, i18n); we do not modify SDK packages or CI.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Next.js App Router specifics

Optional, on-demand detail for this scaffolded head app. The compact guide is [AGENTS.md](../../AGENTS.md); open this file for routing, data fetching, API routes, component maps, and layout depth.

## Next.js App Router specifics

### Routing: `[site]` / `[locale]` / `[[...path]]`

- **URL shape:** `/[site]/[locale]/...path` (e.g. `/default/en`, `/default/en/about`). Site and locale are **in the path**; the Edge proxy rewrites incoming requests to this shape.
- **Page component:** `src/app/[site]/[locale]/[[...path]]/page.tsx`. Receives `params: Promise<{ site, locale, path? }>`. Use `await params`; pass `site` and `locale` to `client.getPage(path ?? [], { site, locale })`.
- **Layout hierarchy:** `app/layout.tsx` → `app/[site]/layout.tsx` (per-site; runs Bootstrap with `siteName={site}` and `draftMode()`) → page. Do not put site/locale-specific data fetching in the root layout; use the `[site]` or page layout.

### i18n (next-intl)

- **Config:** `src/i18n/routing.ts` — `defineRouting({ locales, defaultLocale, localePrefix })`. Align `locales` with Sitecore languages; often sourced from `sitecore.config.ts` (e.g. `defaultLanguage`).
- **Request config:** `src/i18n/request.ts` — `getRequestConfig` receives `requestLocale`. The app uses `{site}_{locale}` (e.g. set by `setRequestLocale(\`${site}_${locale}\`)` in the page). Parse with `requested?.split('_')` to get `parsedSite` and `parsedLocale`; load dictionary with `client.getDictionary({ locale, site: parsedSite })` and return `{ locale, messages }`.
- **In pages:** Call `setRequestLocale(\`${site}_${locale}\`)` at the top of the page so next-intl and request config see the correct locale.

### Multisite and Edge middleware (proxy)

- **Site list:** `.sitecore/sites.json` — typically generated by the Sitecore CLI or deployment. Used by middleware and API route handlers. Avoid hand-editing unless you know the format.
- **Edge middleware:** Implemented in **`src/proxy.ts`**. Next.js only runs middleware from a file named `middleware.ts` at root or in `src/`. If this app has only `proxy.ts`, add `src/middleware.ts` that re-exports it (e.g. `export { default } from './proxy';`) so the proxy runs.
- **Proxy chain (order is critical):** `defineProxy(locale, multisite, redirects, personalize).exec(req)`:
- **LocaleProxy** — runs first; uses `sites` and `routing.locales` from `src/i18n/routing.ts`. Required for App Router so locale is set before multisite.
- **AppRouterMultisiteProxy** — rewrites to `/[site]/[locale]/[...path]`; uses `scConfig.multisite`.
- **RedirectsProxy** — redirects; uses `scConfig.redirects`, `scConfig.api.edge`, `scConfig.api.local`.
- **PersonalizeProxy** — personalization; uses `scConfig.personalize`; often disabled in dev.
- **Matcher:** Exclude API routes, `_next/`, sitemap, robots, healthz, Sitecore paths, and static assets so middleware does not run on every static request. The matcher is defined in `config` in `proxy.ts` (or in `middleware.ts` if it re-exports the proxy).
- **Config:** `sitecore.config.ts` → `multisite`, `redirects`, `personalize`; never commit secrets.

### Data fetching and preview

- **Page data:** In the page (or a Server Component), use `client.getPage(path ?? [], { site, locale })`. For preview, use `draftMode()`; if `draft.isEnabled`, use `client.getPreview(editingParams)` or `client.getDesignLibraryData(editingParams)` from `searchParams`; otherwise use `getPage` with `site` and `locale`.
- **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).
- **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.

### Server vs Client components

- **Default:** Components are Server Components. Use `'use client'` only for interactivity (e.g. hooks, event handlers).
- **draftMode:** Used in layout and page; call `await draftMode()` in Server Components that need to know preview state.

### Not-found and error page

- **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.
- **Root not-found:** `src/app/not-found.tsx` — minimal fallback when no segment handles the route.

### API route handlers

- **Sitemap:** `src/app/api/sitemap/route.ts` — `createSitemapRouteHandler({ client, sites })`. Export `{ GET }`; use `sites` from `.sitecore/sites.json`. Set `export const dynamic = 'force-dynamic'` if the handler relies on request.
- **Robots:** `src/app/api/robots/route.ts` — `createRobotsRouteHandler({ client, sites })`. Same pattern.
- **Editing:** `src/app/api/editing/config/route.ts` and `editing/render/route.ts` — use `createEditingConfigRouteHandler` and the appropriate render handler with `components`, `clientComponents` (`.sitecore/component-map.client.ts`), `metadata`, and `client`. Set `dynamic = 'force-dynamic'` where needed.
- **Rewrites:** `next.config.ts` → rewrites for `/sitemap*.xml`, `/robots.txt` with `locale: false` so they are not localized.

### Sitecore client and config

- **Client:** `src/lib/sitecore-client.ts` — `new SitecoreClient({ ...scConfig })`. Use for `getPage`, `getDictionary`, `getErrorPage`, `getPreview`, `getAppRouterStaticParams`, etc.
- **Config:** `sitecore.config.ts` — `defineConfig({ api, defaultSite, defaultLanguage, editingSecret, redirects, multisite, personalize })`. Use env vars only; no hardcoded secrets.

### Component maps and layout

- **Server/client components:** `.sitecore/component-map.ts` (Server); `.sitecore/component-map.client.ts` (Client). Register all Sitecore components; keep in sync with `src/components/`.
- **Layout:** `Layout.tsx` renders page layout and placeholders; `Providers` wrap page and component context; `Bootstrap` in `[site]/layout.tsx` receives `siteName={site}` and preview state.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Example tasks and boundaries (App Router)

Optional, on-demand detail for this scaffolded head app. The compact guide is [AGENTS.md](../../AGENTS.md); open this file for concrete task examples and edit boundaries.

## Example agent tasks

- **Add a new Sitecore component:** Create the component under `src/components/`, register it in `.sitecore/component-map.ts` and `.sitecore/component-map.client.ts` as appropriate (client components in the client map), and ensure it is rendered in the layout/placeholder as in existing components.
- **Add an API route:** Create the route under `src/app/api/` (e.g. `src/app/api/my-route/route.ts`), add a rewrite in `next.config.ts` if the route should be reached from a public URL, and ensure the proxy `matcher` in `proxy.ts` still excludes it (e.g. `api/` is already excluded).

---

## Boundaries

**Never edit:** `.next/`, `node_modules/`.

**Environment variables:** You may add new env vars when needed. Do it carefully: add the variable to `.env.example` (or `.env.remote.example` / `.env.container.example` in this template) with a placeholder or comment; never put real secrets in example files. If editing `.env.local` for local dev, add only the variable name and tell the user to set the value. **Never commit** `.env` or `.env.local` — they are gitignored.

**Edit with care:** `next.config.ts` (rewrites, next-intl plugin), `sitecore.config.ts` (env only), `proxy.ts` (matcher and proxy order), `src/i18n/routing.ts` and `request.ts`. When adding routes or rewrites, keep middleware `matcher` and rewrite rules consistent.

**Focus on:** `src/app/`, `src/components/`, `src/lib/`, `src/i18n/`, `Layout.tsx`, `Providers.tsx`, `sitecore.config.ts`, `next.config.ts`, `proxy.ts`, `.sitecore/component-map.ts`, `.sitecore/component-map.client.ts`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Layered AI docs (App Router)

Use [AGENTS.md](../../AGENTS.md) first (compact). Open **one** file below when you need depth.

| File | Use when |
|------|----------|
| [AGENTS-overview.md](AGENTS-overview.md) | Project scope and what this head app is |
| [AGENTS-key-concepts.md](AGENTS-key-concepts.md) | Middleware, SitecoreClient, catch-all, locale, component map teaser |
| [AGENTS-router-specifics.md](AGENTS-router-specifics.md) | App Router routing, next-intl, proxy, data fetching, API routes, component maps, layout |
| [AGENTS-workflows-and-boundaries.md](AGENTS-workflows-and-boundaries.md) | Example tasks (new component, API route) and edit boundaries |

Skills: [.agents/skills/](../skills/) — load **one** [SKILL.md](https://agentskills.io) per task. See [Skills.md](../../Skills.md).
Loading
Loading