create-content-sdk-app 2.0.0 → 2.0.1
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/dist/templates/nextjs/.agents/skills/content-sdk-component-data-strategy/SKILL.md +37 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-component-registration/SKILL.md +36 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-component-scaffold/SKILL.md +34 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-component-variants/SKILL.md +36 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-dictionary-and-i18n/SKILL.md +35 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-editing-safe-rendering/SKILL.md +37 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-field-usage-image-link-text/SKILL.md +36 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-graphql-data-fetching/SKILL.md +38 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-multisite-management/SKILL.md +37 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-route-configuration/SKILL.md +38 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-site-setup-and-env/SKILL.md +36 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-sitemap-robots/SKILL.md +37 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-troubleshoot-editing/SKILL.md +39 -0
- package/dist/templates/nextjs/.agents/skills/content-sdk-upgrade-assistant/SKILL.md +36 -0
- package/dist/templates/nextjs/AGENTS.md +1 -0
- package/dist/templates/nextjs/CLAUDE.md +6 -170
- package/dist/templates/nextjs/Skills.md +79 -0
- package/dist/templates/nextjs/package.json +2 -2
- package/dist/templates/nextjs/src/Bootstrap.tsx +20 -13
- package/dist/templates/nextjs/src/byoc/index.tsx +1 -1
- package/dist/templates/nextjs/src/components/content-sdk/CdpPageView.tsx +1 -1
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-component-data-strategy/SKILL.md +37 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-component-registration/SKILL.md +38 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-component-scaffold/SKILL.md +38 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-component-variants/SKILL.md +36 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-dictionary-and-i18n/SKILL.md +37 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-editing-safe-rendering/SKILL.md +37 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-field-usage-image-link-text/SKILL.md +36 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-graphql-data-fetching/SKILL.md +37 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-multisite-management/SKILL.md +37 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-route-configuration/SKILL.md +38 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-site-setup-and-env/SKILL.md +36 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-sitemap-robots/SKILL.md +37 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-troubleshoot-editing/SKILL.md +39 -0
- package/dist/templates/nextjs-app-router/.agents/skills/content-sdk-upgrade-assistant/SKILL.md +36 -0
- package/dist/templates/nextjs-app-router/.sitecore/import-map.server.ts +2 -2
- package/dist/templates/nextjs-app-router/AGENTS.md +6 -6
- package/dist/templates/nextjs-app-router/CLAUDE.md +6 -271
- package/dist/templates/nextjs-app-router/README.md +0 -36
- package/dist/templates/nextjs-app-router/Skills.md +79 -0
- package/dist/templates/nextjs-app-router/package.json +3 -2
- package/dist/templates/nextjs-app-router/src/Bootstrap.tsx +20 -12
- package/dist/templates/nextjs-app-router/src/app/[site]/[locale]/[[...path]]/layout.tsx +19 -0
- package/dist/templates/nextjs-app-router/src/app/[site]/[locale]/[[...path]]/not-found.tsx +3 -28
- package/dist/templates/nextjs-app-router/src/app/[site]/[locale]/[[...path]]/page.tsx +6 -21
- package/dist/templates/nextjs-app-router/src/app/[site]/layout.tsx +5 -21
- package/dist/templates/nextjs-app-router/src/app/not-found.tsx +1 -23
- package/dist/templates/nextjs-app-router/src/byoc/index.tsx +1 -1
- package/dist/templates/nextjs-app-router/src/components/content-sdk/CdpPageView.tsx +1 -1
- package/package.json +2 -2
- package/dist/initializers/angular/args.js +0 -2
- package/dist/initializers/angular/index.js +0 -30
- package/dist/initializers/angular/prompts.js +0 -20
- package/dist/templates/angular/.postcssrc.json +0 -5
- package/dist/templates/angular/.vscode/extensions.json +0 -4
- package/dist/templates/angular/README.md +0 -3
- package/dist/templates/angular/angular.json +0 -79
- package/dist/templates/angular/package.json +0 -58
- package/dist/templates/angular/public/favicon.ico +0 -0
- package/dist/templates/angular/src/app/app.config.server.ts +0 -12
- package/dist/templates/angular/src/app/app.config.ts +0 -31
- package/dist/templates/angular/src/app/app.css +0 -0
- package/dist/templates/angular/src/app/app.html +0 -1
- package/dist/templates/angular/src/app/app.routes.server.ts +0 -15
- package/dist/templates/angular/src/app/app.routes.ts +0 -28
- package/dist/templates/angular/src/app/app.ts +0 -12
- package/dist/templates/angular/src/app/loaders/error.loader.ts +0 -12
- package/dist/templates/angular/src/app/loaders/index.ts +0 -14
- package/dist/templates/angular/src/app/loaders/not-found.loader.ts +0 -12
- package/dist/templates/angular/src/app/loaders/page.loader.ts +0 -15
- package/dist/templates/angular/src/app/loaders/stub-utils.ts +0 -83
- package/dist/templates/angular/src/app/pages/error.component.ts +0 -124
- package/dist/templates/angular/src/app/pages/not-found.component.ts +0 -85
- package/dist/templates/angular/src/app/pages/page.component.ts +0 -58
- package/dist/templates/angular/src/app/shared/layout.component.ts +0 -106
- package/dist/templates/angular/src/index.html +0 -13
- package/dist/templates/angular/src/main.server.ts +0 -8
- package/dist/templates/angular/src/main.ts +0 -6
- package/dist/templates/angular/src/server.ts +0 -65
- package/dist/templates/angular/src/styles.css +0 -3
- package/dist/templates/angular/tsconfig.json +0 -38
- package/dist/templates/angular/tsconfig.spec.json +0 -10
- package/dist/templates/nextjs/LLMs.txt +0 -179
- package/dist/templates/nextjs-app-router/LLMs.txt +0 -236
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Skills.md — Capability groupings for this app (Next.js App Router)
|
|
2
|
+
|
|
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 an App Router app with `[site]`/`[locale]` segments, next-intl, and separate server/client component maps. 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
|
+
|
|
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 **App Router** (e.g. setRequestLocale, draftMode(), component-map.ts + component-map.client.ts).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Why capability grouping
|
|
10
|
+
|
|
11
|
+
Grouping related capabilities makes it easier to know which area of the app applies to a given task and to point to the right docs and patterns. Map the task to one or more of the groupings below; use AGENTS.md and the official docs for concrete steps.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Capability groupings
|
|
16
|
+
|
|
17
|
+
### content-sdk-component-scaffold
|
|
18
|
+
|
|
19
|
+
Creating new Sitecore components: file structure, props interface, and placement under `src/components/`. Use when adding a new component from scratch. In App Router, decide Server vs Client and register in the appropriate map.
|
|
20
|
+
|
|
21
|
+
### content-sdk-component-registration
|
|
22
|
+
|
|
23
|
+
Registering components in `.sitecore/component-map.ts` (Server) and `.sitecore/component-map.client.ts` (Client). Required so layout and editing can resolve and render components. App Router has separate server and client maps.
|
|
24
|
+
|
|
25
|
+
### content-sdk-editing-safe-rendering
|
|
26
|
+
|
|
27
|
+
Safe rendering in XM Cloud editing and preview: `draftMode()`, editing chromes, and design library. Use when ensuring components work in the Sitecore editor and preview. Use `client.getPreview(searchParams)` or `client.getDesignLibraryData(searchParams)` when draft mode is enabled.
|
|
28
|
+
|
|
29
|
+
### content-sdk-field-usage-image-link-text
|
|
30
|
+
|
|
31
|
+
Using SDK field components: `<Text>`, `<RichText>`, `<Image>`, `<Link>`, with proper validation and fallbacks. Use when rendering Sitecore fields.
|
|
32
|
+
|
|
33
|
+
### content-sdk-graphql-data-fetching
|
|
34
|
+
|
|
35
|
+
Page and dictionary fetching via the single Sitecore client in `src/lib/sitecore-client.ts`. Use `getPage(path ?? [], { site, locale })`, `getDictionary`, `getAppRouterStaticParams` for SSG. For preview use `draftMode()` and `getPreview`/`getDesignLibraryData` from searchParams.
|
|
36
|
+
|
|
37
|
+
### content-sdk-route-configuration
|
|
38
|
+
|
|
39
|
+
Routing: single catch-all at `src/app/[site]/[locale]/[[...path]]/page.tsx`. Layout: app/layout.tsx → app/[site]/layout.tsx → page. Call `setRequestLocale(\`${site}_${locale}\`)` at top of page. Use placeholders and Layout.tsx as in AGENTS.md.
|
|
40
|
+
|
|
41
|
+
### content-sdk-site-setup-and-env
|
|
42
|
+
|
|
43
|
+
Site and environment: `sitecore.config.ts`, environment variables, default site and language. Document vars in `.env.example` only; never commit `.env` or `.env.local`.
|
|
44
|
+
|
|
45
|
+
### content-sdk-multisite-management
|
|
46
|
+
|
|
47
|
+
Multisite: `.sitecore/sites.json`, proxy in `src/proxy.ts`. Chain order is **fixed:** LocaleProxy → AppRouterMultisiteProxy → RedirectsProxy → PersonalizeProxy. Do not change proxy order.
|
|
48
|
+
|
|
49
|
+
### content-sdk-dictionary-and-i18n
|
|
50
|
+
|
|
51
|
+
Dictionary and i18n: next-intl with `src/i18n/routing.ts` and `src/i18n/request.ts`. Request locale is `${site}_${locale}`; call `setRequestLocale(\`${site}_${locale}\`)` in the page; in request.ts parse and load dictionary with `client.getDictionary({ locale, site })`.
|
|
52
|
+
|
|
53
|
+
### content-sdk-sitemap-robots
|
|
54
|
+
|
|
55
|
+
Sitemap and robots: `src/app/api/sitemap/route.ts` and `src/app/api/robots/route.ts` with `createSitemapRouteHandler` and `createRobotsRouteHandler`. Rewrites in next.config.ts for /sitemap*.xml and /robots.txt.
|
|
56
|
+
|
|
57
|
+
### content-sdk-component-variants
|
|
58
|
+
|
|
59
|
+
Component variants: different renderings or data-driven variants of the same component type. Use when one component has multiple presentations. Register in the appropriate component map (server or client).
|
|
60
|
+
|
|
61
|
+
### content-sdk-troubleshoot-editing
|
|
62
|
+
|
|
63
|
+
Troubleshooting XM Cloud editing, preview, and design library. Use when editing or preview does not behave as expected. Check draftMode(), getPreview/getDesignLibraryData from searchParams, and component maps.
|
|
64
|
+
|
|
65
|
+
### content-sdk-upgrade-assistant
|
|
66
|
+
|
|
67
|
+
Upgrading @sitecore-content-sdk/* packages: version bumps, breaking changes, migration steps. Use when moving to a newer SDK version. Check the Content SDK repo CHANGELOG and upgrade guides.
|
|
68
|
+
|
|
69
|
+
### content-sdk-component-data-strategy
|
|
70
|
+
|
|
71
|
+
Component data: layout data from getPage (or getPreview/getDesignLibraryData in editing). Pass site and locale from route params; Server Components use the client in server context; Client Components receive serializable props from parent. BYOC must be registered in the component map.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## How to use this
|
|
76
|
+
|
|
77
|
+
Map the task to one or more groupings above. Use [AGENTS.md](AGENTS.md) for app-level instructions and the [official documentation](https://doc.sitecore.com/xmc/en/developers/content-sdk/sitecore-content-sdk-for-xm-cloud.html) for APIs.
|
|
78
|
+
|
|
79
|
+
**If your tool supports Agent Skills:** Load skills from [.agents/skills/](.agents/skills/) (one folder per capability). They provide when-to-use, hard rules, and stop conditions tailored for this App Router app.
|
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
"start": "cross-env-shell NODE_ENV=production npm-run-all --serial build next:start"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@sitecore-cloudsdk/core": "^0.5.4",
|
|
32
|
-
"@sitecore-cloudsdk/events": "^0.5.4",
|
|
33
31
|
"@sitecore-content-sdk/nextjs": "<%- version %>",
|
|
32
|
+
"@sitecore-content-sdk/analytics-core": "<%- version %>",
|
|
33
|
+
"@sitecore-content-sdk/personalize": "<%- version %>",
|
|
34
|
+
"@sitecore-content-sdk/events": "<%- version %>",
|
|
34
35
|
"@sitecore-feaas/clientside": "^0.6.0",
|
|
35
36
|
"@sitecore/components": "~2.1.0",
|
|
36
37
|
"next": "^16.1.1",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useEffect, JSX } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import '@sitecore-
|
|
3
|
+
import { initContentSdk } from '@sitecore-content-sdk/nextjs';
|
|
4
|
+
import { eventsPlugin } from '@sitecore-content-sdk/events';
|
|
5
|
+
import { analyticsBrowserAdapter, analyticsPlugin } from '@sitecore-content-sdk/analytics-core';
|
|
5
6
|
import config from 'sitecore.config';
|
|
6
7
|
|
|
7
8
|
const Bootstrap = ({
|
|
@@ -23,16 +24,23 @@ const Bootstrap = ({
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
if (config.api.edge?.clientContextId) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
initContentSdk({
|
|
28
|
+
config: {
|
|
29
|
+
contextId: config.api.edge.clientContextId,
|
|
30
|
+
edgeUrl: config.api.edge.edgeUrl,
|
|
31
|
+
siteName: siteName || config.defaultSite,
|
|
32
|
+
},
|
|
33
|
+
plugins: [
|
|
34
|
+
analyticsPlugin({
|
|
35
|
+
options: {
|
|
36
|
+
enableCookie: true,
|
|
37
|
+
cookieDomain: window.location.hostname.replace(/^www\./, ''),
|
|
38
|
+
},
|
|
39
|
+
adapter: analyticsBrowserAdapter(),
|
|
40
|
+
}),
|
|
41
|
+
eventsPlugin(),
|
|
42
|
+
],
|
|
43
|
+
});
|
|
36
44
|
} else {
|
|
37
45
|
console.error('Client Edge API settings missing from configuration');
|
|
38
46
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { setCachedPageParams } from '@sitecore-content-sdk/nextjs';
|
|
2
|
+
|
|
3
|
+
export default async function SiteLayout({
|
|
4
|
+
children,
|
|
5
|
+
params,
|
|
6
|
+
}: {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
params: Promise<{ site: string; locale: string }>;
|
|
9
|
+
}) {
|
|
10
|
+
const { site, locale } = await params;
|
|
11
|
+
|
|
12
|
+
// Update the cached page info with the current site and locale values.
|
|
13
|
+
// This ensures the notFound page can access the correct site and locale information when rendered
|
|
14
|
+
// without opting out of SSG by using functions like `headers()`.
|
|
15
|
+
setCachedPageParams({ locale, site });
|
|
16
|
+
|
|
17
|
+
return <>{children}</>;
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -1,21 +1,13 @@
|
|
|
1
1
|
import Link from 'next/link';
|
|
2
|
-
import {
|
|
3
|
-
import { Suspense } from 'react';
|
|
4
|
-
import { ErrorPage } from '@sitecore-content-sdk/nextjs';
|
|
5
|
-
import { parseRewriteHeader } from '@sitecore-content-sdk/nextjs/utils';
|
|
2
|
+
import { ErrorPage, getCachedPageParams } from '@sitecore-content-sdk/nextjs';
|
|
6
3
|
import client from 'lib/sitecore-client';
|
|
7
4
|
import scConfig from 'sitecore.config';
|
|
8
5
|
import Layout from 'src/Layout';
|
|
9
6
|
import Providers from 'src/Providers';
|
|
10
7
|
import { NextIntlClientProvider } from 'next-intl';
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// which allows streaming dynamic content while keeping static parts prerendered.
|
|
15
|
-
// This pattern also works seamlessly when Cache Components is enabled.
|
|
16
|
-
async function DynamicNotFoundContent() {
|
|
17
|
-
const headersList = await headers();
|
|
18
|
-
const { site, locale } = parseRewriteHeader(headersList);
|
|
9
|
+
export default async function NotFound() {
|
|
10
|
+
const { site, locale } = getCachedPageParams();
|
|
19
11
|
|
|
20
12
|
const page = await client.getErrorPage(ErrorPage.NotFound, {
|
|
21
13
|
site: site || scConfig.defaultSite,
|
|
@@ -40,20 +32,3 @@ async function DynamicNotFoundContent() {
|
|
|
40
32
|
</div>
|
|
41
33
|
);
|
|
42
34
|
}
|
|
43
|
-
|
|
44
|
-
export default function NotFound() {
|
|
45
|
-
// Wrap dynamic content in Suspense to enable Next.js 16 Partial Prerendering (PPR).
|
|
46
|
-
// PPR allows streaming dynamic content while keeping static parts prerendered for better performance.
|
|
47
|
-
return (
|
|
48
|
-
<Suspense
|
|
49
|
-
fallback={
|
|
50
|
-
<div style={{ padding: 10 }}>
|
|
51
|
-
<h1>Page not found</h1>
|
|
52
|
-
<p>Loading...</p>
|
|
53
|
-
</div>
|
|
54
|
-
}
|
|
55
|
-
>
|
|
56
|
-
<DynamicNotFoundContent />
|
|
57
|
-
</Suspense>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { isDesignLibraryPreviewData } from '@sitecore-content-sdk/nextjs/editing';
|
|
2
2
|
import { notFound } from 'next/navigation';
|
|
3
3
|
import { draftMode } from 'next/headers';
|
|
4
|
-
import { Suspense } from 'react';
|
|
5
4
|
<% if (prerender === 'SSG') { -%>
|
|
6
5
|
import { SiteInfo } from '@sitecore-content-sdk/nextjs';
|
|
7
6
|
import sites from '.sitecore/sites.json';
|
|
@@ -19,11 +18,12 @@ type PageProps = {
|
|
|
19
18
|
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
|
|
20
19
|
};
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
21
|
+
export default async function Page({ params, searchParams }: PageProps) {
|
|
22
|
+
const { site, locale, path } = await params;
|
|
23
|
+
|
|
24
|
+
// Set site and locale to be available in src/i18n/request.ts for fetching the dictionary
|
|
25
|
+
setRequestLocale(`${site}_${locale}`);
|
|
26
|
+
|
|
27
27
|
const draft = await draftMode();
|
|
28
28
|
|
|
29
29
|
// Fetch the page data from Sitecore
|
|
@@ -53,21 +53,6 @@ async function DynamicPageContent({ site, locale, path, searchParams }: { site:
|
|
|
53
53
|
);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export default async function Page({ params, searchParams }: PageProps) {
|
|
57
|
-
const { site, locale, path } = await params;
|
|
58
|
-
|
|
59
|
-
// Set site and locale to be available in src/i18n/request.ts for fetching the dictionary
|
|
60
|
-
setRequestLocale(`${site}_${locale}`);
|
|
61
|
-
|
|
62
|
-
// Wrap dynamic content in Suspense to enable Next.js 16 Partial Prerendering (PPR).
|
|
63
|
-
// PPR allows streaming dynamic content while keeping static parts prerendered for better performance.
|
|
64
|
-
return (
|
|
65
|
-
<Suspense fallback={<div>Loading...</div>}>
|
|
66
|
-
<DynamicPageContent site={site} locale={locale} path={path} searchParams={searchParams} />
|
|
67
|
-
</Suspense>
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
56
|
<% if (prerender === 'SSG') { -%>
|
|
72
57
|
// This function gets called at build and export time to determine
|
|
73
58
|
// pages for SSG ("paths", as tokenized array).
|
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
import { draftMode } from 'next/headers';
|
|
2
|
-
import { Suspense } from 'react';
|
|
3
2
|
import Bootstrap from 'src/Bootstrap';
|
|
4
3
|
|
|
5
|
-
// Part of layout component that handles dynamic data, like the `draftMode()` call.
|
|
6
|
-
// This component is wrapped in Suspense to enable Next.js 16 Partial Prerendering (PPR),
|
|
7
|
-
// which allows streaming dynamic content while keeping static parts prerendered.
|
|
8
|
-
// This pattern also works seamlessly when Cache Components is enabled.
|
|
9
|
-
async function DynamicLayoutContent({ site, children }: { site: string; children: React.ReactNode }) {
|
|
10
|
-
const { isEnabled } = await draftMode();
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<>
|
|
14
|
-
<Bootstrap siteName={site} isPreviewMode={isEnabled} />
|
|
15
|
-
{children}
|
|
16
|
-
</>
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
4
|
export default async function SiteLayout({
|
|
21
5
|
children,
|
|
22
6
|
params,
|
|
@@ -25,12 +9,12 @@ export default async function SiteLayout({
|
|
|
25
9
|
params: Promise<{ site: string }>;
|
|
26
10
|
}) {
|
|
27
11
|
const { site } = await params;
|
|
12
|
+
const { isEnabled } = await draftMode();
|
|
28
13
|
|
|
29
|
-
// Wrap dynamic content in Suspense to enable Next.js 16 Partial Prerendering (PPR).
|
|
30
|
-
// PPR allows streaming dynamic content while keeping static parts prerendered for better performance.
|
|
31
14
|
return (
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
15
|
+
<>
|
|
16
|
+
<Bootstrap siteName={site} isPreviewMode={isEnabled} />
|
|
17
|
+
{children}
|
|
18
|
+
</>
|
|
35
19
|
);
|
|
36
20
|
}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import Link from 'next/link';
|
|
2
|
-
import { Suspense } from 'react';
|
|
3
2
|
import client from 'lib/sitecore-client';
|
|
4
3
|
import scConfig from 'sitecore.config';
|
|
5
4
|
import { ErrorPage } from '@sitecore-content-sdk/nextjs';
|
|
6
5
|
import Layout from 'src/Layout';
|
|
7
6
|
import Providers from 'src/Providers';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
// This component is wrapped in Suspense to enable Next.js 16 Partial Prerendering (PPR),
|
|
11
|
-
// which allows streaming dynamic content while keeping static parts prerendered.
|
|
12
|
-
// This pattern also works seamlessly when Cache Components is enabled.
|
|
13
|
-
async function DynamicNotFoundContent() {
|
|
8
|
+
export default async function NotFound() {
|
|
14
9
|
if (scConfig.defaultSite) {
|
|
15
10
|
const page = await client.getErrorPage(ErrorPage.NotFound, {
|
|
16
11
|
site: scConfig.defaultSite,
|
|
@@ -34,20 +29,3 @@ async function DynamicNotFoundContent() {
|
|
|
34
29
|
</div>
|
|
35
30
|
);
|
|
36
31
|
}
|
|
37
|
-
|
|
38
|
-
export default function NotFound() {
|
|
39
|
-
// Wrap dynamic content in Suspense to enable Next.js 16 Partial Prerendering (PPR).
|
|
40
|
-
// PPR allows streaming dynamic content while keeping static parts prerendered for better performance.
|
|
41
|
-
return (
|
|
42
|
-
<Suspense
|
|
43
|
-
fallback={
|
|
44
|
-
<div style={{ padding: 10 }}>
|
|
45
|
-
<h1>Page not found</h1>
|
|
46
|
-
<p>Loading...</p>
|
|
47
|
-
</div>
|
|
48
|
-
}
|
|
49
|
-
>
|
|
50
|
-
<DynamicNotFoundContent />
|
|
51
|
-
</Suspense>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
@@ -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-
|
|
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,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { CdpHelper, useSitecore } from '@sitecore-content-sdk/nextjs';
|
|
3
3
|
import { useEffect, JSX } from 'react';
|
|
4
|
-
import { pageView } from '@sitecore-
|
|
4
|
+
import { pageView } from '@sitecore-content-sdk/events';
|
|
5
5
|
import config from 'sitecore.config';
|
|
6
6
|
|
|
7
7
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-content-sdk-app",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Sitecore Content SDK initializer",
|
|
5
5
|
"bin": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"ts-node": "^10.9.2",
|
|
71
71
|
"typescript": "~5.8.3"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "fc12774027a7aa86b870d5da278426b9cdfbfffb"
|
|
74
74
|
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const path_1 = __importDefault(require("path"));
|
|
16
|
-
const common_1 = require("../../common");
|
|
17
|
-
const prompts_1 = require("./prompts");
|
|
18
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
19
|
-
class AngularInitializer {
|
|
20
|
-
init(args) {
|
|
21
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
-
const answers = yield inquirer_1.default.prompt(prompts_1.prompts, args);
|
|
23
|
-
const templatePath = path_1.default.resolve(__dirname, '../../templates/angular');
|
|
24
|
-
yield (0, common_1.transform)(templatePath, Object.assign(Object.assign({}, args), answers));
|
|
25
|
-
const response = {};
|
|
26
|
-
return response;
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.default = AngularInitializer;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.prompts = void 0;
|
|
4
|
-
const common_1 = require("../../common");
|
|
5
|
-
const defaultName = 'content-sdk-angular';
|
|
6
|
-
exports.prompts = [
|
|
7
|
-
...common_1.baseAppPrompts,
|
|
8
|
-
{
|
|
9
|
-
type: 'input',
|
|
10
|
-
name: 'appName',
|
|
11
|
-
message: 'What would you like to name your application?',
|
|
12
|
-
default: defaultName,
|
|
13
|
-
when: (answers) => {
|
|
14
|
-
if (answers.yes && !answers.appName) {
|
|
15
|
-
answers.appName = defaultName;
|
|
16
|
-
}
|
|
17
|
-
return !answers.appName;
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
];
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
|
3
|
-
"version": 1,
|
|
4
|
-
"cli": {
|
|
5
|
-
"packageManager": "yarn"
|
|
6
|
-
},
|
|
7
|
-
"newProjectRoot": "projects",
|
|
8
|
-
"projects": {
|
|
9
|
-
"<%- appName %>": {
|
|
10
|
-
"projectType": "application",
|
|
11
|
-
"schematics": {},
|
|
12
|
-
"root": "",
|
|
13
|
-
"sourceRoot": "src",
|
|
14
|
-
"prefix": "app",
|
|
15
|
-
"architect": {
|
|
16
|
-
"build": {
|
|
17
|
-
"builder": "@angular/build:application",
|
|
18
|
-
"options": {
|
|
19
|
-
"browser": "src/main.ts",
|
|
20
|
-
"tsConfig": "tsconfig.json",
|
|
21
|
-
"assets": [
|
|
22
|
-
{
|
|
23
|
-
"glob": "**/*",
|
|
24
|
-
"input": "public"
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
"styles": ["src/styles.css"],
|
|
28
|
-
"server": "src/main.server.ts",
|
|
29
|
-
"outputMode": "server",
|
|
30
|
-
"ssr": {
|
|
31
|
-
"entry": "src/server.ts"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
"configurations": {
|
|
35
|
-
"production": {
|
|
36
|
-
"budgets": [
|
|
37
|
-
{
|
|
38
|
-
"type": "initial",
|
|
39
|
-
"maximumWarning": "500kB",
|
|
40
|
-
"maximumError": "1MB"
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"type": "anyComponentStyle",
|
|
44
|
-
"maximumWarning": "4kB",
|
|
45
|
-
"maximumError": "8kB"
|
|
46
|
-
}
|
|
47
|
-
],
|
|
48
|
-
"outputHashing": "all"
|
|
49
|
-
},
|
|
50
|
-
"development": {
|
|
51
|
-
"optimization": false,
|
|
52
|
-
"extractLicenses": false,
|
|
53
|
-
"sourceMap": true
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
"defaultConfiguration": "production"
|
|
57
|
-
},
|
|
58
|
-
"serve": {
|
|
59
|
-
"builder": "@angular/build:dev-server",
|
|
60
|
-
"options": {
|
|
61
|
-
"prebundle": false
|
|
62
|
-
},
|
|
63
|
-
"configurations": {
|
|
64
|
-
"production": {
|
|
65
|
-
"buildTarget": "<%- appName %>:build:production"
|
|
66
|
-
},
|
|
67
|
-
"development": {
|
|
68
|
-
"buildTarget": "<%- appName %>:build:development"
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
"defaultConfiguration": "development"
|
|
72
|
-
},
|
|
73
|
-
"test": {
|
|
74
|
-
"builder": "@angular/build:unit-test"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "<%- appName %>",
|
|
3
|
-
"version": "0.0.0",
|
|
4
|
-
"scripts": {
|
|
5
|
-
"ng": "ng",
|
|
6
|
-
"start": "ng serve",
|
|
7
|
-
"build": "ng build",
|
|
8
|
-
"watch": "ng build --watch --configuration development",
|
|
9
|
-
"test": "ng test",
|
|
10
|
-
"serve:ssr": "node dist/<%- appName %>/server/server.mjs"
|
|
11
|
-
},
|
|
12
|
-
"prettier": {
|
|
13
|
-
"printWidth": 100,
|
|
14
|
-
"singleQuote": true,
|
|
15
|
-
"overrides": [
|
|
16
|
-
{
|
|
17
|
-
"files": "*.html",
|
|
18
|
-
"options": {
|
|
19
|
-
"parser": "angular"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
"private": true,
|
|
25
|
-
<%_ if (helper.isDev) { -%>
|
|
26
|
-
"installConfig": {
|
|
27
|
-
"hoistingLimits": "none"
|
|
28
|
-
},
|
|
29
|
-
<% } -%>
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"@angular/common": "^21.1.0",
|
|
32
|
-
"@angular/compiler": "^21.1.0",
|
|
33
|
-
"@angular/core": "^21.1.0",
|
|
34
|
-
"@angular/forms": "^21.1.0",
|
|
35
|
-
"@angular/platform-browser": "^21.1.0",
|
|
36
|
-
"@angular/platform-server": "^21.1.0",
|
|
37
|
-
"@angular/router": "^21.1.0",
|
|
38
|
-
"@angular/ssr": "^21.1.4",
|
|
39
|
-
"@sitecore-content-sdk/angular": "^2.0.0-canary.6",
|
|
40
|
-
"dotenv": "^16.5.0",
|
|
41
|
-
"express": "^5.1.0",
|
|
42
|
-
"rxjs": "~7.8.0",
|
|
43
|
-
"tslib": "^2.3.0"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@angular/build": "^21.1.4",
|
|
47
|
-
"@angular/cli": "^21.1.4",
|
|
48
|
-
"@angular/compiler-cli": "^21.1.0",
|
|
49
|
-
"@tailwindcss/postcss": "^4.1.12",
|
|
50
|
-
"@types/express": "^5.0.1",
|
|
51
|
-
"@types/node": "^20.17.19",
|
|
52
|
-
"jsdom": "^27.1.0",
|
|
53
|
-
"postcss": "^8.5.3",
|
|
54
|
-
"tailwindcss": "^4.1.12",
|
|
55
|
-
"typescript": "~5.9.2",
|
|
56
|
-
"vitest": "^4.0.8"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
Binary file
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
|
|
2
|
-
import { provideServerRendering, withRoutes } from '@angular/ssr';
|
|
3
|
-
import { appConfig } from './app.config';
|
|
4
|
-
import { serverRoutes } from './app.routes.server';
|
|
5
|
-
|
|
6
|
-
const serverConfig: ApplicationConfig = {
|
|
7
|
-
providers: [
|
|
8
|
-
provideServerRendering(withRoutes(serverRoutes))
|
|
9
|
-
]
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const config = mergeApplicationConfig(appConfig, serverConfig);
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
|
|
2
|
-
import { provideRouter, withNavigationErrorHandler } from '@angular/router';
|
|
3
|
-
import { provideHttpClient, withFetch } from '@angular/common/http';
|
|
4
|
-
import {
|
|
5
|
-
provideLoaderRegistry,
|
|
6
|
-
handleNavigationError,
|
|
7
|
-
provideSitecoreAngular,
|
|
8
|
-
PreLoaderDataService,
|
|
9
|
-
} from '@sitecore-content-sdk/angular';
|
|
10
|
-
import { routes } from './app.routes';
|
|
11
|
-
import { LOADERS } from './loaders';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Client hydration is disabled so that RouterLink and other directives attach correctly
|
|
15
|
-
* after bootstrap. With provideClientHydration(), server-rendered DOM is reused and
|
|
16
|
-
* directive event listeners (e.g. RouterLink click) can fail to attach. Without
|
|
17
|
-
* hydration, the client re-renders the app and routing works as expected.
|
|
18
|
-
*/
|
|
19
|
-
export const appConfig: ApplicationConfig = {
|
|
20
|
-
providers: [
|
|
21
|
-
provideBrowserGlobalErrorListeners(),
|
|
22
|
-
provideHttpClient(withFetch()),
|
|
23
|
-
provideSitecoreAngular({
|
|
24
|
-
notFoundRoute: '/404',
|
|
25
|
-
errorRoute: '/500',
|
|
26
|
-
}),
|
|
27
|
-
provideLoaderRegistry(LOADERS),
|
|
28
|
-
PreLoaderDataService,
|
|
29
|
-
provideRouter(routes, withNavigationErrorHandler(handleNavigationError())),
|
|
30
|
-
],
|
|
31
|
-
};
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<router-outlet />
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { RenderMode, ServerRoute } from '@angular/ssr';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Server route config. Define 404 and 500 with status so that when the loader resolver
|
|
5
|
-
* redirects to the not-found or error route (e.g. after NotFoundNavigationError or LoaderHttpError),
|
|
6
|
-
* the server responds with the correct HTTP status code instead of 200.
|
|
7
|
-
*/
|
|
8
|
-
export const serverRoutes: ServerRoute[] = [
|
|
9
|
-
{ path: '404', renderMode: RenderMode.Server, status: 404 },
|
|
10
|
-
{ path: '500', renderMode: RenderMode.Server, status: 500 },
|
|
11
|
-
{
|
|
12
|
-
path: '**',
|
|
13
|
-
renderMode: RenderMode.Server,
|
|
14
|
-
},
|
|
15
|
-
];
|