├── local-containers ├── docker │ ├── data │ │ ├── cm │ │ │ └── .gitkeep │ │ ├── solr │ │ │ └── .gitkeep │ │ └── sql │ │ │ └── .gitkeep │ ├── deploy │ │ └── platform │ │ │ └── .gitkeep │ ├── traefik │ │ ├── certs │ │ │ └── .gitignore │ │ ├── README.md │ │ └── config │ │ │ └── dynamic │ │ │ └── certs_config.yaml │ ├── build │ │ ├── cm │ │ │ ├── readme.md │ │ │ ├── templates │ │ │ │ ├── .gitignore │ │ │ │ └── modules_template │ │ │ │ │ ├── ApiKey.module.json │ │ │ │ │ └── items │ │ │ │ │ └── api-key │ │ │ │ │ └── template.yml │ │ │ └── Dockerfile │ │ ├── README.md │ │ ├── rendering-nextjs │ │ │ └── Dockerfile │ │ └── nodejs │ │ │ └── Dockerfile │ ├── .gitignore │ ├── README.md │ └── clean.ps1 └── scripts │ ├── down.ps1 │ └── New-EdgeToken.ps1 ├── headapps ├── nextjs-starter │ ├── .prettierignore │ ├── src │ │ ├── assets │ │ │ ├── sass │ │ │ │ ├── variants │ │ │ │ │ ├── promo │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── title │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── link-list │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── navigation │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── page-content │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── rich-text │ │ │ │ │ │ └── index.scss │ │ │ │ │ └── index.scss │ │ │ │ ├── base │ │ │ │ │ ├── fonts │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _fonts.scss │ │ │ │ │ ├── links │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _link-button.scss │ │ │ │ │ ├── typehead │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── richtext │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ └── reset │ │ │ │ │ │ ├── _ui-datepicker.scss │ │ │ │ │ │ └── _links.scss │ │ │ │ ├── components │ │ │ │ │ ├── container │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _bordered.scss │ │ │ │ │ ├── layout │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _acaindent.scss │ │ │ │ │ │ └── _background.scss │ │ │ │ │ ├── image │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _image-default-size.scss │ │ │ │ │ ├── rich-text │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── title │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _component-title.scss │ │ │ │ │ ├── spacing │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _background-colors.scss │ │ │ │ │ │ └── _indent.scss │ │ │ │ │ ├── common │ │ │ │ │ │ ├── _promoted-box.scss │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _clearfix.scss │ │ │ │ │ │ ├── _link-button.scss │ │ │ │ │ │ ├── _boxed.scss │ │ │ │ │ │ └── _alignment.scss │ │ │ │ │ ├── link-list │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _list-vertical.scss │ │ │ │ │ ├── image-alignment │ │ │ │ │ │ ├── _image-left.scss │ │ │ │ │ │ └── _image-right.scss │ │ │ │ │ ├── promo │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _absolute-bottom-link.scss │ │ │ │ │ │ ├── _promo-hero.scss │ │ │ │ │ │ └── _promo-shadow.scss │ │ │ │ │ ├── navigation │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _sitemap-navigation.scss │ │ │ │ │ │ └── _navigation-sidebar.scss │ │ │ │ │ ├── _component-column-splitter.scss │ │ │ │ │ ├── _component-image.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ ├── _component-richtext-content.scss │ │ │ │ │ ├── _component-container.scss │ │ │ │ │ ├── _component-promo.scss │ │ │ │ │ └── _component-navigation.scss │ │ │ │ ├── main.scss │ │ │ │ └── abstracts │ │ │ │ │ ├── _vars.scss │ │ │ │ │ ├── _functions.scss │ │ │ │ │ └── vars │ │ │ │ │ ├── _margins.scss │ │ │ │ │ └── _fontSizes.scss │ │ │ ├── main.scss │ │ │ ├── basic │ │ │ │ ├── main.scss │ │ │ │ ├── _fonts.scss │ │ │ │ ├── _variables.scss │ │ │ │ ├── _rich-text.scss │ │ │ │ ├── _footer.scss │ │ │ │ ├── _component.scss │ │ │ │ ├── _header.scss │ │ │ │ ├── _container.scss │ │ │ │ └── _promo.scss │ │ │ └── app.css │ │ ├── temp │ │ │ └── .gitignore │ │ ├── byoc │ │ │ └── index.hybrid.ts │ │ ├── lib │ │ │ ├── graphql-client-factory │ │ │ │ ├── index.ts │ │ │ │ └── create.ts │ │ │ ├── extract-path │ │ │ │ ├── plugins │ │ │ │ │ ├── multisite.ts │ │ │ │ │ └── personalize.ts │ │ │ │ └── index.ts │ │ │ ├── graphql-editing-service.ts │ │ │ ├── config.ts │ │ │ ├── site-resolver │ │ │ │ ├── plugins │ │ │ │ │ ├── multisite.ts │ │ │ │ │ └── default.ts │ │ │ │ └── index.ts │ │ │ ├── next-config │ │ │ │ └── plugins │ │ │ │ │ ├── robots.js │ │ │ │ │ ├── sitemap.js │ │ │ │ │ ├── sass.js │ │ │ │ │ ├── cors-header.js │ │ │ │ │ └── component-props.js │ │ │ ├── page-props.ts │ │ │ ├── component-props │ │ │ │ └── index.ts │ │ │ ├── page-props-factory │ │ │ │ └── plugins │ │ │ │ │ ├── content-styles.ts │ │ │ │ │ ├── component-themes.ts │ │ │ │ │ ├── site.ts │ │ │ │ │ └── personalize.ts │ │ │ ├── sitemap-fetcher │ │ │ │ ├── index.ts │ │ │ │ └── plugins │ │ │ │ │ └── graphql-sitemap-service.ts │ │ │ └── middleware │ │ │ │ └── index.ts │ │ ├── pages │ │ │ ├── api │ │ │ │ ├── healthz.ts │ │ │ │ ├── editing │ │ │ │ │ ├── config.ts │ │ │ │ │ ├── feaas │ │ │ │ │ │ └── render.ts │ │ │ │ │ └── data │ │ │ │ │ │ └── [key].ts │ │ │ │ └── robots.ts │ │ │ ├── _app.tsx │ │ │ ├── _error.tsx │ │ │ └── feaas │ │ │ │ └── render.tsx │ │ ├── NotFound.tsx │ │ ├── components │ │ │ ├── PartialDesignDynamicPlaceholder.tsx │ │ │ ├── RichText.tsx │ │ │ └── ContentBlock.tsx │ │ ├── Scripts.tsx │ │ ├── middleware.ts │ │ └── Navigation.tsx │ ├── scripts │ │ ├── temp │ │ │ └── .gitignore │ │ ├── config │ │ │ ├── plugins │ │ │ │ ├── sxa.ts │ │ │ │ ├── computed.ts │ │ │ │ ├── package-json.ts │ │ │ │ ├── fallback.ts │ │ │ │ ├── scjssconfig.ts │ │ │ │ ├── edge-platform.ts │ │ │ │ └── multisite.ts │ │ │ └── index.ts │ │ ├── bootstrap.ts │ │ ├── scaffold-component │ │ │ └── plugins │ │ │ │ ├── byoc.ts │ │ │ │ ├── next-steps-byoc.ts │ │ │ │ ├── next-steps.ts │ │ │ │ └── component.ts │ │ ├── generate-component-builder │ │ │ └── plugins │ │ │ │ ├── component-builder.ts │ │ │ │ ├── form.ts │ │ │ │ ├── feaas.ts │ │ │ │ ├── packages.ts │ │ │ │ └── components.ts │ │ ├── generate-metadata.ts │ │ ├── templates │ │ │ └── component-src.ts │ │ └── install-pre-push-hook.ts │ ├── public │ │ └── favicon.ico │ ├── .prettierrc │ ├── next-env.d.ts │ ├── tsconfig.scripts.json │ ├── .vscode │ │ ├── extensions.json │ │ └── launch.json │ ├── README.md │ ├── .gitattributes │ ├── .gitignore │ ├── .eslintrc │ └── tsconfig.json └── spa-starters │ ├── angular │ ├── scripts │ │ ├── temp │ │ │ └── .gitignore │ │ ├── generate-component-factory │ │ │ └── plugins │ │ │ │ ├── components.ts │ │ │ │ └── packages.ts │ │ ├── bootstrap.ts │ │ ├── proxy-build.ts │ │ ├── config │ │ │ ├── plugins │ │ │ │ ├── fallback.ts │ │ │ │ ├── computed.ts │ │ │ │ ├── package-json.ts │ │ │ │ └── scjssconfig.ts │ │ │ └── index.ts │ │ ├── generate-metadata.ts │ │ ├── install-pre-push-hook.ts │ │ └── generate-plugins.ts │ ├── src │ │ ├── assets │ │ │ └── styles │ │ │ │ ├── sass │ │ │ │ ├── variants │ │ │ │ │ ├── promo │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── title │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── link-list │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── navigation │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── rich-text │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── page-content │ │ │ │ │ │ └── index.scss │ │ │ │ │ └── index.scss │ │ │ │ ├── base │ │ │ │ │ ├── fonts │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _fonts.scss │ │ │ │ │ ├── links │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _link-button.scss │ │ │ │ │ ├── typehead │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── richtext │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ └── reset │ │ │ │ │ │ ├── _ui-datepicker.scss │ │ │ │ │ │ └── _links.scss │ │ │ │ ├── components │ │ │ │ │ ├── layout │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _acaindent.scss │ │ │ │ │ │ └── _background.scss │ │ │ │ │ ├── container │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _bordered.scss │ │ │ │ │ ├── title │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _component-title.scss │ │ │ │ │ ├── image │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _image-default-size.scss │ │ │ │ │ ├── rich-text │ │ │ │ │ │ └── index.scss │ │ │ │ │ ├── spacing │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _background-colors.scss │ │ │ │ │ │ └── _indent.scss │ │ │ │ │ ├── common │ │ │ │ │ │ ├── _promoted-box.scss │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _clearfix.scss │ │ │ │ │ │ ├── _link-button.scss │ │ │ │ │ │ ├── _boxed.scss │ │ │ │ │ │ └── _alignment.scss │ │ │ │ │ ├── link-list │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ └── _list-vertical.scss │ │ │ │ │ ├── image-alignment │ │ │ │ │ │ ├── _image-left.scss │ │ │ │ │ │ └── _image-right.scss │ │ │ │ │ ├── promo │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _absolute-bottom-link.scss │ │ │ │ │ │ ├── _promo-hero.scss │ │ │ │ │ │ └── _promo-shadow.scss │ │ │ │ │ ├── navigation │ │ │ │ │ │ ├── index.scss │ │ │ │ │ │ ├── _sitemap-navigation.scss │ │ │ │ │ │ └── _navigation-sidebar.scss │ │ │ │ │ ├── _component-column-splitter.scss │ │ │ │ │ ├── _component-image.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ ├── _component-richtext-content.scss │ │ │ │ │ ├── _component-container.scss │ │ │ │ │ └── _component-promo.scss │ │ │ │ ├── main.scss │ │ │ │ └── abstracts │ │ │ │ │ ├── _vars.scss │ │ │ │ │ ├── _functions.scss │ │ │ │ │ └── vars │ │ │ │ │ ├── _margins.scss │ │ │ │ │ └── _fontSizes.scss │ │ │ │ ├── basic │ │ │ │ ├── main.scss │ │ │ │ ├── _fonts.scss │ │ │ │ ├── _variables.scss │ │ │ │ ├── _rich-text.scss │ │ │ │ ├── _footer.scss │ │ │ │ ├── _component.scss │ │ │ │ ├── _header.scss │ │ │ │ ├── _container.scss │ │ │ │ └── _promo.scss │ │ │ │ └── main.scss │ │ ├── environments │ │ │ └── .gitignore │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── routing │ │ │ │ ├── server-error │ │ │ │ │ ├── server-error.component.html │ │ │ │ │ └── server-error.component.ts │ │ │ │ ├── scripts │ │ │ │ │ ├── scripts.component.html │ │ │ │ │ ├── scripts.component.ts │ │ │ │ │ └── scripts.module.ts │ │ │ │ ├── navigation │ │ │ │ │ ├── navigation.component.ts │ │ │ │ │ └── navigation.component.html │ │ │ │ ├── not-found │ │ │ │ │ ├── not-found.component.html │ │ │ │ │ └── not-found.component.ts │ │ │ │ ├── jss-route-resolver.service.ts │ │ │ │ └── layout │ │ │ │ │ └── layout.component.html │ │ │ ├── components │ │ │ │ ├── partial-design-dynamic-placeholder │ │ │ │ │ ├── partial-design-dynamic-placeholder.component.html │ │ │ │ │ └── partial-design-dynamic-placeholder.component.ts │ │ │ │ ├── page-content │ │ │ │ │ ├── page-content.component.html │ │ │ │ │ └── page-content.component.ts │ │ │ │ ├── content-block │ │ │ │ │ ├── content-block.component.html │ │ │ │ │ └── content-block.component.ts │ │ │ │ ├── column-splitter │ │ │ │ │ └── column-splitter.component.html │ │ │ │ ├── richtext │ │ │ │ │ ├── richtext.component.html │ │ │ │ │ └── richtext.component.ts │ │ │ │ ├── title │ │ │ │ │ └── title.component.html │ │ │ │ ├── .gitignore │ │ │ │ ├── row-splitter │ │ │ │ │ ├── row-splitter.component.html │ │ │ │ │ └── row-splitter.component.ts │ │ │ │ ├── promo │ │ │ │ │ ├── promo.component.ts │ │ │ │ │ └── promo.component.html │ │ │ │ ├── link-list │ │ │ │ │ └── link-list.component.html │ │ │ │ ├── sxa.component.ts │ │ │ │ ├── container │ │ │ │ │ ├── container.component.html │ │ │ │ │ └── container.component.ts │ │ │ │ ├── navigation │ │ │ │ │ ├── navigation.component.html │ │ │ │ │ └── navigation-item.component.html │ │ │ │ └── app-components.shared.module.ts │ │ │ ├── JssState.ts │ │ │ ├── lib │ │ │ │ ├── config.ts │ │ │ │ ├── layout-service-factory.ts │ │ │ │ ├── graphql-client-factory │ │ │ │ │ └── index.ts │ │ │ │ └── dictionary-service-factory.ts │ │ │ ├── i18n │ │ │ │ ├── jss-translation-loader.service.ts │ │ │ │ └── jss-translation-client-loader.service.ts │ │ │ ├── jss-meta.service.ts │ │ │ └── app.component.ts │ │ ├── tsconfig.webpack-server.json │ │ ├── typings.d.ts │ │ ├── index.html │ │ ├── main.server.ts │ │ ├── tsconfig.spec.json │ │ ├── tsconfig.server.json │ │ ├── tsconfig.app.json │ │ ├── styles.css │ │ ├── main.ts │ │ └── test.ts │ ├── .eslintignore │ ├── webpack.config.js │ ├── .vscode │ │ └── extensions.json │ ├── proxy.conf.js │ ├── .gitignore │ ├── server.exports.ts │ ├── karma.conf.js │ └── tsconfig.json │ ├── pnpm-workspace.yaml │ ├── .gitignore │ ├── .npmrc │ ├── package.json │ └── proxy │ ├── .gitignore │ ├── tsconfig.json │ ├── package.json │ └── .env ├── .config └── dotnet-tools.json ├── authoring ├── Directory.Build.targets ├── items │ └── nextjs-starter.module.json ├── platform │ ├── README.md │ ├── Properties │ │ └── PublishProfiles │ │ │ └── Local.pubxml │ └── Platform.wpp.targets └── Packages.props ├── .dockerignore ├── .vscode └── settings.json ├── nuget.config ├── .gitignore ├── sitecore.json └── xmcloud.build.json /local-containers/docker/data/cm/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /local-containers/docker/data/solr/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /local-containers/docker/data/sql/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /local-containers/docker/deploy/platform/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/.prettierignore: -------------------------------------------------------------------------------- 1 | package.json -------------------------------------------------------------------------------- /local-containers/docker/traefik/certs/.gitignore: -------------------------------------------------------------------------------- 1 | *.pem -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/variants/promo/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/variants/title/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/temp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/temp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/variants/link-list/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/variants/navigation/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/variants/page-content/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/variants/rich-text/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/temp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/variants/promo/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/variants/title/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/environments/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/fonts/index.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/variants/link-list/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/variants/navigation/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/variants/rich-text/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/variants/page-content/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /local-containers/docker/build/cm/readme.md: -------------------------------------------------------------------------------- 1 | # Placeholder for copy optional files 2 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/links/index.scss: -------------------------------------------------------------------------------- 1 | @import "link-button"; 2 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/typehead/index.scss: -------------------------------------------------------------------------------- 1 | @import "typehead"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/container/index.scss: -------------------------------------------------------------------------------- 1 | @import "bordered"; 2 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/layout/index.scss: -------------------------------------------------------------------------------- 1 | @import "background"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/fonts/index.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | -------------------------------------------------------------------------------- /local-containers/docker/build/cm/templates/.gitignore: -------------------------------------------------------------------------------- 1 | /modules 2 | /.sitecore 3 | sitecore.json -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/image/index.scss: -------------------------------------------------------------------------------- 1 | @import "image-default-size"; 2 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/rich-text/index.scss: -------------------------------------------------------------------------------- 1 | @import "rich-text-lists"; 2 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/title/index.scss: -------------------------------------------------------------------------------- 1 | @import "component-title"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/links/index.scss: -------------------------------------------------------------------------------- 1 | @import "link-button"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/typehead/index.scss: -------------------------------------------------------------------------------- 1 | @import "typehead"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/layout/index.scss: -------------------------------------------------------------------------------- 1 | @import "background"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | # headless apps 3 | - 'angular' 4 | - 'proxy' -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/container/index.scss: -------------------------------------------------------------------------------- 1 | @import "bordered"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/title/index.scss: -------------------------------------------------------------------------------- 1 | @import "component-title"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/image/index.scss: -------------------------------------------------------------------------------- 1 | @import "image-default-size"; 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/rich-text/index.scss: -------------------------------------------------------------------------------- 1 | @import "rich-text-lists"; 2 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/richtext/index.scss: -------------------------------------------------------------------------------- 1 | @import "richtext"; 2 | @import "richtext-files-icons"; 3 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/spacing/index.scss: -------------------------------------------------------------------------------- 1 | @import "background-colors"; 2 | @import "indent"; 3 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/index.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | @import "links"; 3 | @import "reset/ui-datepicker"; 4 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/common/_promoted-box.scss: -------------------------------------------------------------------------------- 1 | .promoted-box { 2 | border: none !important; 3 | } 4 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/link-list/index.scss: -------------------------------------------------------------------------------- 1 | @import "component-link-list"; 2 | @import "list-vertical"; 3 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import "base"; 2 | @import "components"; 3 | @import "variants"; 4 | @import "app"; 5 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/server-error/server-error.component.html: -------------------------------------------------------------------------------- 1 |

2 | 500: Internal Server Error 3 |

4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/richtext/index.scss: -------------------------------------------------------------------------------- 1 | @import "richtext"; 2 | @import "richtext-files-icons"; 3 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/spacing/index.scss: -------------------------------------------------------------------------------- 1 | @import "background-colors"; 2 | @import "indent"; 3 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/abstracts/_vars.scss: -------------------------------------------------------------------------------- 1 | @import "vars/colors"; 2 | @import "vars/margins"; 3 | @import "vars/fontSizes"; 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/index.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | @import "links"; 3 | @import "reset/ui-datepicker"; 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/common/_promoted-box.scss: -------------------------------------------------------------------------------- 1 | .promoted-box { 2 | border: none !important; 3 | } 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/link-list/index.scss: -------------------------------------------------------------------------------- 1 | @import "component-link-list"; 2 | @import "list-vertical"; 3 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/image-alignment/_image-left.scss: -------------------------------------------------------------------------------- 1 | .image-left .component-content>div>img { 2 | float: left; 3 | } 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import "base"; 2 | @import "components"; 3 | @import "variants"; 4 | @import "app"; 5 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sitecorelabs/xmcloud-foundation-head-dev/HEAD/headapps/nextjs-starter/public/favicon.ico -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/image-alignment/_image-right.scss: -------------------------------------------------------------------------------- 1 | .image-right .component-content>div>img { 2 | float: right; 3 | } 4 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/promo/index.scss: -------------------------------------------------------------------------------- 1 | @import "absolute-bottom-link"; 2 | @import "promo-hero"; 3 | @import "promo-shadow"; 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/abstracts/_vars.scss: -------------------------------------------------------------------------------- 1 | @import "vars/colors"; 2 | @import "vars/margins"; 3 | @import "vars/fontSizes"; 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | # dependencies 3 | /node_modules 4 | 5 | /.pnpm-store 6 | -------------------------------------------------------------------------------- /headapps/spa-starters/.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers=true 2 | link-workspace-packages=true 3 | prefer-workspace-packages=true 4 | recursive-install=true 5 | node-linker=hoisted -------------------------------------------------------------------------------- /headapps/spa-starters/angular/.eslintignore: -------------------------------------------------------------------------------- 1 | src/environments/environment.js 2 | src/environments/environment.prod.js 3 | src/app/components/app-components.module.ts 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/image-alignment/_image-left.scss: -------------------------------------------------------------------------------- 1 | .image-left .component-content>div>img { 2 | float: left; 3 | } 4 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/promo/index.scss: -------------------------------------------------------------------------------- 1 | @import "absolute-bottom-link"; 2 | @import "promo-hero"; 3 | @import "promo-shadow"; 4 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/main.scss: -------------------------------------------------------------------------------- 1 | @import "basic/fonts"; 2 | @import "bootstrap/scss/bootstrap"; 3 | @import "sass/main.scss"; 4 | @import "basic/main.scss"; 5 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/image-alignment/_image-right.scss: -------------------------------------------------------------------------------- 1 | .image-right .component-content>div>img { 2 | float: right; 3 | } 4 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/layout/_acaindent.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | 3 | .alan-indent { 4 | margin: 0 $extralarge-margin; 5 | } 6 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/tsconfig.webpack-server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/layout/_acaindent.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | 3 | .alan-indent { 4 | margin: 0 $extralarge-margin; 5 | } 6 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/reset/_ui-datepicker.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/vars'; 2 | 3 | .ui-datepicker-title { 4 | select { 5 | color: $text-basic; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "crlf", 3 | "semi": true, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "es5", 7 | "printWidth": 100 8 | } 9 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/image/_image-default-size.scss: -------------------------------------------------------------------------------- 1 | .image-default-size { 2 | img { 3 | max-width: none; 4 | width: auto !important; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/variants/index.scss: -------------------------------------------------------------------------------- 1 | @import "link-list"; 2 | @import "navigation"; 3 | @import "page-content"; 4 | @import "promo"; 5 | @import "rich-text"; 6 | @import "title"; -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | /* eslint-disable no-var */ 3 | declare var module: NodeModule; 4 | interface NodeModule { 5 | id: string; 6 | } 7 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/webpack.config.js: -------------------------------------------------------------------------------- 1 | const Dotenv = require('dotenv-webpack'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | plugins: [new Dotenv()], 6 | 7 | }; 8 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/reset/_ui-datepicker.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/vars'; 2 | 3 | .ui-datepicker-title { 4 | select { 5 | color: $text-basic; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/variants/index.scss: -------------------------------------------------------------------------------- 1 | @import "link-list"; 2 | @import "navigation"; 3 | @import "page-content"; 4 | @import "promo"; 5 | @import "rich-text"; 6 | @import "title"; -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/common/index.scss: -------------------------------------------------------------------------------- 1 | @import "alignment"; 2 | @import "boxed"; 3 | @import "clearfix"; 4 | @import "highlighted"; 5 | @import "link-button"; 6 | @import "promoted-box"; -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/image/_image-default-size.scss: -------------------------------------------------------------------------------- 1 | .image-default-size { 2 | img { 3 | max-width: none; 4 | width: auto !important; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/common/index.scss: -------------------------------------------------------------------------------- 1 | @import "alignment"; 2 | @import "boxed"; 3 | @import "clearfix"; 4 | @import "highlighted"; 5 | @import "link-button"; 6 | @import "promoted-box"; -------------------------------------------------------------------------------- /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "sitecore.cli": { 6 | "version": "6.0.23", 7 | "commands": [ 8 | "sitecore" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/main.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | @import "container"; 3 | @import "header"; 4 | @import "promo"; 5 | @import "navigation"; 6 | @import "component"; 7 | @import "rich-text"; 8 | @import "footer"; 9 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/fonts/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese'); 2 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/page-content/page-content.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/main.scss: -------------------------------------------------------------------------------- 1 | @import "fonts"; 2 | @import "container"; 3 | @import "header"; 4 | @import "promo"; 5 | @import "navigation"; 6 | @import "component"; 7 | @import "rich-text"; 8 | @import "footer"; 9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/fonts/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese'); 2 | -------------------------------------------------------------------------------- /local-containers/docker/.gitignore: -------------------------------------------------------------------------------- 1 | /data/cm/* 2 | !/data/cm/.gitkeep 3 | /data/cd/* 4 | !/data/cd/.gitkeep 5 | /data/sql/* 6 | !/data/sql/.gitkeep 7 | /data/solr/* 8 | !/data/solr/.gitkeep 9 | 10 | /deploy/platform/* 11 | !/deploy/platform/.gitkeep -------------------------------------------------------------------------------- /headapps/nextjs-starter/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/navigation/index.scss: -------------------------------------------------------------------------------- 1 | @import "navigation-main-horizontal-vertical"; 2 | @import "navigation-mobile"; 3 | @import "navigation-sidebar"; 4 | @import "sitemap-navigation"; 5 | @import "navigation-fat"; 6 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/tsconfig.scripts.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "ts-node": { 4 | "require": [ 5 | "tsconfig-paths/register" 6 | ] 7 | }, 8 | "compilerOptions": { 9 | "module": "commonjs" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/scripts/scripts.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "GraphQL.vscode-graphql", 4 | "dbaeumer.vscode-eslint", 5 | "esbenp.prettier-vscode", 6 | "mikestead.dotenv", 7 | "redhat.vscode-yaml", 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/abstracts/_functions.scss: -------------------------------------------------------------------------------- 1 | @function headings($from:1, $to:6) { 2 | @if $from==$to { 3 | @return 'h#{$from}'; 4 | } 5 | @else { 6 | @return 'h#{$from},'+headings($from+1, $to); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/scripts/scripts.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-scripts', 5 | templateUrl: './scripts.component.html', 6 | }) 7 | export class ScriptsComponent {} 8 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/navigation/index.scss: -------------------------------------------------------------------------------- 1 | @import "navigation-main-horizontal-vertical"; 2 | @import "navigation-mobile"; 3 | @import "navigation-sidebar"; 4 | @import "sitemap-navigation"; 5 | @import "navigation-fat"; 6 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | /* FontAwesome */ 3 | @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css'); 4 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/promo/_absolute-bottom-link.scss: -------------------------------------------------------------------------------- 1 | .promo.absolute-bottom-link { 2 | position: relative; 3 | .field-promolink { 4 | position: absolute; 5 | bottom: 10px; 6 | right: 10px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "GraphQL.vscode-graphql", 4 | "dbaeumer.vscode-eslint", 5 | "esbenp.prettier-vscode", 6 | "mikestead.dotenv", 7 | "redhat.vscode-yaml", 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /local-containers/docker/traefik/README.md: -------------------------------------------------------------------------------- 1 | # Traefik Proxy 2 | 3 | This path contains certificates and configuration for the Traefik 4 | reverse proxy, which is used in container-based Sitecore development 5 | environments. See Sitecore Containers documentation for more information. -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/navigation/navigation.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-navigation', 5 | templateUrl: './navigation.component.html', 6 | }) 7 | export class NavigationComponent {} 8 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/not-found/not-found.component.html: -------------------------------------------------------------------------------- 1 |

Not found

2 |

This page does not exist.

3 |

4 | Site: {{errorContextData?.context?.site?.name}} 5 |
6 | Language: {{errorContextData?.context?.language}} 7 |

8 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/abstracts/_functions.scss: -------------------------------------------------------------------------------- 1 | @function headings($from:1, $to:6) { 2 | @if $from==$to { 3 | @return 'h#{$from}'; 4 | } 5 | @else { 6 | @return 'h#{$from},'+headings($from+1, $to); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/content-block/content-block.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 |
4 |
5 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/promo/_absolute-bottom-link.scss: -------------------------------------------------------------------------------- 1 | .promo.absolute-bottom-link { 2 | position: relative; 3 | .field-promolink { 4 | position: absolute; 5 | bottom: 10px; 6 | right: 10px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/server-error/server-error.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-server-error', 5 | templateUrl: './server-error.component.html', 6 | }) 7 | export class ServerErrorComponent { } 8 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | /* FontAwesome */ 3 | @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css'); 4 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_variables.scss: -------------------------------------------------------------------------------- 1 | $text-size-14: 14px; 2 | $text-size-16: 16px; 3 | $text-size-18: 18px; 4 | $text-size-24: 24px; 5 | $text-size-30: 30px; 6 | $text-size-36: 36px; 7 | $text-size-48: 48px; 8 | $text-size-50: 50px; 9 | 10 | $main-color: #27272A; -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_variables.scss: -------------------------------------------------------------------------------- 1 | $text-size-14: 14px; 2 | $text-size-16: 16px; 3 | $text-size-18: 18px; 4 | $text-size-24: 24px; 5 | $text-size-30: 30px; 6 | $text-size-36: 36px; 7 | $text-size-48: 48px; 8 | $text-size-50: 50px; 9 | 10 | $main-color: #27272A; -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_rich-text.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "variables"; 3 | 4 | .rich-text { 5 | font-size: $text-size-16; 6 | 7 | @include respond-to(mobile-large) { 8 | padding: 0 30px 10px 30px; 9 | font-size: $text-size-14; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/column-splitter/column-splitter.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_rich-text.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "variables"; 3 | 4 | .rich-text { 5 | font-size: $text-size-16; 6 | 7 | @include respond-to(mobile-large) { 8 | padding: 0 30px 10px 30px; 9 | font-size: $text-size-14; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/common/_clearfix.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .component-content-clearfix { 5 | .component-content { 6 | @include clearfix; 7 | } 8 | } 9 | .component-clearfix { 10 | @include clearfix; 11 | } 12 | -------------------------------------------------------------------------------- /local-containers/docker/build/README.md: -------------------------------------------------------------------------------- 1 | # Docker Images for Sitecore Roles 2 | 3 | This path contains a build context for all potential Sitecore roles, 4 | not just those of the XP0 topology used in this example's `docker-compose`. 5 | Most of the Dockerfiles are empty, but in this sample the `cm` and `rendering` 6 | roles are important. -------------------------------------------------------------------------------- /authoring/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/abstracts/vars/_margins.scss: -------------------------------------------------------------------------------- 1 | $default-padding:5px; 2 | $default-inputs-padding:12px 10px; 3 | 4 | $extrasmall-margin-bottom: 2px; 5 | $extrasmall-margin:5px; 6 | $small-margin:10px; 7 | $middle-margin:20px; 8 | $large-margin:30px; 9 | $extralarge-margin:40px; 10 | 11 | $small-padding:10px; -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/JssState.ts: -------------------------------------------------------------------------------- 1 | import { BaseJssState } from '@sitecore-jss/sitecore-jss-angular'; 2 | import { LayoutServiceError } from './layout/jss-layout.service'; 3 | 4 | export class JssState extends BaseJssState { 5 | language: string; 6 | serverRoute: string; 7 | routeFetchError?: LayoutServiceError; 8 | } 9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/richtext/richtext.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 | Rich text 7 | 8 |
9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/common/_clearfix.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .component-content-clearfix { 5 | .component-content { 6 | @include clearfix; 7 | } 8 | } 9 | .component-clearfix { 10 | @include clearfix; 11 | } 12 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | JSS Angular 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/abstracts/vars/_margins.scss: -------------------------------------------------------------------------------- 1 | $default-padding:5px; 2 | $default-inputs-padding:12px 10px; 3 | 4 | $extrasmall-margin-bottom: 2px; 5 | $extrasmall-margin:5px; 6 | $small-margin:10px; 7 | $middle-margin:20px; 8 | $large-margin:30px; 9 | $extralarge-margin:40px; 10 | 11 | $small-padding:10px; -------------------------------------------------------------------------------- /local-containers/docker/build/cm/templates/modules_template/ApiKey.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "namespace": "ApiKey", 3 | "items" : { 4 | "includes": [ 5 | { 6 | "name": "api-key", 7 | "path": "/sitecore/system/Settings/Services/API Keys/" 8 | } 9 | ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import "basic/fonts"; 2 | @import "bootstrap/scss/bootstrap"; 3 | @import "sass/main.scss"; 4 | @import "basic/main.scss"; 5 | 6 | sc-placeholder { 7 | display: flex; 8 | flex-direction: column; 9 | flex-grow: 1; 10 | 11 | &.row { 12 | flex-direction: row; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /local-containers/docker/README.md: -------------------------------------------------------------------------------- 1 | # Sitecore Containers 2 | 3 | This example follows the recommended folder structure for container-based 4 | Sitecore solutions. See Sitecore Containers documentation for more information. 5 | 6 | The `clean.ps1` script here can be used to "reset" the state of your containers. 7 | It clears all mounted data and deployed/copied build output. -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/byoc/index.hybrid.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * You can import your own hybrid (server render + hydration) components below 3 | * @example 4 | * import './MyHybridComponent'; 5 | * @example 6 | * import 'src/otherFolder/MyOtherComponent'; 7 | */ 8 | 9 | // eslint-disable-next-line import/no-anonymous-default-export 10 | export default {}; 11 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/main.server.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { environment } from './environments/environment'; 3 | 4 | if (environment.production) { 5 | enableProdMode(); 6 | } 7 | 8 | export { AppServerModule } from './app/app.server.module'; 9 | export { renderModule } from '@angular/platform-server'; 10 | -------------------------------------------------------------------------------- /local-containers/docker/traefik/config/dynamic/certs_config.yaml: -------------------------------------------------------------------------------- 1 | tls: 2 | certificates: 3 | - certFile: C:\etc\traefik\certs\_wildcard.xmc-starter-js.localhost.pem 4 | keyFile: C:\etc\traefik\certs\_wildcard.xmc-starter-js.localhost-key.pem 5 | - certFile: C:\etc\traefik\certs\xmcloudcm.localhost.pem 6 | keyFile: C:\etc\traefik\certs\xmcloudcm.localhost-key.pem -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/title/title.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/graphql-client-factory/index.ts: -------------------------------------------------------------------------------- 1 | import config from 'temp/config'; 2 | import { createGraphQLClientFactory } from './create'; 3 | 4 | // The GraphQLRequestClientFactory serves as the central hub for executing GraphQL requests within the application 5 | 6 | // Create a new instance on each import call 7 | export default createGraphQLClientFactory(config); 8 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/.gitignore: -------------------------------------------------------------------------------- 1 | # App component module is auto-generated by default. 2 | # To manually maintain the module, 3 | # - Remove this ignore file 4 | # - Delete /scripts/generate-component-factory/index.ts 5 | # - Remove the reference from /scripts/bootstrap.ts 6 | # - Consider merging app-components.shared and app-components modules 7 | app-components.module.ts 8 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # folders 2 | .git 3 | .gitignore 4 | .vs 5 | .config 6 | .sitecore 7 | build 8 | docker 9 | packages 10 | **/bin/ 11 | **/obj/ 12 | **/out/ 13 | **/node_modules/ 14 | **/.generated/ 15 | **/.next*/ 16 | **/.vscode/ 17 | **/coverage/ 18 | 19 | # files 20 | *Dockerfile 21 | docker-compose* 22 | **/*.md 23 | *.ps1 24 | scjssconfig.json 25 | **/*.yml 26 | **/*.module.json 27 | sitecore.json 28 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/row-splitter/row-splitter.component.html: -------------------------------------------------------------------------------- 1 |
6 |
7 |
8 | 9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /local-containers/scripts/down.ps1: -------------------------------------------------------------------------------- 1 | # Set the root of the repository 2 | $RepoRoot = Resolve-Path "$PSScriptRoot\..\.." 3 | 4 | Write-Host "Down containers..." -ForegroundColor Green 5 | try { 6 | Push-Location $RepoRoot\local-containers 7 | docker-compose down 8 | Pop-Location 9 | if ($LASTEXITCODE -ne 0) { 10 | Write-Error "Container down failed, see errors above." 11 | } 12 | } 13 | finally { 14 | } 15 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/spacing/_background-colors.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/vars'; 2 | 3 | .container-gray-background { 4 | background: $bg-light-gray; 5 | } 6 | .container-clean-background { 7 | background: $bg-basic-color; 8 | } 9 | .container-dark-background { 10 | background: $bg-black-active; 11 | } 12 | .container-color-background { 13 | background: $bg-blue; 14 | } 15 | -------------------------------------------------------------------------------- /local-containers/docker/build/cm/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | 3 | ARG PARENT_IMAGE 4 | ARG SOLUTION_IMAGE 5 | ARG TOOLS_IMAGE 6 | 7 | FROM ${TOOLS_IMAGE} as tools 8 | FROM ${PARENT_IMAGE} 9 | 10 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] 11 | 12 | WORKDIR C:\inetpub\wwwroot 13 | 14 | # Copy developer tools and entrypoint 15 | COPY --from=tools C:\tools C:\tools -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/spacing/_indent.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/vars'; 2 | .indent { 3 | margin: 0 $extralarge-margin; 4 | &.col-xxl-12, &.col-xl-12, &.col-lg-12, &.col-md-12, &.col-12 { 5 | width: calc(100% - ($extralarge-margin * 2)); 6 | } 7 | } 8 | .indent-top { 9 | margin-top: $middle-margin; 10 | } 11 | .indent-bottom { 12 | margin-bottom: $middle-margin; 13 | } 14 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/common/_link-button.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/mixins"; 2 | 3 | .link-button { 4 | @import "@sass/base/links/"; 5 | } 6 | // Promo button 7 | .promo.link-button { 8 | a { 9 | @extend .button-default; 10 | } 11 | } 12 | .link.link-button { 13 | .is-empty-hint, .field-link span, a { 14 | @include default-link-button(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/extract-path/plugins/multisite.ts: -------------------------------------------------------------------------------- 1 | import { normalizeSiteRewrite } from '@sitecore-jss/sitecore-jss-nextjs'; 2 | import { Plugin } from '..'; 3 | 4 | class MultisitePlugin implements Plugin { 5 | exec(path: string) { 6 | // Remove site rewrite segment from the path 7 | return normalizeSiteRewrite(path); 8 | } 9 | } 10 | 11 | export const multisitePlugin = new MultisitePlugin(); 12 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/content-block/content-block.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { ComponentRendering } from '@sitecore-jss/sitecore-jss-angular'; 3 | 4 | @Component({ 5 | selector: 'app-content-block', 6 | templateUrl: './content-block.component.html', 7 | }) 8 | export class ContentBlockComponent { 9 | @Input() rendering: ComponentRendering; 10 | } 11 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/not-found/not-found.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { LayoutServiceContextData } from '@sitecore-jss/sitecore-jss-angular'; 3 | 4 | @Component({ 5 | selector: 'app-not-found', 6 | templateUrl: './not-found.component.html', 7 | }) 8 | export class NotFoundComponent { 9 | @Input() errorContextData: LayoutServiceContextData; 10 | } 11 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/graphql-editing-service.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLEditingService } from '@sitecore-jss/sitecore-jss-nextjs/editing'; 2 | import clientFactory from 'lib/graphql-client-factory'; 3 | 4 | /** 5 | * GraphQL Editing Service instance. Used to fetch editing data in Pages preview (editing) Metadata Edit Mode. 6 | */ 7 | export const graphQLEditingService = new GraphQLEditingService({ 8 | clientFactory, 9 | }); 10 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/spacing/_background-colors.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/vars'; 2 | 3 | .container-gray-background { 4 | background: $bg-light-gray; 5 | } 6 | .container-clean-background { 7 | background: $bg-basic-color; 8 | } 9 | .container-dark-background { 10 | background: $bg-black-active; 11 | } 12 | .container-color-background { 13 | background: $bg-blue; 14 | } 15 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/spacing/_indent.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/vars'; 2 | .indent { 3 | margin: 0 $extralarge-margin; 4 | &.col-xxl-12, &.col-xl-12, &.col-lg-12, &.col-md-12, &.col-12 { 5 | width: calc(100% - ($extralarge-margin * 2)); 6 | } 7 | } 8 | .indent-top { 9 | margin-top: $middle-margin; 10 | } 11 | .indent-bottom { 12 | margin-bottom: $middle-margin; 13 | } 14 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/reset/_links.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/mixins"; 2 | @import "@sass/abstracts/vars"; 3 | 4 | a { 5 | background-color: transparent; 6 | text-decoration: none; 7 | font-size: 1em; 8 | color: $text-basic; 9 | border-bottom: 1px solid $border-basic-color; 10 | &:hover { 11 | color: $text-basic-active; 12 | text-decoration: none; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/common/_boxed.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .boxed { 5 | box-sizing: border-box; 6 | margin: 20px 0; 7 | @include respond-to(tablet) { 8 | padding: 10px; 9 | } 10 | @include respond-to(mobile) { 11 | padding: 10px; 12 | } 13 | >div { 14 | @include wrapper(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/common/_link-button.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/mixins"; 2 | 3 | .link-button { 4 | @import "sass/base/links/"; 5 | } 6 | // Promo button 7 | .promo.link-button { 8 | a { 9 | @extend .button-default; 10 | } 11 | } 12 | .link.link-button { 13 | .is-empty-hint, .field-link span, a { 14 | @include default-link-button(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/_component-column-splitter.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/vars'; 2 | 3 | .row.column-splitter { 4 | margin-left: 0; 5 | margin-right: 0; 6 | padding-left: $default-padding * 0.5; 7 | padding-right: $default-padding * 0.5; 8 | max-width: none; 9 | 10 | > div { 11 | padding-left: $default-padding; 12 | padding-right: $default-padding; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/promo/promo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { SxaComponent } from '../sxa.component'; 3 | 4 | @Component({ 5 | selector: 'app-promo', 6 | templateUrl: './promo.component.html', 7 | host: { 8 | 'class': 'component promo', 9 | '[class]': "styles", 10 | '[id]': "id", 11 | }, 12 | }) 13 | export class PromoComponent extends SxaComponent {} 14 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/reset/_links.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/mixins"; 2 | @import "sass/abstracts/vars"; 3 | 4 | a { 5 | background-color: transparent; 6 | text-decoration: none; 7 | font-size: 1em; 8 | color: $text-basic; 9 | border-bottom: 1px solid $border-basic-color; 10 | &:hover { 11 | color: $text-basic-active; 12 | text-decoration: none; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/common/_boxed.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .boxed { 5 | box-sizing: border-box; 6 | margin: 20px 0; 7 | @include respond-to(tablet) { 8 | padding: 10px; 9 | } 10 | @include respond-to(mobile) { 11 | padding: 10px; 12 | } 13 | >div { 14 | @include wrapper(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/abstracts/vars/_fontSizes.scss: -------------------------------------------------------------------------------- 1 | $font-small:11px; 2 | $font-normal:13px; 3 | $font-medium:16px; 4 | $font-big:20px; 5 | $font-extrabig:24px; 6 | //Navigation 7 | $navigation-font-basic:18px; 8 | $navigation-font-basic-submenu:14px; 9 | //Tabs 10 | $tab-font-header:16px; 11 | //Accordion 12 | $accordion-header:16px; 13 | //Breadcrumb 14 | $breadcrumb-font:15px; 15 | // Link List 16 | $link-list-title-font:15px; 17 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/extract-path/plugins/personalize.ts: -------------------------------------------------------------------------------- 1 | import { normalizePersonalizedRewrite } from '@sitecore-jss/sitecore-jss-nextjs'; 2 | import { Plugin } from '..'; 3 | 4 | class PersonalizePlugin implements Plugin { 5 | exec(path: string) { 6 | // Remove personalize rewrite segment from the path 7 | return normalizePersonalizedRewrite(path); 8 | } 9 | } 10 | 11 | export const personalizePlugin = new PersonalizePlugin(); 12 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/README.md: -------------------------------------------------------------------------------- 1 | # Sitecore JSS Next.js Sample Application 2 | 3 | 6 | [Documentation (Experience Platform)](https://doc.sitecore.com/xp/en/developers/hd/22/sitecore-headless-development/sitecore-javascript-rendering-sdk--jss--for-next-js.html) 7 | 8 | [Documentation (XM Cloud)](https://doc.sitecore.com/xmc/en/developers/xm-cloud/sitecore-javascript-rendering-sdk--jss--for-next-js.html) 9 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/_component-column-splitter.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/vars'; 2 | 3 | .row.column-splitter { 4 | margin-left: 0; 5 | margin-right: 0; 6 | padding-left: calc($default-padding / 2); 7 | padding-right: calc($default-padding / 2); 8 | max-width: none; 9 | 10 | > div { 11 | padding-left: $default-padding; 12 | padding-right: $default-padding; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /authoring/items/nextjs-starter.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../.sitecore/schemas/ModuleFile.schema.json", 3 | "namespace": "nextjs-starter", 4 | "items": { 5 | "path": "nextjs-starter", 6 | "includes": [ 7 | { 8 | "name": "DefaultRenderingHost", 9 | "path": "/sitecore/system/Settings/Services/Rendering Hosts/Default", 10 | "scope": "singleItem" 11 | } 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /headapps/nextjs-starter/.gitattributes: -------------------------------------------------------------------------------- 1 | # Line endings for this repository 2 | # See: https://help.github.com/en/articles/configuring-git-to-handle-line-endings 3 | # This should line up with the expectations from .eslintrc 4 | 5 | # Set the default behavior, in case people don't have core.autocrlf set. 6 | * text=crlf 7 | 8 | # Declare files that will always have CRLF line endings on checkout. 9 | *.ts text eol=crlf 10 | *.tsx text eol=crlf 11 | *.js text eol=crlf 12 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/_component-image.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | 3 | .image { 4 | img { 5 | max-width: 100%; 6 | height: auto; 7 | } 8 | a { 9 | display: inline-block; 10 | max-width: 100%; 11 | } 12 | span { 13 | display: block; 14 | font-style: italic; 15 | font-size: $font-small; 16 | color: $image-caption-color; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/abstracts/vars/_fontSizes.scss: -------------------------------------------------------------------------------- 1 | $font-small:11px; 2 | $font-normal:13px; 3 | $font-medium:16px; 4 | $font-big:20px; 5 | $font-extrabig:24px; 6 | //Navigation 7 | $navigation-font-basic:18px; 8 | $navigation-font-basic-submenu:14px; 9 | //Tabs 10 | $tab-font-header:16px; 11 | //Accordion 12 | $accordion-header:16px; 13 | //Breadcrumb 14 | $breadcrumb-font:15px; 15 | // Link List 16 | $link-list-title-font:15px; 17 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/_component-image.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | 3 | .image { 4 | img { 5 | max-width: 100%; 6 | height: auto; 7 | } 8 | a { 9 | display: inline-block; 10 | max-width: 100%; 11 | } 12 | span { 13 | display: block; 14 | font-style: italic; 15 | font-size: $font-small; 16 | color: $image-caption-color; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Represents the type of config object available within the generated temp/config.js 3 | */ 4 | export interface JssConfig extends Record { 5 | sitecoreApiKey?: string; 6 | sitecoreApiHost?: string; 7 | sitecoreSiteName?: string; 8 | graphQLEndpointPath?: string; 9 | defaultLanguage?: string; 10 | graphQLEndpoint?: string; 11 | layoutServiceConfigurationName?: string; 12 | publicUrl?: string; 13 | } 14 | -------------------------------------------------------------------------------- /local-containers/docker/clean.ps1: -------------------------------------------------------------------------------- 1 | Get-ChildItem -Path (Join-Path $PSScriptRoot "\data") -Directory | ForEach-Object { 2 | $dataPath = $_.FullName 3 | 4 | Get-ChildItem -Path $dataPath -Exclude ".gitkeep" -Recurse | Remove-Item -Force -Recurse -Verbose 5 | } 6 | 7 | Get-ChildItem -Path (Join-Path $PSScriptRoot "\deploy") -Directory | ForEach-Object { 8 | $deployPath = $_.FullName 9 | 10 | Get-ChildItem -Path $deployPath -Exclude ".gitkeep" -Recurse | Remove-Item -Force -Recurse -Verbose 11 | } -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/link-list/_list-vertical.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/vars'; 2 | @import '@sass/abstracts/mixins'; 3 | 4 | .link-list.list-vertical { 5 | h3 { 6 | background: $bg-basic-color; 7 | width: 100%; 8 | display: inline-block; 9 | padding: 3px 5px; 10 | @include border-basic(); 11 | } 12 | a { 13 | border: none; 14 | } 15 | li { 16 | display: block; 17 | margin-left: $middle-margin; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /local-containers/docker/build/rendering-nextjs/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | 3 | # 4 | # Development-only image for running Next.js in a containerized environment. 5 | # Assumes that the Next.js rendering host source is mounted to c:\app. 6 | # 7 | 8 | ARG PARENT_IMAGE 9 | FROM ${PARENT_IMAGE} as debug 10 | 11 | USER ContainerAdministrator 12 | 13 | WORKDIR /app 14 | 15 | EXPOSE 3000 16 | #ENTRYPOINT "npm install && npm install next@canary && npm run start:connected" 17 | ENTRYPOINT "npm install && npm run start:connected" -------------------------------------------------------------------------------- /headapps/nextjs-starter/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Attach to Process", 9 | "type": "node", 10 | "request": "attach", 11 | "skipFiles": ["/**"], 12 | "port": 9229 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/link-list/_list-vertical.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/vars'; 2 | @import 'sass/abstracts/mixins'; 3 | 4 | .link-list.list-vertical { 5 | h3 { 6 | background: $bg-basic-color; 7 | width: 100%; 8 | display: inline-block; 9 | padding: 3px 5px; 10 | @include border-basic(); 11 | } 12 | a { 13 | border: none; 14 | } 15 | li { 16 | display: block; 17 | margin-left: $middle-margin; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/index.scss: -------------------------------------------------------------------------------- 1 | @import "component-column-splitter"; 2 | @import "component-container"; 3 | @import "component-image"; 4 | @import "component-navigation"; 5 | @import "component-promo"; 6 | @import "_component-richtext-content"; 7 | 8 | @import "common"; 9 | @import "container"; 10 | @import "layout"; 11 | @import "spacing"; 12 | @import "promo"; 13 | @import "spacing"; 14 | @import "title"; 15 | @import "image"; 16 | @import "link-list"; 17 | @import "rich-text"; 18 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.sicpackage": "json" 4 | }, 5 | "json.schemas": [ 6 | { 7 | "fileMatch": ["/sitecore.json"], 8 | "url": "./.sitecore/schemas/RootConfigurationFile.schema.json" 9 | }, 10 | { 11 | "fileMatch": ["/.sitecore/user.json"], 12 | "url": "./.sitecore/schemas/UserConfiguration.schema.json" 13 | }, 14 | { 15 | "fileMatch": ["*.module.json"], 16 | "url": "./.sitecore/schemas/ModuleFile.schema.json" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/api/healthz.ts: -------------------------------------------------------------------------------- 1 | import { HealthcheckMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/monitoring'; 2 | 3 | /** 4 | * This Next.js API route is used to handle healthz check request. 5 | * By default this is used only by Sitecore XM Cloud (when running as editing host), 6 | * but could be used in other deployment scenarios. 7 | */ 8 | 9 | // Wire up the HealthcheckMiddleware handler 10 | const handler = new HealthcheckMiddleware().getHandler(); 11 | 12 | export default handler; 13 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/site-resolver/plugins/multisite.ts: -------------------------------------------------------------------------------- 1 | import { SiteInfo } from '@sitecore-jss/sitecore-jss-nextjs/site'; 2 | import config from 'temp/config'; 3 | import { SiteResolverPlugin } from '..'; 4 | 5 | class MultisitePlugin implements SiteResolverPlugin { 6 | exec(sites: SiteInfo[]): SiteInfo[] { 7 | // Add preloaded sites 8 | sites.push(...(JSON.parse(config.sites) as SiteInfo[])); 9 | 10 | return sites; 11 | } 12 | } 13 | 14 | export const multisitePlugin = new MultisitePlugin(); 15 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/NotFound.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import Head from 'next/head'; 3 | 4 | /** 5 | * Rendered in case if we have 404 error 6 | */ 7 | const NotFound = (): JSX.Element => ( 8 | <> 9 | 10 | 404: NotFound 11 | 12 |
13 |

Page not found

14 |

This page does not exist.

15 | Go to the Home page 16 |
17 | 18 | ); 19 | 20 | export default NotFound; 21 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/components/PartialDesignDynamicPlaceholder.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import { Placeholder, ComponentRendering } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | 4 | type DynamicPlaceholderProps = { 5 | rendering: ComponentRendering; 6 | }; 7 | 8 | const PartialDesignDynamicPlaceholder = (props: DynamicPlaceholderProps): JSX.Element => ( 9 | 10 | ); 11 | 12 | export default PartialDesignDynamicPlaceholder; 13 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/index.scss: -------------------------------------------------------------------------------- 1 | @import "component-column-splitter"; 2 | @import "component-container"; 3 | @import "component-image"; 4 | @import "component-navigation"; 5 | @import "component-promo"; 6 | @import "_component-richtext-content"; 7 | 8 | @import "common"; 9 | @import "container"; 10 | @import "layout"; 11 | @import "spacing"; 12 | @import "promo"; 13 | @import "spacing"; 14 | @import "title"; 15 | @import "image"; 16 | @import "link-list"; 17 | @import "rich-text"; 18 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "target": "es5", 7 | "newLine": "LF", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | }, 13 | "lib": [ 14 | "esnext.asynciterable" 15 | ], 16 | "files": [ 17 | "test.ts", 18 | "polyfills.ts" 19 | ], 20 | "include": [ 21 | "**/*.spec.ts", 22 | "**/*.d.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/tsconfig.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "target": "ES2022", 7 | "module": "commonjs", 8 | "newLine": "LF" 9 | }, 10 | "lib": [ 11 | "esnext.asynciterable" 12 | ], 13 | "files": [ 14 | "main.server.ts", 15 | "../server.bundle.ts" 16 | ], 17 | "angularCompilerOptions": { 18 | "entryModule": "app/app.server.module#AppServerModule" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /authoring/platform/README.md: -------------------------------------------------------------------------------- 1 | # Sitecore Platform Project 2 | 3 | This Visual Studio / MSBuild project is used to deploy code and configuration 4 | to the main Sitecore platform roles, known as Content Management and 5 | Content Delivery. (This sample uses the XP0 container topology and thus only has a 6 | Standalone `cm`.) 7 | 8 | To deploy configuration, assemblies, and content from this project into your running Docker 9 | environment, run a Publish of it from Visual Studio. To debug, you can attach to 10 | the `w3wp` process within the `cm` container. -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/plugins/sxa.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | 4 | /** 5 | * This plugin will set configuration specific for SXA. 6 | */ 7 | class SXAPlugin implements ConfigPlugin { 8 | // should come before fallback 9 | order = 1; 10 | 11 | async exec(config: JssConfig) { 12 | return Object.assign({}, config, { 13 | layoutServiceConfigurationName: 'sxa-jss', 14 | }); 15 | } 16 | } 17 | 18 | export const sxaPlugin = new SXAPlugin(); 19 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/next-config/plugins/robots.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {import('next').NextConfig} nextConfig 3 | */ 4 | const robotsPlugin = (nextConfig = {}) => { 5 | return Object.assign({}, nextConfig, { 6 | async rewrites() { 7 | return [ 8 | ...await nextConfig.rewrites(), 9 | // robots route 10 | { 11 | source: '/robots.txt', 12 | destination: '/api/robots', 13 | }, 14 | ]; 15 | }, 16 | }); 17 | }; 18 | 19 | module.exports = robotsPlugin; 20 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/_component-richtext-content.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .content, .rich-text { 5 | border: $rich-content-border; 6 | line-height: 1.5; 7 | font-size: 12px; 8 | overflow: hidden; 9 | * { 10 | max-width: 100%; 11 | } 12 | @import "@sass/base/richtext"; 13 | } 14 | .rich-text { 15 | @import "@sass/variants/rich-text"; 16 | } 17 | .content { 18 | @import "@sass/variants/page-content"; 19 | } 20 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/page-props.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DictionaryPhrases, 3 | ComponentPropsCollection, 4 | LayoutServiceData, 5 | SiteInfo, 6 | HTMLLink, 7 | } from '@sitecore-jss/sitecore-jss-nextjs'; 8 | 9 | /** 10 | * Sitecore page props 11 | */ 12 | export type SitecorePageProps = { 13 | site: SiteInfo; 14 | locale: string; 15 | dictionary: DictionaryPhrases; 16 | componentProps: ComponentPropsCollection; 17 | notFound: boolean; 18 | layoutData: LayoutServiceData; 19 | headLinks: HTMLLink[]; 20 | }; 21 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/api/editing/config.ts: -------------------------------------------------------------------------------- 1 | import { EditingConfigMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/editing'; 2 | import { components } from 'temp/componentBuilder'; 3 | import metadata from 'temp/metadata.json'; 4 | 5 | /** 6 | * This Next.js API route is used by Sitecore editors (Pages) in XM Cloud 7 | * to determine feature compatibility and configuration. 8 | */ 9 | 10 | const handler = new EditingConfigMiddleware({ 11 | components, 12 | metadata, 13 | }).getHandler(); 14 | 15 | export default handler; 16 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/_component-richtext-content.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .content, .rich-text { 5 | border: $rich-content-border; 6 | line-height: 1.5; 7 | font-size: 12px; 8 | overflow: hidden; 9 | * { 10 | max-width: 100%; 11 | } 12 | @import "sass/base/richtext"; 13 | } 14 | .rich-text { 15 | @import "sass/variants/rich-text"; 16 | } 17 | .content { 18 | @import "sass/variants/page-content"; 19 | } 20 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/_component-container.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/mixins'; 2 | 3 | $size-padding: 8px; 4 | .container-wrapper { 5 | width: 100%; 6 | } 7 | 8 | .component { 9 | position: relative; 10 | padding: 0 $size-padding; 11 | 12 | @include respond-to(all-mobile) { 13 | padding: 0; 14 | } 15 | } 16 | 17 | .container { 18 | padding: 0; 19 | 20 | &.fullwidth-container { 21 | max-width: unset; 22 | } 23 | 24 | .component-content { 25 | @include clearfix(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/next-config/plugins/sitemap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {import('next').NextConfig} nextConfig 3 | */ 4 | const sitemapPlugin = (nextConfig = {}) => { 5 | return Object.assign({}, nextConfig, { 6 | async rewrites() { 7 | return [ 8 | ...await nextConfig.rewrites(), 9 | // sitemap route 10 | { 11 | source: '/sitemap:id([\\w-]{0,}).xml', 12 | destination: '/api/sitemap' 13 | }, 14 | ]; 15 | }, 16 | }); 17 | }; 18 | 19 | module.exports = sitemapPlugin; 20 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # next.js 10 | /.next*/ 11 | /out/ 12 | 13 | # graphql code generation 14 | /.generated 15 | *.graphql.d.ts 16 | *.graphqls.d.ts 17 | 18 | # misc 19 | .DS_Store 20 | 21 | # local env files 22 | .env.local 23 | .env.*.local 24 | 25 | # Log files 26 | *.log* 27 | 28 | # sitecore 29 | scjssconfig.json 30 | *.deploysecret.config 31 | 32 | # vercel 33 | .vercel -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/_component-container.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/mixins'; 2 | 3 | $size-padding: 8px; 4 | .container-wrapper { 5 | width: 100%; 6 | } 7 | 8 | .component { 9 | position: relative; 10 | padding: 0 $size-padding; 11 | 12 | @include respond-to(all-mobile) { 13 | padding: 0; 14 | } 15 | } 16 | 17 | .container { 18 | padding: 0; 19 | 20 | &.fullwidth-container { 21 | max-width: unset; 22 | } 23 | 24 | .component-content { 25 | @include clearfix(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/link-list/link-list.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 |
5 |
    6 |
  • 7 | 10 |
  • 11 |
12 |
13 | 14 | Link list 15 | 16 | -------------------------------------------------------------------------------- /headapps/spa-starters/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xmcloud-foundation", 3 | "private": true, 4 | "version": "22.9.0", 5 | "description": "This repository contains the Starter Kits for Sitecore XM Cloud Development.", 6 | "scripts": { 7 | "install-build:angular": "pnpm install && pnpm build:angular", 8 | "build:angular": "pnpm -F=angular-starter build", 9 | "start:angular": "pnpm -F=node-xmcloud-sample start" 10 | }, 11 | "license": "ISC", 12 | "packageManager": "pnpm@9.11.0", 13 | "engines": { 14 | "node": ">=22.0.0", 15 | "pnpm": ">=9.11.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/sxa.component.ts: -------------------------------------------------------------------------------- 1 | import { OnInit, Input, Directive } from '@angular/core'; 2 | import { ComponentFields, ComponentRendering } from '@sitecore-jss/sitecore-jss-angular'; 3 | 4 | @Directive() 5 | export abstract class SxaComponent implements OnInit { 6 | @Input() rendering: ComponentRendering; 7 | 8 | id?: string; 9 | styles?: string; 10 | 11 | ngOnInit() { 12 | this.id = this.rendering.params?.RenderingIdentifier; 13 | this.styles = this.rendering.params?.styles; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/scripts/scripts.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ScriptsComponent } from './scripts.component'; 3 | import { JssModule } from '@sitecore-jss/sitecore-jss-angular'; 4 | import { CloudSdkInitComponent } from './cloud-sdk-init.component'; 5 | import { CdpPageViewComponent } from './cdp-page-view.component'; 6 | 7 | @NgModule({ 8 | exports: [ScriptsComponent], 9 | imports: [JssModule], 10 | declarations: [ScriptsComponent, CloudSdkInitComponent, CdpPageViewComponent], 11 | }) 12 | export class ScriptsModule {} 13 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/container/container.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 | 11 | 12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/common/_alignment.scss: -------------------------------------------------------------------------------- 1 | .position-left, 2 | .position-left * { 3 | text-align: left !important; 4 | } 5 | 6 | .position-right, 7 | .position-right * { 8 | text-align: right !important; 9 | } 10 | 11 | .position-center, 12 | .position-center * { 13 | text-align: center !important; 14 | } 15 | 16 | .position-left select { 17 | direction: ltr !important; 18 | } 19 | 20 | .position-right select { 21 | direction: rtl !important; 22 | } 23 | 24 | .position-center select { 25 | text-align-last: center !important; 26 | } -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/site-resolver/plugins/default.ts: -------------------------------------------------------------------------------- 1 | import { SiteInfo } from '@sitecore-jss/sitecore-jss-nextjs/site'; 2 | import config from 'temp/config'; 3 | import { SiteResolverPlugin } from '..'; 4 | 5 | class DefaultPlugin implements SiteResolverPlugin { 6 | exec(sites: SiteInfo[]): SiteInfo[] { 7 | // Add default/configured site 8 | sites.unshift({ 9 | name: config.sitecoreSiteName, 10 | language: config.defaultLanguage, 11 | hostName: '*', 12 | }); 13 | 14 | return sites; 15 | } 16 | } 17 | 18 | export const defaultPlugin = new DefaultPlugin(); 19 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "newLine": "LF" 7 | }, 8 | "lib": [ 9 | "esnext.asynciterable" 10 | ], 11 | "exclude": [ 12 | "test.ts", 13 | "**/*.spec.ts", 14 | "**/*.sitecore.ts", 15 | "./app/jss-context.server-side.service.ts", 16 | "./app/i18n/jss-translation-server-loader.service.ts", 17 | "./app/app.server.module.ts", 18 | "./main.server.ts", 19 | "./environments/environment.prod.js" 20 | ], 21 | } 22 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/generate-component-factory/plugins/components.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactoryPlugin, ComponentFactoryPluginConfig } from '..'; 2 | 3 | /** 4 | * Provides custom components configuration 5 | */ 6 | class ComponentsPlugin implements ComponentFactoryPlugin { 7 | order = 0; 8 | 9 | exec(config: ComponentFactoryPluginConfig) { 10 | /** 11 | * You can specify components which you want to import using custom path 12 | */ 13 | config.components = []; 14 | 15 | return config; 16 | } 17 | } 18 | 19 | export const componentsPlugin = new ComponentsPlugin(); 20 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/lib/config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Represents the type of config object available within the generated /environments/environment.js 3 | */ 4 | export interface JssConfig extends Record { 5 | production?: false; 6 | sitecoreApiKey?: string; 7 | sitecoreApiHost?: string; 8 | sitecoreSiteName?: string; 9 | defaultLanguage?: string; 10 | graphQLEndpoint?: string; 11 | graphQLEndpointPath?: string; 12 | defaultServerRoute?: string; 13 | proxyBuildPath?: string; 14 | sitecoreEdgeUrl?: string; 15 | sitecoreEdgeContextId?: string; 16 | } 17 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/i18n/jss-translation-loader.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { TranslateLoader } from '@ngx-translate/core'; 3 | import { from as fromPromise } from 'rxjs'; 4 | import { dictionaryServiceFactory } from '../lib/dictionary-service-factory'; 5 | 6 | export const dictionaryServiceInstance = dictionaryServiceFactory.create(); 7 | 8 | @Injectable() 9 | export class JssTranslationLoaderService implements TranslateLoader { 10 | getTranslation(lang: string) { 11 | return fromPromise(dictionaryServiceInstance.fetchDictionaryData(lang)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /local-containers/docker/build/nodejs/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | 3 | # 4 | # Basic Windows node.js image for use as a parent image in the solution. 5 | # 6 | 7 | ARG PARENT_IMAGE 8 | FROM $PARENT_IMAGE 9 | 10 | ARG NODEJS_VERSION 11 | 12 | USER ContainerAdministrator 13 | WORKDIR c:\build 14 | RUN curl.exe -sS -L -o node.zip https://nodejs.org/dist/v%NODEJS_VERSION%/node-v%NODEJS_VERSION%-win-x64.zip 15 | RUN tar.exe -xf node.zip -C C:\ 16 | RUN move C:\node-v%NODEJS_VERSION%-win-x64 c:\node 17 | RUN del node.zip 18 | 19 | RUN SETX /M PATH "%PATH%;C:\node\" 20 | RUN icacls.exe C:\node\ /grant "Authenticated Users":(F) /t 21 | USER ContainerUser -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/navigation/_sitemap-navigation.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/vars'; 2 | @import '@sass/abstracts/mixins'; 3 | @import '~font-awesome/scss/mixins'; 4 | @import '~font-awesome/scss/variables'; 5 | 6 | .navigation.sitemap-navigation { 7 | .level2 a { 8 | position: relative; 9 | padding-left: 10px; 10 | &:before { 11 | @include font-size(1.4); 12 | @include fa-icon(); 13 | transform: translateY(-50%) scale(1, -1); 14 | position: absolute; 15 | content: $fa-var-share; 16 | top: 50%; 17 | left: -8px; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/proxy.conf.js: -------------------------------------------------------------------------------- 1 | /* 2 | When the app runs in connected mode, some of the requests should be 3 | proxied to the Sitecore API 4 | */ 5 | const environment = require('./src/environments/environment.js').environment; 6 | 7 | const PROXY_CONFIG = [ 8 | { 9 | context: [ 10 | // API endpoints 11 | '/sitecore', 12 | // media items 13 | '/-', 14 | // visitor identification 15 | '/layouts', 16 | ], 17 | target: environment.sitecoreApiHost, 18 | secure: false, 19 | changeOrigin: true, 20 | }, 21 | ]; 22 | 23 | module.exports = PROXY_CONFIG; 24 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { SxaComponent } from '../sxa.component'; 3 | 4 | @Component({ 5 | selector: 'app-partial-design-dynamic-placeholder', 6 | templateUrl: './partial-design-dynamic-placeholder.component.html', 7 | }) 8 | export class PartialDesignDynamicPlaceholderComponent extends SxaComponent implements OnInit { 9 | sig: string; 10 | ngOnInit() { 11 | super.ngOnInit(); 12 | 13 | this.sig = this.rendering.params?.sig || ''; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/Scripts.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import { EditingScripts } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | // The BYOC bundle imports external (BYOC) components into the app and makes sure they are ready to be used 4 | import BYOC from 'src/byoc'; 5 | import CdpPageView from 'components/CdpPageView'; 6 | import FEAASScripts from 'components/FEAASScripts'; 7 | 8 | const Scripts = (): JSX.Element => { 9 | return ( 10 | <> 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | }; 18 | 19 | export default Scripts; 20 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /* 2 | BOOTSTRAPPING 3 | The bootstrap process runs before build, and generates JS that needs to be 4 | included into the build - specifically, plugins, the global config module, 5 | and the component name to component mapping. 6 | */ 7 | 8 | /* 9 | PLUGINS GENERATION 10 | */ 11 | import './generate-plugins'; 12 | 13 | /* 14 | CONFIG GENERATION 15 | */ 16 | import './generate-config'; 17 | 18 | /* 19 | COMPONENT BUILDER GENERATION 20 | */ 21 | import './generate-component-builder'; 22 | 23 | /* 24 | META DATA GENERATION 25 | */ 26 | import './generate-metadata'; 27 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/navigation/_sitemap-navigation.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/vars'; 2 | @import 'sass/abstracts/mixins'; 3 | @import 'font-awesome/scss/mixins'; 4 | @import 'font-awesome/scss/variables'; 5 | 6 | .navigation.sitemap-navigation { 7 | .level2 a { 8 | position: relative; 9 | padding-left: 10px; 10 | &:before { 11 | @include font-size(1.4); 12 | @include fa-icon(); 13 | transform: translateY(-50%) scale(1, -1); 14 | position: absolute; 15 | content: $fa-var-share; 16 | top: 50%; 17 | left: -8px; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /headapps/spa-starters/proxy/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | 6 | # dependencies 7 | /node_modules 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # IDE - VSCode 14 | .vscode/* 15 | !.vscode/settings.json 16 | !.vscode/tasks.json 17 | !.vscode/launch.json 18 | !.vscode/extensions.json 19 | 20 | # misc 21 | /connect.lock 22 | /libpeerconnection.log 23 | npm-debug.log 24 | testem.log 25 | /typings 26 | 27 | # System Files 28 | .DS_Store 29 | Thumbs.db 30 | 31 | # deploy platforms 32 | .vercel 33 | .netlify 34 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_footer.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/mixins"; 2 | @import "variables"; 3 | 4 | footer { 5 | @include respond-to(mobile-large) { 6 | padding-top: 0; 7 | } 8 | .container-dark-background { 9 | background-color: #262626; 10 | } 11 | 12 | .contacts { 13 | font-size: $text-size-14; 14 | 15 | a { 16 | color: $text-white; 17 | } 18 | 19 | p, span { 20 | color: $text-white; 21 | } 22 | } 23 | 24 | .indent-inner { 25 | padding: 65px; 26 | 27 | @include respond-to(mobile-large) { 28 | padding: 40px 0; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/scaffold-component/plugins/byoc.ts: -------------------------------------------------------------------------------- 1 | import { ScaffoldComponentPlugin, ScaffoldComponentPluginConfig } from '..'; 2 | import generateByocComponentSrc from 'scripts/templates/byoc-component-src'; 3 | 4 | /** 5 | * Sets up generation for BYOC components 6 | */ 7 | class ByocPlugin implements ScaffoldComponentPlugin { 8 | order = 0; 9 | 10 | exec(config: ScaffoldComponentPluginConfig) { 11 | if (config.args.includes('--byoc')) { 12 | config.componentTemplateGenerator = generateByocComponentSrc; 13 | } 14 | 15 | return config; 16 | } 17 | } 18 | 19 | export const byocPlugin = new ByocPlugin(); 20 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/jss-meta.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Meta, Title } from '@angular/platform-browser'; 3 | 4 | export interface MetaSettings { 5 | title?: string; 6 | } 7 | 8 | @Injectable() 9 | export class JssMetaService { 10 | constructor(private titleService: Title, private meta: Meta) {} 11 | 12 | setTitle(title?: string) { 13 | this.titleService.setTitle(title); 14 | } 15 | 16 | setTag(name: string, value: string) { 17 | this.meta.addTag({ name, content: value }); 18 | } 19 | 20 | update(meta: MetaSettings) { 21 | this.setTitle(meta.title); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/jss-route-resolver.service.ts: -------------------------------------------------------------------------------- 1 | import { inject } from '@angular/core'; 2 | import { RouterStateSnapshot, ActivatedRouteSnapshot, ResolveFn } from '@angular/router'; 3 | import { JssContextService } from '../jss-context.service'; 4 | import { JssState } from '../JssState'; 5 | 6 | export const jssRouteResolver: ResolveFn = (route: ActivatedRouteSnapshot, _state: RouterStateSnapshot) => { 7 | // route params are created by custom route matcher in app-routing.module 8 | const jssService = inject(JssContextService); 9 | return jssService.changeRoute(route.params.serverRoute, route.params.language); 10 | }; 11 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_footer.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/mixins"; 2 | @import "variables"; 3 | 4 | footer { 5 | @include respond-to(mobile-large) { 6 | padding-top: 0; 7 | } 8 | .container-dark-background { 9 | background-color: #262626; 10 | } 11 | 12 | .contacts { 13 | font-size: $text-size-14; 14 | 15 | a { 16 | color: $text-white; 17 | } 18 | 19 | p, span { 20 | color: $text-white; 21 | } 22 | } 23 | 24 | .indent-inner { 25 | padding: 65px; 26 | 27 | @include respond-to(mobile-large) { 28 | padding: 40px 0; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/container/_bordered.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .sxa-bordered { 5 | box-sizing: border-box; 6 | >.component-content { 7 | padding: 0; 8 | @include border-basic(); 9 | border-radius: 5px; 10 | } 11 | } 12 | 13 | .column-splitter, 14 | .row-splitter { 15 | box-sizing: border-box; 16 | .sxa-bordered { 17 | padding: $default-padding !important; 18 | >.component, 19 | .scEmptyPlaceholder { 20 | @include border-basic(); 21 | border-radius: 5px; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/lib/layout-service-factory.ts: -------------------------------------------------------------------------------- 1 | import { 2 | LayoutService, 3 | GraphQLLayoutService, 4 | } from '@sitecore-jss/sitecore-jss-angular'; 5 | import { environment } from '../../environments/environment'; 6 | import clientFactory from './graphql-client-factory'; 7 | 8 | export class LayoutServiceFactory { 9 | create(): LayoutService { 10 | const service = 11 | new GraphQLLayoutService({ 12 | clientFactory, 13 | siteName: environment.sitecoreSiteName, 14 | }); 15 | 16 | return service; 17 | } 18 | } 19 | 20 | export const layoutServiceFactory = new LayoutServiceFactory(); 21 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | 3 | /* 4 | BOOTSTRAPPING 5 | The bootstrap process runs before build, and generates TS that needs to be 6 | included into the build - specifically, the component name to component mapping, 7 | and the global config module. 8 | */ 9 | 10 | /* 11 | PLUGINS GENERATION 12 | */ 13 | require('./generate-plugins'); 14 | 15 | /* 16 | CONFIG GENERATION 17 | */ 18 | require('./generate-config'); 19 | 20 | /* 21 | COMPONENT FACTORY GENERATION 22 | */ 23 | require('./generate-component-factory'); 24 | 25 | /* 26 | METADATA GENERATION 27 | */ 28 | require('./generate-metadata'); 29 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/proxy-build.ts: -------------------------------------------------------------------------------- 1 | import { environment } from '../src/environments/environment'; 2 | import { cpSync, rmSync } from 'fs'; 3 | 4 | // Executed at the end of the build process (jss build) to move the build output to the proxy build path 5 | 6 | try { 7 | console.log('Moving build output to proxy build path:', environment.proxyBuildPath); 8 | 9 | rmSync(environment.proxyBuildPath, { recursive: true, force: true }); 10 | cpSync('./dist', environment.proxyBuildPath, { recursive: true }); 11 | 12 | console.log('Proxy build prepared successfully!'); 13 | } catch (error) { 14 | console.error('Error preparing proxy build:', error); 15 | } 16 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/container/_bordered.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .sxa-bordered { 5 | box-sizing: border-box; 6 | >.component-content { 7 | padding: 0; 8 | @include border-basic(); 9 | border-radius: 5px; 10 | } 11 | } 12 | 13 | .column-splitter, 14 | .row-splitter { 15 | box-sizing: border-box; 16 | .sxa-bordered { 17 | padding: $default-padding !important; 18 | >.component, 19 | .scEmptyPlaceholder { 20 | @include border-basic(); 21 | border-radius: 5px; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/generate-component-builder/plugins/component-builder.ts: -------------------------------------------------------------------------------- 1 | import { generateComponentBuilder } from '@sitecore-jss/sitecore-jss-dev-tools/nextjs'; 2 | import { 3 | ComponentBuilderPluginConfig, 4 | ComponentBuilderPlugin as ComponentBuilderPluginType, 5 | } from '..'; 6 | 7 | /** 8 | * Generates the component builder file. 9 | */ 10 | class ComponentBuilderPlugin implements ComponentBuilderPluginType { 11 | order = 9999; 12 | 13 | exec(config: ComponentBuilderPluginConfig) { 14 | generateComponentBuilder(config); 15 | 16 | return config; 17 | } 18 | } 19 | 20 | export const componentBuilderPlugin = new ComponentBuilderPlugin(); 21 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/config/plugins/fallback.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | 4 | /** 5 | * This config will set fallback values for properties that were left empty 6 | * If neither env, nor other places had a proper value, this will ensure a fallback is set 7 | */ 8 | class FallbackPlugin implements ConfigPlugin { 9 | // should always come last 10 | order = 100; 11 | 12 | async exec(config: JssConfig) { 13 | return Object.assign({}, config, { 14 | defaultLanguage: config.defaultLanguage || 'en', 15 | }); 16 | } 17 | } 18 | 19 | export const fallbackPlugin = new FallbackPlugin(); 20 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/generate-component-builder/plugins/form.ts: -------------------------------------------------------------------------------- 1 | import { ComponentBuilderPlugin, ComponentBuilderPluginConfig } from '..'; 2 | 3 | /** 4 | * Provides Form component configuration 5 | */ 6 | class FormPlugin implements ComponentBuilderPlugin { 7 | order = 1; 8 | 9 | exec(config: ComponentBuilderPluginConfig) { 10 | config.packages.push({ 11 | name: '@sitecore-jss/sitecore-jss-nextjs', 12 | components: [ 13 | { 14 | componentName: 'Form', 15 | moduleName: 'Form', 16 | }, 17 | ], 18 | }); 19 | 20 | return config; 21 | } 22 | } 23 | 24 | export const formPlugin = new FormPlugin(); 25 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/api/editing/feaas/render.ts: -------------------------------------------------------------------------------- 1 | import { FEAASRenderMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/editing'; 2 | 3 | /** 4 | * This Next.js API route is used to handle GET requests from Sitecore Component Builder. 5 | * 6 | * The `FEAASRenderMiddleware` will: 7 | * 1. Enable Next.js Preview Mode. 8 | * 2. Redirect the request to the /feaas/render page. 9 | * - If "feaasSrc" query parameter is provided, the page will render a FEAAS component. 10 | * - The page provides all the registered FEAAS components. 11 | */ 12 | 13 | // Wire up the FEAASRenderMiddleware handler 14 | const handler = new FEAASRenderMiddleware().getHandler(); 15 | 16 | export default handler; 17 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/lib/graphql-client-factory/index.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLRequestClient } from '@sitecore-jss/sitecore-jss-angular/cjs'; 2 | import { getGraphQLClientFactoryConfig } from './config'; 3 | 4 | // The GraphQLRequestClientFactory serves as the central hub for executing GraphQL requests within the application 5 | 6 | /** 7 | * Creates a new GraphQLRequestClientFactory instance 8 | * @returns GraphQLRequestClientFactory instance 9 | */ 10 | const createGraphQLClientFactory = () => { 11 | const clientConfig = getGraphQLClientFactoryConfig(); 12 | 13 | return GraphQLRequestClient.createClientFactory(clientConfig); 14 | }; 15 | 16 | export default createGraphQLClientFactory(); 17 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/richtext/richtext.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Field } from '@sitecore-jss/sitecore-jss-angular'; 3 | import { SxaComponent } from '../sxa.component'; 4 | 5 | @Component({ 6 | selector: 'app-richtext', 7 | templateUrl: './richtext.component.html', 8 | host: { 9 | 'class': 'component rich-text', 10 | '[class]': "styles", 11 | "[attr.id]": "id" 12 | }, 13 | }) 14 | export class RichTextComponent extends SxaComponent implements OnInit { 15 | text?: Field; 16 | 17 | ngOnInit() { 18 | super.ngOnInit(); 19 | this.text = this.rendering.fields?.Text as Field; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/component-props/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ComponentParams, 3 | ComponentRendering, 4 | SitecoreContextValue, 5 | } from '@sitecore-jss/sitecore-jss-nextjs'; 6 | 7 | /** 8 | * Shared component props 9 | */ 10 | export type ComponentProps = { 11 | rendering: ComponentRendering; 12 | params: ComponentParams; 13 | }; 14 | 15 | /** 16 | * Component props with context 17 | * You can access `sitecoreContext` by withSitecoreContext/useSitecoreContext 18 | * @example withSitecoreContext()(ContentBlock) 19 | * @example const { sitecoreContext } = useSitecoreContext() 20 | */ 21 | export type ComponentWithContextProps = ComponentProps & { 22 | sitecoreContext: SitecoreContextValue; 23 | }; 24 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/navigation/navigation.component.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /headapps/spa-starters/proxy/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "newLine": "LF", 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "noFallthroughCasesInSwitch": true, 7 | "rootDir": ".", 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "noImplicitAny": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "strictFunctionTypes": false, 16 | "downlevelIteration": true, 17 | "moduleResolution": "node", 18 | "isolatedModules": true, 19 | "allowSyntheticDefaultImports": true 20 | }, 21 | "exclude": ["node_modules", "dist"] 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # may contain OAuth secrets, do not commit 2 | .sitecore/user.json 3 | 4 | # NuGet cache for Sitecore CLI 5 | .sitecore/package-cache/ 6 | 7 | # Ephemeral index caches used by serialization, do not commit 8 | .scindex 9 | 10 | # Don't commit packages 11 | *.itempackage 12 | *.sicpackage 13 | 14 | #Ignore thumbnails created by Windows 15 | Thumbs.db 16 | #Ignore files built by Visual Studio 17 | *.obj 18 | *.exe 19 | *.pdb 20 | *.user 21 | *.aps 22 | *.pch 23 | *.vspscc 24 | *_i.c 25 | *_p.c 26 | *.ncb 27 | *.suo 28 | *.tlb 29 | *.tlh 30 | *.bak 31 | *.cache 32 | *.ilk 33 | *.log 34 | [Bb]in 35 | [Dd]ebug*/ 36 | *.lib 37 | *.sbr 38 | obj/ 39 | [Rr]elease*/ 40 | _ReSharper*/ 41 | [Tt]est[Rr]esult* 42 | .vs/ 43 | #Nuget packages folder 44 | packages/ -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/promo/promo.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 15 |
16 |
17 |
18 | 19 | 20 | Promo 21 | 22 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/layout/_background.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | %cover-bg { 5 | background-repeat: no-repeat; 6 | background-size: cover; 7 | } 8 | .cover-background { 9 | >.component-content { 10 | @extend %cover-bg; 11 | } 12 | } 13 | .fix-background { 14 | >.component-content { 15 | @extend %cover-bg; 16 | @include fixed-bg(left top); 17 | } 18 | } 19 | .parallax-background { 20 | >.component-content { 21 | @extend %cover-bg; 22 | @include fixed-bg(50% 0); 23 | @include respond-to(mobile-large) { 24 | background-attachment: scroll; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/navigation/navigation.component.html: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/title/_component-title.scss: -------------------------------------------------------------------------------- 1 | @import '@sass/abstracts/vars'; 2 | @import '@sass/abstracts/mixins'; 3 | 4 | .title { 5 | background: $title-bg; 6 | 7 | h1, 8 | .field-title { 9 | @include border-basic(bottom, $border-basic-color); 10 | font-size: $font-extrabig; 11 | margin-bottom: $small-margin; 12 | color: $title-color; 13 | line-height: normal; 14 | padding-bottom: 10px; 15 | display: block; 16 | text-decoration: none; 17 | cursor: pointer; 18 | 19 | &:hover { 20 | color: $title-color-active; 21 | } 22 | 23 | > a, 24 | > span { 25 | text-decoration: none; 26 | } 27 | } 28 | 29 | @import '@sass/variants/title'; 30 | } 31 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/layout/_background.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | %cover-bg { 5 | background-repeat: no-repeat; 6 | background-size: cover; 7 | } 8 | .cover-background { 9 | >.component-content { 10 | @extend %cover-bg; 11 | } 12 | } 13 | .fix-background { 14 | >.component-content { 15 | @extend %cover-bg; 16 | @include fixed-bg(left top); 17 | } 18 | } 19 | .parallax-background { 20 | >.component-content { 21 | @extend %cover-bg; 22 | @include fixed-bg(50% 0); 23 | @include respond-to(mobile-large) { 24 | background-attachment: scroll; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/styles.css: -------------------------------------------------------------------------------- 1 | a[target='_blank']:after { 2 | content: '\1F5D7' 3 | } 4 | 5 | .logo { 6 | background-image: url('assets/images/sc_logo.svg'); 7 | display: block; 8 | height: 48px; 9 | width: 221px; 10 | } 11 | 12 | /* 13 | Hides Sitecore Experience Editor markup, 14 | if you run the app in connected mode while the Sitecore cookies 15 | are set to edit mode. 16 | */ 17 | .scChromeData, .scpm { display: none !important; } 18 | 19 | /* 20 | Style for default content block 21 | */ 22 | .contentTitle { 23 | font-size: 3.5rem; 24 | font-weight: 300; 25 | line-height: 1.2; 26 | } 27 | 28 | a { 29 | text-decoration: none; 30 | } 31 | 32 | a:hover { 33 | text-decoration: underline; 34 | } 35 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/plugins/computed.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | 4 | /** 5 | * This plugin will set computed config props. 6 | * The "graphQLEndpoint" is an example of making a _computed_ config setting 7 | * based on other config settings. 8 | */ 9 | class ComputedPlugin implements ConfigPlugin { 10 | // should come after other plugins (but before fallback) 11 | order = 10; 12 | 13 | async exec(config: JssConfig) { 14 | return Object.assign({}, config, { 15 | graphQLEndpoint: 16 | config.graphQLEndpoint || `${config.sitecoreApiHost}${config.graphQLEndpointPath}`, 17 | }); 18 | } 19 | } 20 | 21 | export const computedPlugin = new ComputedPlugin(); 22 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/config/plugins/computed.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | 4 | /** 5 | * This plugin will set computed config props. 6 | * The "graphQLEndpoint" is an example of making a _computed_ config setting 7 | * based on other config settings. 8 | */ 9 | class ComputedPlugin implements ConfigPlugin { 10 | // should come after other plugins (but before fallback) 11 | order = 10; 12 | 13 | async exec(config: JssConfig) { 14 | return Object.assign({}, config, { 15 | graphQLEndpoint: 16 | config.graphQLEndpoint || `${config.sitecoreApiHost}${config.graphQLEndpointPath}`, 17 | }); 18 | } 19 | } 20 | 21 | export const computedPlugin = new ComputedPlugin(); 22 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/title/_component-title.scss: -------------------------------------------------------------------------------- 1 | @import 'sass/abstracts/vars'; 2 | @import 'sass/abstracts/mixins'; 3 | 4 | .title { 5 | background: $title-bg; 6 | 7 | h1, 8 | .field-title { 9 | @include border-basic(bottom, $border-basic-color); 10 | font-size: $font-extrabig; 11 | margin-bottom: $small-margin; 12 | color: $title-color; 13 | line-height: normal; 14 | padding-bottom: 10px; 15 | display: block; 16 | text-decoration: none; 17 | cursor: pointer; 18 | 19 | &:hover { 20 | color: $title-color-active; 21 | } 22 | 23 | > a, 24 | > span { 25 | text-decoration: none; 26 | } 27 | } 28 | 29 | @import 'sass/variants/title'; 30 | } 31 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/base/links/_link-button.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars/colors"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .button-default, .default { 5 | @include default-link-button(); 6 | background: #f6f6f6; 7 | color: $text-basic; 8 | } 9 | .button-success, .success { 10 | @include default-link-button(); 11 | background: $btn-green-light; 12 | color: $text-white; 13 | &:hover { 14 | color: $text-white; 15 | background: $btn-green; 16 | } 17 | } 18 | .button-warning, .warning { 19 | @include default-link-button(); 20 | background: $btn-red; 21 | color: $text-white; 22 | &:hover { 23 | color: $text-white; 24 | background: $btn-red-active; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/base/links/_link-button.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars/colors"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .button-default, .default { 5 | @include default-link-button(); 6 | background: #f6f6f6; 7 | color: $text-basic; 8 | } 9 | .button-success, .success { 10 | @include default-link-button(); 11 | background: $btn-green-light; 12 | color: $text-white; 13 | &:hover { 14 | color: $text-white; 15 | background: $btn-green; 16 | } 17 | } 18 | .button-warning, .warning { 19 | @include default-link-button(); 20 | background: $btn-red; 21 | color: $text-white; 22 | &:hover { 23 | color: $text-white; 24 | background: $btn-red-active; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/app.css: -------------------------------------------------------------------------------- 1 | a[target='_blank']:after { 2 | content: '\1F5D7' 3 | } 4 | 5 | /* 6 | Hides Sitecore editor markup, 7 | if you run the app in connected mode while the Sitecore cookies 8 | are set to edit mode. 9 | */ 10 | .scChromeData, .scpm { display: none !important; } 11 | 12 | /* 13 | Styles for default JSS error components 14 | */ 15 | .sc-jss-editing-error, 16 | .sc-jss-placeholder-error { 17 | padding: 1em; 18 | background-color: lightyellow; 19 | } 20 | 21 | /* 22 | Style for default content block 23 | */ 24 | .contentTitle { 25 | font-size: 3.5rem; 26 | font-weight: 300; 27 | line-height: 1.2; 28 | } 29 | 30 | a { 31 | text-decoration: none; 32 | } 33 | 34 | a:hover { 35 | text-decoration: underline; 36 | } 37 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/middleware.ts: -------------------------------------------------------------------------------- 1 | import type { NextRequest, NextFetchEvent } from 'next/server'; 2 | import middleware from 'lib/middleware'; 3 | 4 | // eslint-disable-next-line 5 | export default async function (req: NextRequest, ev: NextFetchEvent) { 6 | return middleware(req, ev); 7 | } 8 | 9 | export const config = { 10 | /* 11 | * Match all paths except for: 12 | * 1. /api routes 13 | * 2. /_next (Next.js internals) 14 | * 3. /sitecore/api (Sitecore API routes) 15 | * 4. /- (Sitecore media) 16 | * 5. /healthz (Health check) 17 | * 6. /feaas-render (FEaaS render) 18 | * 7. all root files inside /public 19 | */ 20 | matcher: [ 21 | '/', 22 | '/((?!api/|_next/|feaas-render|healthz|sitecore/api/|-/|favicon.ico|sc_logo.svg).*)', 23 | ], 24 | }; 25 | -------------------------------------------------------------------------------- /authoring/platform/Properties/PublishProfiles/Local.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | False 8 | False 9 | True 10 | Debug 11 | Any CPU 12 | FileSystem 13 | ..\..\..\local-containers\docker\deploy\platform 14 | FileSystem 15 | 16 | 17 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/next-config/plugins/sass.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const SassAlias = require('sass-alias'); 3 | 4 | /** 5 | * @param {import('next').NextConfig} nextConfig 6 | */ 7 | const sassPlugin = (nextConfig = {}) => { 8 | return Object.assign({}, nextConfig, { 9 | sassOptions: { 10 | importer: new SassAlias({ 11 | '@sass': path.join(__dirname, '../../../assets', 'sass'), 12 | '@fontawesome': path.join(__dirname, '../../../../node_modules', 'font-awesome'), 13 | }).getImporter(), 14 | // temporary measure until new versions of bootstrap and font-awesome released 15 | quietDeps: true, 16 | silenceDeprecations: ["import", "legacy-js-api"], 17 | }, 18 | }); 19 | }; 20 | 21 | module.exports = sassPlugin; 22 | -------------------------------------------------------------------------------- /headapps/spa-starters/proxy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-xmcloud-sample", 3 | "version": "0.1.0", 4 | "description": "Node XM Cloud Proxy sample for running XM Cloud JSS SPA apps", 5 | "author": { 6 | "name": "Sitecore Corporation", 7 | "url": "https://jss.sitecore.com" 8 | }, 9 | "scripts": { 10 | "start": "ts-node ./src/index.ts" 11 | }, 12 | "dependencies": { 13 | "@sitecore-jss/sitecore-jss-proxy": "~22.9.0", 14 | "compression": "^1.8.1", 15 | "express": "^5.1.0", 16 | "dotenv": "^17.2.1", 17 | "http-proxy-middleware": "^3.0.5" 18 | }, 19 | "devDependencies": { 20 | "@sitecore-jss/sitecore-jss": "~22.9.0", 21 | "@types/compression": "^1.8.1", 22 | "@types/express": "^5.0.3", 23 | "ts-node": "^10.9.1", 24 | "typescript": "~5.9.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/page-props-factory/plugins/content-styles.ts: -------------------------------------------------------------------------------- 1 | import { SitecorePageProps } from 'lib/page-props'; 2 | import { getContentStylesheetLink } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | import { Plugin } from '..'; 4 | import config from 'temp/config'; 5 | 6 | class ContentStylesPlugin implements Plugin { 7 | order = 2; 8 | 9 | async exec(props: SitecorePageProps) { 10 | // Get content stylessheet link, empty if styles are not used on the page 11 | const contentStyles = getContentStylesheetLink( 12 | props.layoutData, 13 | config.sitecoreEdgeContextId, 14 | config.sitecoreEdgeUrl 15 | ); 16 | 17 | if (contentStyles) props.headLinks.push(contentStyles); 18 | 19 | return props; 20 | } 21 | } 22 | 23 | export const contentStylesPlugin = new ContentStylesPlugin(); 24 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/generate-component-builder/plugins/feaas.ts: -------------------------------------------------------------------------------- 1 | import { ComponentBuilderPlugin, ComponentBuilderPluginConfig } from '..'; 2 | 3 | /** 4 | * Provides Sitecore Components (FEaaS) packages configuration 5 | */ 6 | class FEaaSPlugin implements ComponentBuilderPlugin { 7 | order = 1; 8 | 9 | exec(config: ComponentBuilderPluginConfig) { 10 | config.packages.push({ 11 | name: '@sitecore-jss/sitecore-jss-nextjs', 12 | components: [ 13 | { 14 | componentName: 'BYOCWrapper', 15 | moduleName: 'BYOCWrapper', 16 | }, 17 | { 18 | componentName: 'FEaaSWrapper', 19 | moduleName: 'FEaaSWrapper', 20 | }, 21 | ], 22 | }); 23 | 24 | return config; 25 | } 26 | } 27 | 28 | export const feaasPlugin = new FEaaSPlugin(); 29 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/plugins/package-json.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | import packageConfig from 'package.json'; 4 | 5 | /** 6 | * This plugin will set config props based on package.json. 7 | */ 8 | class PackageJsonPlugin implements ConfigPlugin { 9 | order = 1; 10 | 11 | async exec(config: JssConfig) { 12 | if (!packageConfig.config) return config; 13 | 14 | return Object.assign({}, config, { 15 | sitecoreSiteName: config.sitecoreSiteName || packageConfig.config.appName, 16 | graphQLEndpointPath: config.graphQLEndpointPath || packageConfig.config.graphQLEndpointPath, 17 | defaultLanguage: config.defaultLanguage || packageConfig.config.language, 18 | }); 19 | } 20 | } 21 | 22 | export const packageJsonPlugin = new PackageJsonPlugin(); 23 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/config/plugins/package-json.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | import packageConfig from 'package.json'; 4 | 5 | /** 6 | * This plugin will set config props based on package.json. 7 | */ 8 | class PackageJsonPlugin implements ConfigPlugin { 9 | order = 1; 10 | 11 | async exec(config: JssConfig) { 12 | if (!packageConfig.config) return config; 13 | 14 | return Object.assign({}, config, { 15 | sitecoreSiteName: config.sitecoreSiteName || packageConfig.config.appName, 16 | graphQLEndpointPath: config.graphQLEndpointPath || packageConfig.config.graphQLEndpointPath, 17 | defaultLanguage: config.defaultLanguage || packageConfig.config.language, 18 | }); 19 | } 20 | } 21 | 22 | export const packageJsonPlugin = new PackageJsonPlugin(); 23 | -------------------------------------------------------------------------------- /headapps/spa-starters/proxy/.env: -------------------------------------------------------------------------------- 1 | # To secure the Sitecore editor endpoint exposed by your proxy app 2 | # (`/api/editing/render` by default), a secret token is used. 3 | # The environment variable is used by `editingRouter` 4 | # We recommend an alphanumeric value of at least 16 characters. 5 | JSS_EDITING_SECRET= 6 | 7 | # Your proxy port (default: 3000) 8 | PROXY_PORT= 9 | 10 | # Your proxy server bundle path 11 | PROXY_BUNDLE_PATH= 12 | 13 | # Set the DEBUG environment variable to 'sitecore-jss:*,sitecore-jss:proxy,http-proxy-middleware*' to see all logs: 14 | #DEBUG=sitecore-jss:*,http-proxy-middleware* 15 | 16 | # Timeout (ms) for Sitecore CDP requests to respond within. Default is 400. 17 | PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT= 18 | 19 | # Timeout (ms) for Sitecore Experience Edge requests to respond within. Default is 400. 20 | PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT= 21 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/components/RichText.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import { Field, RichText as JssRichText } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | 4 | interface Fields { 5 | Text: Field; 6 | } 7 | 8 | export type RichTextProps = { 9 | params: { [key: string]: string }; 10 | fields: Fields; 11 | }; 12 | 13 | export const Default = (props: RichTextProps): JSX.Element => { 14 | const text = props.fields ? ( 15 | 16 | ) : ( 17 | Rich text 18 | ); 19 | const id = props.params.RenderingIdentifier; 20 | 21 | return ( 22 |
26 |
{text}
27 |
28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/page-props-factory/plugins/component-themes.ts: -------------------------------------------------------------------------------- 1 | import { SitecorePageProps } from 'lib/page-props'; 2 | import { getDesignLibraryStylesheetLinks } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | import { Plugin } from '..'; 4 | import config from 'temp/config'; 5 | 6 | class ComponentThemesPlugin implements Plugin { 7 | // Make sure to run this plugin after the personalization plugin, since it relies on the layout data 8 | order = 10; 9 | 10 | async exec(props: SitecorePageProps) { 11 | // Collect FEAAS, BYOC, SXA component themes 12 | props.headLinks.push( 13 | ...getDesignLibraryStylesheetLinks( 14 | props.layoutData, 15 | config.sitecoreEdgeContextId, 16 | config.sitecoreEdgeUrl 17 | ) 18 | ); 19 | return props; 20 | } 21 | } 22 | 23 | export const componentThemesPlugin = new ComponentThemesPlugin(); 24 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/plugins/fallback.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | import { getPublicUrl } from '@sitecore-jss/sitecore-jss-nextjs/utils'; 4 | 5 | /** 6 | * This config will set fallback values for properties that were left empty 7 | * If neither env, nor other places had a proper value, this will ensure a fallback is set 8 | */ 9 | class FallbackPlugin implements ConfigPlugin { 10 | // should always come last 11 | order = 100; 12 | 13 | async exec(config: JssConfig) { 14 | return Object.assign({}, config, { 15 | defaultLanguage: config.defaultLanguage || 'en', 16 | layoutServiceConfigurationName: config.layoutServiceConfigurationName || 'default', 17 | publicUrl: config.publicUrl || getPublicUrl(), 18 | }); 19 | } 20 | } 21 | 22 | export const fallbackPlugin = new FallbackPlugin(); 23 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/Navigation.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import config from 'temp/config'; 3 | 4 | // Prefix public assets with a public URL to enable compatibility with Sitecore editors. 5 | // If you're not supporting Sitecore editors, you can remove this. 6 | const publicUrl = config.publicUrl; 7 | 8 | const Navigation = (): JSX.Element => ( 9 |
10 | 25 |
26 | ); 27 | 28 | export default Navigation; 29 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/navigation/_navigation-sidebar.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .navigation.navigation-sidebar { 5 | a { 6 | text-decoration: none; 7 | } 8 | nav>ul { 9 | .rel-level1 { 10 | >.navigation-title { 11 | margin-bottom: 0; 12 | >a { 13 | padding: 5px 10px; 14 | display: block; 15 | position: relative; 16 | z-index: 1; 17 | margin-right: 0; 18 | } 19 | } 20 | >ul { 21 | margin-left: $small-margin; 22 | margin-top: $extrasmall-margin; 23 | } 24 | } 25 | .rel-level2 { 26 | display: block; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/navigation/_navigation-sidebar.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .navigation.navigation-sidebar { 5 | a { 6 | text-decoration: none; 7 | } 8 | nav>ul { 9 | .rel-level1 { 10 | >.navigation-title { 11 | margin-bottom: 0; 12 | >a { 13 | padding: 5px 10px; 14 | display: block; 15 | position: relative; 16 | z-index: 1; 17 | margin-right: 0; 18 | } 19 | } 20 | >ul { 21 | margin-left: $small-margin; 22 | margin-top: $extrasmall-margin; 23 | } 24 | } 25 | .rel-level2 { 26 | display: block; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | import { handleEditorAnchors } from '@sitecore-jss/sitecore-jss-angular'; 7 | 8 | if (environment.production) { 9 | enableProdMode(); 10 | } 11 | 12 | // Waiting for DOMContentLoaded is a temporary workaround to get TransferState working in the client 13 | // See https://github.com/angular/angular/issues/20484 for further info. 14 | document.addEventListener('DOMContentLoaded', () => { 15 | platformBrowserDynamic() 16 | .bootstrapModule(AppModule) 17 | .catch(err => console.log(err)); 18 | 19 | // allows Experience Editor anchor tag's onclick events to properly propagate 20 | handleEditorAnchors(); 21 | }); 22 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/generate-metadata.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { Metadata, getMetadata } from '@sitecore-jss/sitecore-jss-dev-tools'; 4 | 5 | /* 6 | METADATA GENERATION 7 | Generates the /src/temp/metadata.json file which contains application 8 | configuration metadata that is used for Sitecore XM Cloud integration. 9 | */ 10 | generateMetadata(); 11 | 12 | function generateMetadata(): void { 13 | const metadata: Metadata = getMetadata(); 14 | writeMetadata(metadata); 15 | } 16 | 17 | /** 18 | * Writes the metadata object to disk. 19 | * @param {Metadata} metadata metadata to write. 20 | */ 21 | function writeMetadata(metadata: Metadata): void { 22 | const filePath = path.resolve('src/temp/metadata.json'); 23 | console.log(`Writing metadata to ${filePath}`); 24 | fs.writeFileSync(filePath, JSON.stringify(metadata, null, 2), { encoding: 'utf8' }); 25 | } 26 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/next-config/plugins/cors-header.js: -------------------------------------------------------------------------------- 1 | const config = require('../../../temp/config'); 2 | 3 | /** 4 | * @param {import('next').NextConfig} nextConfig 5 | */ 6 | const corsHeaderPlugin = (nextConfig = {}) => { 7 | if (!config.sitecoreApiHost) { 8 | return nextConfig; 9 | } 10 | return Object.assign({}, nextConfig, { 11 | async headers() { 12 | const extendHeaders = 13 | typeof nextConfig.headers === 'function' ? await nextConfig.headers() : []; 14 | return [ 15 | ...(await extendHeaders), 16 | { 17 | source: '/_next/:path*', 18 | headers: [ 19 | { 20 | key: 'Access-Control-Allow-Origin', 21 | value: config.sitecoreApiHost.replace(/\/$/, ''), 22 | }, 23 | ], 24 | }, 25 | ]; 26 | }, 27 | }); 28 | }; 29 | 30 | module.exports = corsHeaderPlugin; 31 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # sitecore 4 | scjssconfig.json 5 | *.deploysecret.config 6 | 7 | # compiled output 8 | /dist 9 | /dist-server 10 | /tmp 11 | /out-tsc 12 | /.angular 13 | 14 | # dependencies 15 | /node_modules 16 | 17 | # local env files 18 | .env.local 19 | .env.*.local 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json 36 | 37 | # misc 38 | /.sass-cache 39 | /connect.lock 40 | /coverage 41 | /libpeerconnection.log 42 | npm-debug.log 43 | testem.log 44 | /typings 45 | 46 | # e2e 47 | /e2e/*.js 48 | /e2e/*.map 49 | 50 | # System Files 51 | .DS_Store 52 | Thumbs.db 53 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/site-resolver/index.ts: -------------------------------------------------------------------------------- 1 | import { SiteInfo, SiteResolver } from '@sitecore-jss/sitecore-jss-nextjs/site'; 2 | import * as plugins from 'temp/site-resolver-plugins'; 3 | 4 | /* 5 | The site resolver stores site information and is used in the app 6 | whenever site lookup is required (e.g. by name in page props factory 7 | or by host in Next.js middleware). 8 | 9 | By default, the app is single-site (one JSS app per Sitecore site). 10 | However, multi-site is available with the `nextjs-multisite` add-on. 11 | */ 12 | 13 | export interface SiteResolverPlugin { 14 | /** 15 | * A function which will be called during sites collection 16 | */ 17 | exec(sites: SiteInfo[]): SiteInfo[]; 18 | } 19 | 20 | const sites = (Object.values(plugins) as SiteResolverPlugin[]).reduce( 21 | (sites, plugin) => plugin.exec(sites), 22 | [] 23 | ); 24 | 25 | export const siteResolver = new SiteResolver(sites); 26 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/api/robots.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from 'next'; 2 | import { GraphQLRobotsService } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | import { siteResolver } from 'lib/site-resolver'; 4 | import clientFactory from 'lib/graphql-client-factory'; 5 | 6 | const robotsApi = async (req: NextApiRequest, res: NextApiResponse): Promise => { 7 | res.setHeader('Content-Type', 'text/plain'); 8 | 9 | // Resolve site based on hostname 10 | const hostName = req.headers['host']?.split(':')[0] || 'localhost'; 11 | const site = siteResolver.getByHost(hostName); 12 | 13 | // create robots graphql service 14 | const robotsService = new GraphQLRobotsService({ 15 | clientFactory, 16 | siteName: site.name, 17 | }); 18 | 19 | const robotsResult = await robotsService.fetchRobots(); 20 | 21 | return res.status(200).send(robotsResult); 22 | }; 23 | 24 | export default robotsApi; 25 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/generate-metadata.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { Metadata, getMetadata } from '@sitecore-jss/sitecore-jss-dev-tools'; 4 | 5 | /* 6 | METADATA GENERATION 7 | Generates the /src/environments/metadata.json file which contains application 8 | configuration metadata that is used for Sitecore XM Cloud integration. 9 | */ 10 | generateMetadata(); 11 | 12 | function generateMetadata(): void { 13 | const metadata: Metadata = getMetadata(); 14 | writeMetadata(metadata); 15 | } 16 | 17 | /** 18 | * Writes the metadata object to disk. 19 | * @param {Metadata} metadata metadata to write. 20 | */ 21 | function writeMetadata(metadata: Metadata): void { 22 | const filePath = path.resolve('src/environments/metadata.json'); 23 | console.log(`Writing metadata to ${filePath}`); 24 | fs.writeFileSync(filePath, JSON.stringify(metadata, null, 2), { encoding: 'utf8' }); 25 | } 26 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/generate-component-builder/plugins/packages.ts: -------------------------------------------------------------------------------- 1 | import { ComponentBuilderPlugin, ComponentBuilderPluginConfig } from '..'; 2 | 3 | /** 4 | * Provides custom packages configuration 5 | */ 6 | class PackagesPlugin implements ComponentBuilderPlugin { 7 | order = 0; 8 | 9 | exec(config: ComponentBuilderPluginConfig) { 10 | /** 11 | * You can specify components which you want to import from external/internal packages 12 | * in format: 13 | * { 14 | * name: 'package name', 15 | * components: [ 16 | * { 17 | * componentName: 'component name', // component rendering name, 18 | * moduleName: 'module name' // component name to import from the package 19 | * } 20 | * ] 21 | * } 22 | */ 23 | config.packages = []; 24 | 25 | return config; 26 | } 27 | } 28 | 29 | export const packagesPlugin = new PackagesPlugin(); 30 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/next-config/plugins/component-props.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {import('next').NextConfig} nextConfig 3 | */ 4 | const componentPropsPlugin = (nextConfig = {}) => { 5 | return Object.assign({}, nextConfig, { 6 | webpack: (config, options) => { 7 | 8 | if (!options.isServer) { 9 | // Add a loader to strip out getServerSideProps and getStaticProps from components in the client bundle 10 | config.module.rules.unshift({ 11 | test: /src\\components\\.*\.tsx$/, 12 | use: ['@sitecore-jss\\sitecore-jss-dev-tools\\nextjs-component-props-loader'], 13 | }); 14 | } 15 | 16 | // Overload the Webpack config if it was already overloaded 17 | if (typeof nextConfig.webpack === 'function') { 18 | return nextConfig.webpack(config, options); 19 | } 20 | 21 | return config; 22 | }, 23 | }); 24 | }; 25 | 26 | module.exports = componentPropsPlugin; 27 | -------------------------------------------------------------------------------- /sitecore.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./.sitecore/schemas/RootConfigurationFile.schema.json", 3 | "modules": [ 4 | "authoring/items/**/*.module.json" 5 | ], 6 | "plugins": [ 7 | "Sitecore.DevEx.Extensibility.Serialization@6.0.23", 8 | "Sitecore.DevEx.Extensibility.Publishing@6.0.23", 9 | "Sitecore.DevEx.Extensibility.Indexing@6.0.23", 10 | "Sitecore.DevEx.Extensibility.ResourcePackage@6.0.23", 11 | "Sitecore.DevEx.Extensibility.XMCloud@1.1.120" 12 | ], 13 | "serialization": { 14 | "defaultMaxRelativeItemPathLength": 100, 15 | "defaultModuleRelativeSerializationPath": "items", 16 | "removeOrphansForRoles": true, 17 | "removeOrphansForUsers": true, 18 | "continueOnItemFailure": false, 19 | "excludedFields": [] 20 | }, 21 | "settings": { 22 | "telemetryEnabled": false, 23 | "cacheAuthenticationToken": true, 24 | "versionComparisonEnabled": true, 25 | "apiClientTimeoutInMinutes": 5 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": [ 4 | "next", 5 | "next/core-web-vitals", 6 | "plugin:@typescript-eslint/recommended", 7 | "prettier", 8 | "plugin:yaml/recommended", 9 | "plugin:prettier/recommended" 10 | ], 11 | "plugins": [ 12 | "@typescript-eslint", 13 | "prettier", 14 | "yaml", 15 | "react" 16 | ], 17 | "ignorePatterns": [".generated/**/*", "**/*.d.ts", "**/*.js"], 18 | "rules": { 19 | "@next/next/no-img-element": "off", // Don't force next/image 20 | "jsx-a11y/alt-text": ["warn", { "elements": ["img"] }], // Don't force alt for (sourced from Sitecore media) 21 | "no-unused-vars": "off", 22 | "@typescript-eslint/no-unused-vars": [ 23 | "error", 24 | { 25 | "caughtErrorsIgnorePattern": "." 26 | } 27 | ], 28 | "@typescript-eslint/no-explicit-any": "error", 29 | "jsx-quotes": ["error", "prefer-double"] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/components/ContentBlock.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import { Text, RichText, Field, withDatasourceCheck } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | import { ComponentProps } from 'lib/component-props'; 4 | 5 | type ContentBlockProps = ComponentProps & { 6 | fields: { 7 | heading: Field; 8 | content: Field; 9 | }; 10 | }; 11 | 12 | /** 13 | * A simple Content Block component, with a heading and rich text block. 14 | * This is the most basic building block of a content site, and the most basic 15 | * JSS component that's useful. 16 | */ 17 | const ContentBlock = ({ fields }: ContentBlockProps): JSX.Element => ( 18 |
19 | 20 | 21 | 22 |
23 | ); 24 | 25 | export default withDatasourceCheck()(ContentBlock); 26 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy } from '@angular/core'; 2 | import { TranslateService } from '@ngx-translate/core'; 3 | import { JssContextService } from './jss-context.service'; 4 | import { Subscription } from 'rxjs'; 5 | 6 | @Component({ 7 | selector: 'app-root', 8 | templateUrl: './app.component.html' 9 | }) 10 | export class AppComponent implements OnDestroy { 11 | private contextSubscription: Subscription; 12 | 13 | constructor( 14 | translate: TranslateService, 15 | jssContextService: JssContextService, 16 | ) { 17 | this.contextSubscription = jssContextService.state.subscribe(jssState => { 18 | // listen for language changes 19 | if (jssState.language) { 20 | translate.use(jssState.language); 21 | } 22 | }); 23 | } 24 | 25 | ngOnDestroy() { 26 | if (this.contextSubscription) { 27 | this.contextSubscription.unsubscribe(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/scaffold-component/plugins/next-steps-byoc.ts: -------------------------------------------------------------------------------- 1 | import { ScaffoldComponentPlugin, ScaffoldComponentPluginConfig } from '..'; 2 | 3 | /** 4 | * Set next steps for BYOC component. 5 | */ 6 | class NextStepsByocPlugin implements ScaffoldComponentPlugin { 7 | order = 101; 8 | 9 | exec(config: ScaffoldComponentPluginConfig) { 10 | if (config.args.includes('--byoc')) { 11 | const { componentOutputPath } = config; 12 | 13 | config.nextSteps.push( 14 | `* Modify component registration through FEAAS.External.registerComponent if needed` 15 | ); 16 | if (!(componentOutputPath as string).includes('src\\components')) { 17 | config.nextSteps.push( 18 | `* Ensure component availability by importing it in your app through src\\byoc or registering it in scripts\\generate-component-builder` 19 | ); 20 | } 21 | } 22 | 23 | return config; 24 | } 25 | } 26 | 27 | export const nextStepsByocPlugin = new NextStepsByocPlugin(); 28 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/api/editing/data/[key].ts: -------------------------------------------------------------------------------- 1 | import { EditingDataMiddleware } from '@sitecore-jss/sitecore-jss-nextjs/editing'; 2 | /** 3 | * This Next.js API route is used to handle Sitecore editor data storage and retrieval by key 4 | * on serverless deployment architectures (e.g. Vercel) via the `ServerlessEditingDataService`. 5 | * 6 | * The `EditingDataMiddleware` expects this dynamic route name to be '[key]' by default, but can 7 | * be configured to use something else with the `dynamicRouteKey` option. 8 | */ 9 | 10 | // Bump body size limit (1mb by default) and disable response limit for Sitecore editor payloads 11 | // See https://nextjs.org/docs/api-routes/request-helpers#custom-config 12 | export const config = { 13 | api: { 14 | bodyParser: { 15 | sizeLimit: '2mb', 16 | }, 17 | responseLimit: false, 18 | }, 19 | }; 20 | 21 | // Wire up the EditingDataMiddleware handler 22 | const handler = new EditingDataMiddleware().getHandler(); 23 | 24 | export default handler; 25 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/config/plugins/scjssconfig.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | 4 | /** 5 | * This plugin will set config props based on scjssconfig.json. 6 | * scjssconfig.json may not exist if you've never run `jss setup` (development) 7 | * or are depending on environment variables instead (production). 8 | */ 9 | class ScJssConfigPlugin implements ConfigPlugin { 10 | order = 1; 11 | 12 | async exec(config: JssConfig) { 13 | let scJssConfig; 14 | try { 15 | scJssConfig = require('scjssconfig.json'); 16 | } catch (e) { 17 | return config; 18 | } 19 | 20 | if (!scJssConfig) return config; 21 | 22 | return Object.assign({}, config, { 23 | sitecoreApiKey: config.sitecoreApiKey || scJssConfig.sitecore?.apiKey, 24 | sitecoreApiHost: config.sitecoreApiHost || scJssConfig.sitecore?.layoutServiceHost, 25 | }); 26 | } 27 | } 28 | 29 | export const scjssconfigPlugin = new ScJssConfigPlugin(); 30 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/scaffold-component/plugins/next-steps.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | import { ScaffoldComponentPlugin, ScaffoldComponentPluginConfig } from '..'; 3 | 4 | /** 5 | * Set next steps. 6 | */ 7 | class NextStepsPlugin implements ScaffoldComponentPlugin { 8 | order = 100; 9 | 10 | exec(config: ScaffoldComponentPluginConfig) { 11 | const { componentOutputPath, componentName } = config; 12 | 13 | if (componentOutputPath) { 14 | config.nextSteps.push( 15 | `* Implement the React component in ${chalk.green(componentOutputPath)}` 16 | ); 17 | } 18 | if (!(componentOutputPath as string).includes('src\\components')) { 19 | config.nextSteps.push( 20 | `* ${chalk.green( 21 | componentName 22 | )} has been created outside src\\components. Ensure it is registered via scripts\\generate-component-builder.` 23 | ); 24 | } 25 | 26 | return config; 27 | } 28 | } 29 | 30 | export const nextStepsPlugin = new NextStepsPlugin(); 31 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/scaffold-component/plugins/component.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { scaffoldFile } from '@sitecore-jss/sitecore-jss-dev-tools'; 3 | import { ScaffoldComponentPlugin, ScaffoldComponentPluginConfig } from '..'; 4 | 5 | /** 6 | * Generates the component file. 7 | */ 8 | class ComponentPlugin implements ScaffoldComponentPlugin { 9 | order = 99; 10 | 11 | exec(config: ScaffoldComponentPluginConfig) { 12 | const { componentName, componentPath } = config; 13 | const filename = `${componentName}.tsx`; 14 | const componentRoot = componentPath.startsWith('src/') ? '' : 'src/components'; 15 | const outputFilePath = path.join(componentRoot, componentPath, filename); 16 | const template = config.componentTemplateGenerator(componentName); 17 | 18 | const componentOutputPath = scaffoldFile(outputFilePath, template); 19 | 20 | return { 21 | ...config, 22 | componentOutputPath, 23 | }; 24 | } 25 | } 26 | 27 | export const componentPlugin = new ComponentPlugin(); 28 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/templates/component-src.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Generates React boilerplate for a component under `src/components` 3 | * @param componentName - the component name 4 | * @returns component src boilerplate as a string 5 | */ 6 | function generateComponentSrc(componentName: string): string { 7 | return `import { JSX } from 'react'; 8 | import { ComponentParams, ComponentRendering } from '@sitecore-jss/sitecore-jss-nextjs'; 9 | 10 | interface ${componentName}Props { 11 | rendering: ComponentRendering & { params: ComponentParams }; 12 | params: ComponentParams; 13 | } 14 | 15 | export const Default = (props: ${componentName}Props): JSX.Element => { 16 | const id = props.params.RenderingIdentifier; 17 | 18 | return ( 19 |
20 |
21 |

${componentName} Component

22 |
23 |
24 | ); 25 | }; 26 | `; 27 | } 28 | 29 | export default generateComponentSrc; 30 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import type { AppProps } from 'next/app'; 3 | import { I18nProvider } from 'next-localization'; 4 | import { SitecorePageProps } from 'lib/page-props'; 5 | import Bootstrap from 'src/Bootstrap'; 6 | 7 | import 'assets/main.scss'; 8 | 9 | function App({ Component, pageProps }: AppProps): JSX.Element { 10 | const { dictionary, ...rest } = pageProps; 11 | 12 | return ( 13 | <> 14 | 15 | {/* 16 | // Use the next-localization (w/ rosetta) library to provide our translation dictionary to the app. 17 | // Note Next.js does not (currently) provide anything for translation, only i18n routing. 18 | // If your app is not multilingual, next-localization and references to it can be removed. 19 | */} 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | 27 | export default App; 28 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_component.scss: -------------------------------------------------------------------------------- 1 | .component-content { 2 | @include respond-to(mobile-large) { 3 | .row { 4 | padding: 0; 5 | margin: 0; 6 | } 7 | } 8 | } 9 | @include respond-to(mobile-large) { 10 | .row { 11 | margin: 0; 12 | padding: 0; 13 | > * { 14 | padding: 0; 15 | margin: 0; 16 | } 17 | } 18 | } 19 | 20 | .hero-banner { 21 | .component-content { 22 | background-position: center; 23 | background-repeat: no-repeat; 24 | background-size: cover; 25 | height: 800px; 26 | 27 | @include respond-to(mobile-large) { 28 | height: 300px; 29 | } 30 | } 31 | .sc-image-wrapper { 32 | opacity: 0; 33 | } 34 | &.scEnabledChrome { 35 | &.hero-banner-empty { 36 | .sc-image-wrapper { 37 | display: block; 38 | width: 100%; 39 | 40 | .scEmptyImage { 41 | max-height: 800px; 42 | max-width: 100%; 43 | width: 100%; 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_component.scss: -------------------------------------------------------------------------------- 1 | .component-content { 2 | @include respond-to(mobile-large) { 3 | .row { 4 | padding: 0; 5 | margin: 0; 6 | } 7 | } 8 | } 9 | @include respond-to(mobile-large) { 10 | .row { 11 | margin: 0; 12 | padding: 0; 13 | > * { 14 | padding: 0; 15 | margin: 0; 16 | } 17 | } 18 | } 19 | 20 | .hero-banner { 21 | .component-content { 22 | background-position: center; 23 | background-repeat: no-repeat; 24 | background-size: cover; 25 | height: 800px; 26 | 27 | @include respond-to(mobile-large) { 28 | height: 300px; 29 | } 30 | } 31 | .sc-image-wrapper { 32 | opacity: 0; 33 | } 34 | &.scEnabledChrome { 35 | &.hero-banner-empty { 36 | .sc-image-wrapper { 37 | display: block; 38 | width: 100%; 39 | 40 | .scEmptyImage { 41 | max-height: 800px; 42 | max-width: 100%; 43 | width: 100%; 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /authoring/Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 1.* 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/sitemap-fetcher/index.ts: -------------------------------------------------------------------------------- 1 | import { GetStaticPathsContext } from 'next'; 2 | import { StaticPath } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | import * as plugins from 'temp/sitemap-fetcher-plugins'; 4 | 5 | export interface SitemapFetcherPlugin { 6 | /** 7 | * A function which will be called during page props generation 8 | */ 9 | exec(context?: GetStaticPathsContext): Promise; 10 | } 11 | 12 | export class SitecoreSitemapFetcher { 13 | /** 14 | * Generates SitecoreSitemap for given mode (Export / Disconnected Export / SSG) 15 | * @param {GetStaticPathsContext} context 16 | */ 17 | async fetch(context?: GetStaticPathsContext): Promise { 18 | const pluginsList = Object.values(plugins) as SitemapFetcherPlugin[]; 19 | const pluginsResults = await Promise.all(pluginsList.map((plugin) => plugin.exec(context))); 20 | const results = pluginsResults.reduce((acc, cur) => [...acc, ...cur], []); 21 | return results; 22 | } 23 | } 24 | 25 | export const sitemapFetcher = new SitecoreSitemapFetcher(); 26 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/plugins/scjssconfig.ts: -------------------------------------------------------------------------------- 1 | import { JssConfig } from 'lib/config'; 2 | import { ConfigPlugin } from '..'; 3 | 4 | /** 5 | * This plugin will set config props based on scjssconfig.json. 6 | * scjssconfig.json may not exist if you've never run `jss setup` (development) 7 | * or are depending on environment variables instead (production). 8 | */ 9 | class ScJssConfigPlugin implements ConfigPlugin { 10 | order = 1; 11 | 12 | async exec(config: JssConfig) { 13 | let scJssConfig; 14 | try { 15 | // eslint-disable-next-line @typescript-eslint/no-require-imports 16 | scJssConfig = require('scjssconfig.json'); 17 | } catch (e) { 18 | return config; 19 | } 20 | 21 | if (!scJssConfig) return config; 22 | 23 | return Object.assign({}, config, { 24 | sitecoreApiKey: config.sitecoreApiKey || scJssConfig.sitecore?.apiKey, 25 | sitecoreApiHost: config.sitecoreApiHost || scJssConfig.sitecore?.layoutServiceHost, 26 | }); 27 | } 28 | } 29 | 30 | export const scjssconfigPlugin = new ScJssConfigPlugin(); 31 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/extract-path/index.ts: -------------------------------------------------------------------------------- 1 | import { ParsedUrlQuery } from 'querystring'; 2 | import * as plugins from 'temp/extract-path-plugins'; 3 | 4 | export interface Plugin { 5 | /** 6 | * A function which will be called during path extraction 7 | */ 8 | exec(path: string): string; 9 | } 10 | 11 | export class PathExtractor { 12 | /** 13 | * Extract normalized Sitecore item path 14 | * @param {ParsedUrlQuery} [params] 15 | */ 16 | public extract(params: ParsedUrlQuery | undefined): string { 17 | if (params === undefined) { 18 | return '/'; 19 | } 20 | let path = Array.isArray(params.path) ? params.path.join('/') : params.path ?? '/'; 21 | 22 | // Ensure leading '/' 23 | if (!path.startsWith('/')) { 24 | path = '/' + path; 25 | } 26 | 27 | const extractedPath = (Object.values(plugins) as Plugin[]).reduce( 28 | (resultPath, plugin) => plugin.exec(resultPath), 29 | path 30 | ); 31 | 32 | return extractedPath; 33 | } 34 | } 35 | 36 | export const pathExtractor = new PathExtractor(); 37 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/app-components.shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { TranslateModule } from '@ngx-translate/core'; 5 | import { RouterModule } from '@angular/router'; 6 | import { JssModule } from '@sitecore-jss/sitecore-jss-angular'; 7 | import { NavigationItemComponent } from './navigation/navigation-item.component'; 8 | 9 | /* 10 | This module is imported by the generated app-components.module.ts. 11 | You can use this module to provide shared Angular components that are not 12 | JSS components, etc to the generated module. 13 | 14 | Don't want code generation? See ./.gitignore for instructions to turn it off. 15 | */ 16 | @NgModule({ 17 | imports: [CommonModule, TranslateModule, RouterModule, JssModule, FormsModule], 18 | exports: [CommonModule, TranslateModule, RouterModule, FormsModule, NavigationItemComponent], 19 | declarations: [NavigationItemComponent], 20 | }) 21 | export class AppComponentsSharedModule {} 22 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/install-pre-push-hook.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { promisify } from 'util'; 4 | import { exec } from 'child_process'; 5 | import chalk from 'chalk'; 6 | 7 | const installHooks = async () => { 8 | try { 9 | const appPath = path.join(__dirname, '..').replace(/\\/g, '/'); 10 | const { stdout } = await promisify(exec)('git rev-parse --show-toplevel'); 11 | const gitRootPath = stdout.trim(); 12 | console.log(chalk.green(`Writing data to local .git folder ${gitRootPath}...`)); 13 | 14 | const data = `#!/bin/sh 15 | # 16 | # pre-push hook runs our linter before we push our changes 17 | # 18 | # To skip this hook, use the --no-verify flag 19 | # when pushing. 20 | # 21 | echo "Running lint check..." 22 | cd ${appPath} 23 | npm run lint`; 24 | 25 | await promisify(fs.writeFile)(`${gitRootPath}/.git/hooks/pre-push`, data, 'utf8'); 26 | console.log(chalk.green('Success')); 27 | } catch (error) { 28 | console.log(chalk.red(`Error installing hook: ${error}`)); 29 | } 30 | }; 31 | 32 | installHooks(); 33 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/_error.tsx: -------------------------------------------------------------------------------- 1 | import { NextPage } from 'next'; 2 | import Head from 'next/head'; 3 | 4 | interface ErrorPageProps { 5 | statusCode?: number | null | undefined; 6 | } 7 | 8 | /** 9 | * Rendered for 500 errors on both server and client. Used only in Production mode. 10 | * @link https://nextjs.org/docs/advanced-features/custom-error-page#more-advanced-error-page-customizing 11 | */ 12 | const ErrorPage: NextPage = ({ statusCode }) => ( 13 | <> 14 | 15 | Error 16 | 17 |
18 |

An error occurred

19 |

20 | {statusCode 21 | ? `A server-side ${statusCode} error occurred.` 22 | : 'A client-side error occurred.'} 23 |

24 | Go to the Home page 25 |
26 | 27 | ); 28 | 29 | ErrorPage.getInitialProps = ({ res, err }) => { 30 | const statusCode = res ? res.statusCode : err ? err.statusCode : 404; 31 | 32 | return { statusCode }; 33 | }; 34 | 35 | export default ErrorPage; 36 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/index.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-require-imports 2 | const plugins = require('scripts/temp/config-plugins'); 3 | import { JssConfig } from 'lib/config'; 4 | 5 | export interface ConfigPlugin { 6 | /** 7 | * Detect order when the plugin should be called, e.g. 0 - will be called first (can be a plugin which data is required for other plugins) 8 | */ 9 | order: number; 10 | /** 11 | * A function which will be called during config generation 12 | * @param {JssConfig} config Current (accumulated) config 13 | */ 14 | exec(config: JssConfig): Promise; 15 | } 16 | 17 | export class JssConfigFactory { 18 | public async create(defaultConfig: JssConfig = {}): Promise { 19 | return (Object.values(plugins) as ConfigPlugin[]) 20 | .sort((p1, p2) => p1.order - p2.order) 21 | .reduce( 22 | (promise, plugin) => promise.then((config) => plugin.exec(config)), 23 | Promise.resolve(defaultConfig) 24 | ); 25 | } 26 | } 27 | 28 | export const jssConfigFactory = new JssConfigFactory(); 29 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/config/index.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-var-requires 2 | const plugins = require('scripts/temp/config-plugins'); 3 | import { JssConfig } from 'lib/config'; 4 | 5 | export interface ConfigPlugin { 6 | /** 7 | * Detect order when the plugin should be called, e.g. 0 - will be called first (can be a plugin which data is required for other plugins) 8 | */ 9 | order: number; 10 | /** 11 | * A function which will be called during config generation 12 | * @param {JssConfig} config Current (accumulated) config 13 | */ 14 | exec(config: JssConfig): Promise; 15 | } 16 | 17 | export class JssConfigFactory { 18 | public async create(defaultConfig: JssConfig = {}): Promise { 19 | return (Object.values(plugins) as ConfigPlugin[]) 20 | .sort((p1, p2) => p1.order - p2.order) 21 | .reduce( 22 | (promise, plugin) => promise.then((config) => plugin.exec(config)), 23 | Promise.resolve(defaultConfig) 24 | ); 25 | } 26 | } 27 | 28 | export const jssConfigFactory = new JssConfigFactory(); 29 | -------------------------------------------------------------------------------- /local-containers/scripts/New-EdgeToken.ps1: -------------------------------------------------------------------------------- 1 | # parse the sitecore.json file for the XM Cloud plugin version 2 | [CmdletBinding(DefaultParameterSetName = 'FromArgs')] 3 | param ( 4 | [Parameter(Mandatory)] 5 | [string]$EnvironmentId 6 | ) 7 | 8 | $ErrorActionPreference = "Stop" 9 | 10 | $XmCloudDeployApi = (Get-Content "$PSScriptRoot\.sitecore\user.json" | ConvertFrom-Json).endpoints.xmCloud.host 11 | $XmCloudDeployAccessToken = (Get-Content "$PSScriptRoot\.sitecore\user.json" | ConvertFrom-Json).endpoints.xmCloud.accessToken 12 | 13 | $Headers = @{"Authorization" = "Bearer $XmCloudDeployAccessToken" } 14 | $URL = @( 15 | "$($XmCloudDeployApi)api/environments/v1" 16 | $EnvironmentId 17 | 'obtain-edge-token' 18 | ) 19 | 20 | $Response = Invoke-RestMethod ($URL -join '/') -Method 'GET' -Headers $Headers -Verbose 21 | $AccessToken = $Response.apiKey 22 | $EdgeUrl = "$($Response.edgeUrl)/api/graphql/ide" 23 | Write-Host "Launching Edge GraphQL IDE" 24 | Write-Host "Add { ""X-GQL-Token"" : ""$AccessToken"" } to the HTTP HEADERS tab at the bottom-left of the screen to write queries against your content" 25 | Start-Process $EdgeUrl 26 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/_component-promo.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .promo { 5 | background: $promo-bg; 6 | padding: 15px; 7 | overflow: hidden; 8 | box-sizing: border-box; 9 | >.component-content { 10 | position: relative; 11 | @include clearfix(); 12 | @include border-basic(all, $promo-border); 13 | 14 | >div { 15 | padding: 5px; 16 | } 17 | } 18 | .zg-height-fix { 19 | .field-promoicon { 20 | margin-top: 100px; 21 | } 22 | } 23 | .field-promoicon { 24 | overflow: hidden; 25 | width: 100%; 26 | img { 27 | width: 100%; 28 | height: auto; 29 | } 30 | } 31 | .field-promolink { 32 | margin-top: 5px; 33 | padding-bottom: 10px; 34 | } 35 | &.image-full-size { 36 | img { 37 | margin-bottom: 10px; 38 | } 39 | } 40 | @import "@sass/variants/promo"; 41 | @import "@sass/base/richtext/richtext"; 42 | } 43 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/generate-component-builder/plugins/components.ts: -------------------------------------------------------------------------------- 1 | import { ComponentBuilderPlugin, ComponentBuilderPluginConfig } from '..'; 2 | 3 | /** 4 | * Provides custom components configuration 5 | */ 6 | class ComponentsPlugin implements ComponentBuilderPlugin { 7 | order = 0; 8 | 9 | exec(config: ComponentBuilderPluginConfig) { 10 | /** 11 | * You can specify components which you want to import using custom path in format: 12 | * { 13 | * path: string; // path to component 14 | * moduleName: string; // module name to import 15 | * componentName: 'component name'; // component rendering name 16 | * } 17 | * 18 | * Or you can register all components from a path using the below approach: 19 | * import { getComponentList } from '@sitecore-jss/sitecore-jss-dev-tools'; 20 | * ... 21 | * const componentsPath = 'src/extra'; 22 | * config.components = getComponentList(componentsPath); 23 | */ 24 | config.components = []; 25 | 26 | return config; 27 | } 28 | } 29 | 30 | export const componentsPlugin = new ComponentsPlugin(); 31 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/generate-component-factory/plugins/packages.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactoryPlugin, ComponentFactoryPluginConfig } from '..'; 2 | 3 | /** 4 | * Provides custom packages configuration 5 | */ 6 | class PackagesPlugin implements ComponentFactoryPlugin { 7 | order = 0; 8 | 9 | exec(config: ComponentFactoryPluginConfig) { 10 | /** 11 | * You can specify components which you want to import from external/internal packages 12 | * in format: 13 | * { 14 | * name: 'package name', 15 | * components: [ 16 | * { 17 | * componentName: 'component name', // component rendering name, 18 | * moduleName: 'module name' // component name to import from the package 19 | * } 20 | * ] 21 | * } 22 | */ 23 | config.packages = [ 24 | { 25 | name: '@sitecore-jss/sitecore-jss-angular', 26 | components: [{ componentName: 'Form', moduleName: 'FormComponent' }], 27 | }, 28 | ]; 29 | 30 | return config; 31 | } 32 | } 33 | 34 | export const packagesPlugin = new PackagesPlugin(); 35 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/container/container.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { SxaComponent } from '../sxa.component'; 3 | 4 | @Component({ 5 | selector: 'app-container', 6 | templateUrl: './container.component.html', 7 | }) 8 | export class ContainerComponent extends SxaComponent implements OnInit { 9 | placeholderName: string; 10 | wrapped: boolean; 11 | 12 | override ngOnInit() { 13 | super.ngOnInit(); 14 | 15 | this.placeholderName = `container-${this.rendering.params?.DynamicPlaceholderId}`; 16 | this.wrapped = this.rendering.params?.Styles?.split(' ').includes('container'); 17 | } 18 | 19 | get backgroundStyle() { 20 | const backgroundImage = this.rendering.params?.BackgroundImage; 21 | const mediaUrlPattern = new RegExp(/mediaurl=\"([^"]*)\"/, 'i'); 22 | if (!backgroundImage || !backgroundImage.match(mediaUrlPattern)) { 23 | return {}; 24 | } 25 | const mediaUrl = backgroundImage.match(mediaUrlPattern)[1]; 26 | return { 27 | backgroundImage: `url('${mediaUrl}')`, 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/_component-promo.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .promo { 5 | background: $promo-bg; 6 | padding: 15px; 7 | overflow: hidden; 8 | box-sizing: border-box; 9 | >.component-content { 10 | position: relative; 11 | @include clearfix(); 12 | @include border-basic(all, $promo-border); 13 | 14 | >div { 15 | padding: 5px; 16 | } 17 | } 18 | .zg-height-fix { 19 | .field-promoicon { 20 | margin-top: 100px; 21 | } 22 | } 23 | .field-promoicon { 24 | overflow: hidden; 25 | width: 100%; 26 | img { 27 | width: 100%; 28 | height: auto; 29 | } 30 | } 31 | .field-promolink { 32 | margin-top: 5px; 33 | padding-bottom: 10px; 34 | } 35 | &.image-full-size { 36 | img { 37 | margin-bottom: 10px; 38 | } 39 | } 40 | @import "sass/variants/promo"; 41 | @import "sass/base/richtext/richtext"; 42 | } 43 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/lib/dictionary-service-factory.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DictionaryService, 3 | GraphQLDictionaryService, 4 | } from '@sitecore-jss/sitecore-jss-angular'; 5 | import { environment as env } from '../../environments/environment'; 6 | import clientFactory from './graphql-client-factory'; 7 | 8 | export class DictionaryServiceFactory { 9 | create(): DictionaryService { 10 | const service = 11 | new GraphQLDictionaryService({ 12 | clientFactory, 13 | siteName: env.sitecoreSiteName, 14 | useSiteQuery: true, 15 | /* 16 | The Dictionary Service needs a root item ID in order to fetch dictionary phrases for the current 17 | app. If your Sitecore instance only has 1 JSS App, you can specify the root item ID here; 18 | otherwise, the service will attempt to figure out the root item for the current JSS App using GraphQL and app name. 19 | rootItemId: '{GUID}' 20 | */ 21 | }); 22 | 23 | return service; 24 | } 25 | } 26 | 27 | export const dictionaryServiceFactory = new DictionaryServiceFactory(); 28 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_header.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars/colors"; 2 | @import "@sass/abstracts/mixins"; 3 | @import "variables"; 4 | 5 | .prod-mode { 6 | #header { 7 | display: flex; 8 | 9 | @include respond-to(mobile-large) { 10 | padding-bottom: 0; 11 | flex-direction: column-reverse; 12 | } 13 | } 14 | } 15 | 16 | header { 17 | #header { 18 | .bs-title { 19 | padding-left: 50px; 20 | 21 | h1 { 22 | font-size: $text-size-24; 23 | font-weight: 600; 24 | line-height: 18px; 25 | padding-top: 40px; 26 | margin: 0; 27 | } 28 | } 29 | 30 | @include respond-to(mobile-large) { 31 | padding-bottom: 0; 32 | padding-top: 0; 33 | flex-direction: column-reverse; 34 | 35 | .bs-title { 36 | padding-left: 0; 37 | text-align: center; 38 | margin-top: -5px; 39 | 40 | h1 { 41 | font-weight: 500; 42 | line-height: 29px; 43 | padding-top: 0; 44 | margin-bottom: 10px; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/page-props-factory/plugins/site.ts: -------------------------------------------------------------------------------- 1 | import { SitecorePageProps } from 'lib/page-props'; 2 | import { GetServerSidePropsContext, GetStaticPropsContext } from 'next'; 3 | import { getSiteRewriteData } from '@sitecore-jss/sitecore-jss-nextjs'; 4 | import { Plugin } from '..'; 5 | import { siteResolver } from 'lib/site-resolver'; 6 | import config from 'temp/config'; 7 | 8 | class SitePlugin implements Plugin { 9 | order = 0; 10 | 11 | async exec(props: SitecorePageProps, context: GetServerSidePropsContext | GetStaticPropsContext) { 12 | if (context.preview) return props; 13 | 14 | const path = 15 | context.params === undefined 16 | ? '/' 17 | : Array.isArray(context.params.path) 18 | ? context.params.path.join('/') 19 | : context.params.path ?? '/'; 20 | 21 | // Get site name (from path) 22 | const siteData = getSiteRewriteData(path, config.sitecoreSiteName); 23 | 24 | // Resolve site by name 25 | props.site = siteResolver.getByName(siteData.siteName); 26 | 27 | return props; 28 | } 29 | } 30 | 31 | export const sitePlugin = new SitePlugin(); 32 | -------------------------------------------------------------------------------- /authoring/platform/Platform.wpp.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/install-pre-push-hook.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | import { promisify } from 'util'; 4 | import { exec } from 'child_process'; 5 | 6 | const greenLog = '\x1b[32m%s\x1b[0m'; 7 | const redLog = '\x1b[31m%o\x1b[0m'; 8 | 9 | const installHooks = async () => { 10 | try { 11 | const appPath = path.join(__dirname, '..').replace(/\\/g, '/'); 12 | const { stdout } = await promisify(exec)('git rev-parse --show-toplevel'); 13 | const gitRootPath = stdout.trim(); 14 | console.log(greenLog, 'Writing data to local .git folder...'); 15 | 16 | const data = `#!/bin/sh 17 | # 18 | # pre-push hook runs our linter before we push our changes 19 | # 20 | # To skip this hook, use the --no-verify flag 21 | # when pushing. 22 | echo "Running lint check..." 23 | cd ${appPath} 24 | npm run lint 25 | # 26 | `; 27 | 28 | await promisify(fs.writeFile)(`${gitRootPath}/.git/hooks/pre-push`, data, 'utf8'); 29 | console.log(greenLog, 'Success!'); 30 | } catch (error) { 31 | console.log(redLog, `Error installing hook: ${error}`); 32 | } 33 | }; 34 | 35 | installHooks(); 36 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/navigation/navigation-item.component.html: -------------------------------------------------------------------------------- 1 |
  • 2 | 15 |
      16 | 22 |
    23 |
  • 24 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/i18n/jss-translation-client-loader.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, TransferState } from '@angular/core'; 2 | import { TranslateLoader } from '@ngx-translate/core'; 3 | import { DictionaryPhrases } from '@sitecore-jss/sitecore-jss-angular'; 4 | import { EMPTY, Observable, of } from 'rxjs'; 5 | import { JssTranslationLoaderService } from './jss-translation-loader.service'; 6 | import { dictionaryStateKey } from './jss-translation-server-loader.service'; 7 | 8 | @Injectable() 9 | export class JssTranslationClientLoaderService implements TranslateLoader { 10 | constructor( 11 | private fallbackLoader: JssTranslationLoaderService, 12 | private transferState: TransferState 13 | ) {} 14 | 15 | getTranslation(lang: string): Observable { 16 | const dictionary = this.transferState.get(dictionaryStateKey, null); 17 | 18 | if (dictionary) { 19 | return of(dictionary); 20 | } 21 | 22 | if (!this.fallbackLoader) { 23 | return EMPTY; 24 | } 25 | 26 | // likely invoking the JSS translation service here 27 | return this.fallbackLoader.getTranslation(lang); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/promo/_promo-hero.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .promo.promo-hero { 5 | position: relative; 6 | text-align: center; 7 | &.promo-hero-half { 8 | float: left; 9 | width: 50%; 10 | @include respond-to(all-mobile) { 11 | float: none; 12 | width: 100%; 13 | } 14 | } 15 | .field-promotext { 16 | display: inline-block; 17 | transform: translateY(-50%); 18 | position: absolute; 19 | top: 50%; 20 | left: 0; 21 | right: 0; 22 | padding: 20px; 23 | color: $promo-hero-text-color; 24 | background: $promo-bg-hero; 25 | >a { 26 | color: inherit; 27 | text-decoration: none; 28 | } 29 | @include respond-to(all-mobile) { 30 | width: 100%; 31 | margin: 0; 32 | h1 { 33 | @include font-size(2.4); 34 | } 35 | h2, h3, h4 { 36 | @include font-size(2.0); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/server.exports.ts: -------------------------------------------------------------------------------- 1 | import clientFactory from './src/app/lib/graphql-client-factory'; 2 | import { getGraphQLClientFactoryConfig } from './src/app/lib/graphql-client-factory/config'; 3 | import { dictionaryServiceFactory } from './src/app/lib/dictionary-service-factory'; 4 | import { layoutServiceFactory } from './src/app/lib/layout-service-factory'; 5 | import { environment } from './src/environments/environment'; 6 | import { components } from './src/app/components/app-components.module'; 7 | import metadata from './src/environments/metadata.json'; 8 | /** 9 | * Define the required configuration values to be exported from the server.bundle.ts. 10 | */ 11 | 12 | const defaultLanguage = environment.defaultLanguage; 13 | const sitecoreSiteName = environment.sitecoreSiteName; 14 | const personalizeScope = environment.personalizeScope; 15 | const getClientFactoryConfig = getGraphQLClientFactoryConfig; 16 | 17 | export { 18 | clientFactory, 19 | getClientFactoryConfig, 20 | dictionaryServiceFactory, 21 | layoutServiceFactory, 22 | defaultLanguage, 23 | sitecoreSiteName, 24 | personalizeScope, 25 | components, 26 | metadata, 27 | }; 28 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/row-splitter/row-splitter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { SxaComponent } from '../sxa.component'; 3 | 4 | @Component({ 5 | selector: 'app-row-splitter', 6 | templateUrl: './row-splitter.component.html', 7 | host: { 8 | "class": "component row-splitter", 9 | "[class]": "rowSplitterStyles", 10 | "[id]": "id" 11 | } 12 | }) 13 | export class RowSplitterComponent extends SxaComponent { 14 | get rowSplitterStyles(): string { 15 | return `${this.rendering.params.GridParameters ?? ''} ${this.rendering.params.Styles ?? 16 | ''}`.trimEnd(); 17 | } 18 | 19 | get rowStyles(): string[] { 20 | return Array.from({ length: 8 }, (_, i) => this.rendering.params[`Styles${i + 1}`]); 21 | } 22 | 23 | get enabledPlaceholders(): string[] { 24 | return this.rendering.params.EnabledPlaceholders.split(','); 25 | } 26 | 27 | getRowClass(index: number): string { 28 | const styleClass = this.rowStyles[index] || ''; 29 | return `${styleClass}`.trim(); 30 | } 31 | 32 | getPlaceholderName(ph: string): string { 33 | return `row-${ph}-{*}`; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/graphql-client-factory/create.ts: -------------------------------------------------------------------------------- 1 | import { 2 | GraphQLRequestClientFactoryConfig, 3 | GraphQLRequestClient, 4 | getEdgeProxyContentUrl, 5 | } from '@sitecore-jss/sitecore-jss-nextjs/graphql'; 6 | import { JssConfig } from 'lib/config'; 7 | 8 | /** 9 | * Creates a new GraphQLRequestClientFactory instance 10 | * @param config jss config 11 | * @returns GraphQLRequestClientFactory instance 12 | */ 13 | export const createGraphQLClientFactory = (config: JssConfig) => { 14 | let clientConfig: GraphQLRequestClientFactoryConfig; 15 | 16 | if (config.sitecoreEdgeContextId) { 17 | clientConfig = { 18 | endpoint: getEdgeProxyContentUrl(config.sitecoreEdgeContextId, config.sitecoreEdgeUrl), 19 | }; 20 | } else if (config.graphQLEndpoint && config.sitecoreApiKey) { 21 | clientConfig = { 22 | endpoint: config.graphQLEndpoint, 23 | apiKey: config.sitecoreApiKey, 24 | }; 25 | } else { 26 | throw new Error( 27 | 'Please configure either your sitecoreEdgeContextId, or your graphQLEndpoint and sitecoreApiKey.' 28 | ); 29 | } 30 | 31 | return GraphQLRequestClient.createClientFactory(clientConfig); 32 | }; 33 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | angularCli: { 23 | environment: 'dev' 24 | }, 25 | reporters: ['progress', 'kjhtml'], 26 | port: 9876, 27 | colors: true, 28 | logLevel: config.LOG_INFO, 29 | autoWatch: true, 30 | browsers: ['Chrome'], 31 | singleRun: false 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/promo/_promo-hero.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .promo.promo-hero { 5 | position: relative; 6 | text-align: center; 7 | &.promo-hero-half { 8 | float: left; 9 | width: 50%; 10 | @include respond-to(all-mobile) { 11 | float: none; 12 | width: 100%; 13 | } 14 | } 15 | .field-promotext { 16 | display: inline-block; 17 | transform: translateY(-50%); 18 | position: absolute; 19 | top: 50%; 20 | left: 0; 21 | right: 0; 22 | padding: 20px; 23 | color: $promo-hero-text-color; 24 | background: $promo-bg-hero; 25 | >a { 26 | color: inherit; 27 | text-decoration: none; 28 | } 29 | @include respond-to(all-mobile) { 30 | width: 100%; 31 | margin: 0; 32 | h1 { 33 | @include font-size(2.4); 34 | } 35 | h2, h3, h4 { 36 | @include font-size(2.0); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/plugins/edge-platform.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | import { constantCase } from 'constant-case'; 3 | import { JssConfig } from 'lib/config'; 4 | import { ConfigPlugin } from '..'; 5 | 6 | /** 7 | * This plugin will set config props used by the Sitecore Edge Platform. 8 | */ 9 | class EdgePlatformPlugin implements ConfigPlugin { 10 | order = 2; 11 | 12 | async exec(config: JssConfig) { 13 | const sitecoreEdgeUrl = 14 | process.env[`${constantCase('sitecoreEdgeUrl')}`]?.replace(/\/$/, '') || 15 | 'https://edge-platform.sitecorecloud.io'; 16 | const sitecoreEdgeContextId = process.env[`${constantCase('sitecoreEdgeContextId')}`]; 17 | 18 | if (config.sitecoreApiKey && sitecoreEdgeContextId) { 19 | console.log( 20 | chalk.yellow( 21 | "You have configured both 'sitecoreApiKey' and 'sitecoreEdgeContextId' values. The 'sitecoreEdgeContextId' is used instead." 22 | ) 23 | ); 24 | } 25 | 26 | return Object.assign({}, config, { 27 | sitecoreEdgeUrl, 28 | sitecoreEdgeContextId, 29 | }); 30 | } 31 | } 32 | 33 | export const edgePlatformPlugin = new EdgePlatformPlugin(); 34 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_header.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars/colors"; 2 | @import "sass/abstracts/mixins"; 3 | @import "variables"; 4 | 5 | .prod-mode { 6 | #header { 7 | display: flex; 8 | 9 | @include respond-to(mobile-large) { 10 | padding-bottom: 0; 11 | sc-placeholder { 12 | flex-direction: column-reverse; 13 | } 14 | } 15 | } 16 | } 17 | 18 | header { 19 | #header { 20 | .bs-title { 21 | padding-left: 50px; 22 | 23 | h1 { 24 | font-size: $text-size-24; 25 | font-weight: 600; 26 | line-height: 18px; 27 | padding-top: 40px; 28 | margin: 0; 29 | } 30 | } 31 | 32 | @include respond-to(mobile-large) { 33 | padding-bottom: 0; 34 | padding-top: 0; 35 | flex-direction: column-reverse; 36 | 37 | .bs-title { 38 | padding-left: 0; 39 | text-align: center; 40 | margin-top: -5px; 41 | 42 | h1 { 43 | font-weight: 500; 44 | line-height: 29px; 45 | padding-top: 0; 46 | margin-bottom: 10px; 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "components/*": ["src/components/*"], 6 | "lib/*": ["src/lib/*"], 7 | "temp/*": ["src/temp/*"], 8 | "assets/*": ["src/assets/*"], 9 | "react": ["node_modules/react"] 10 | }, 11 | "target": "es5", 12 | "types": ["node"], 13 | "lib": ["dom", "dom.iterable", "esnext"], 14 | "allowJs": true, 15 | "skipLibCheck": true, 16 | "strict": true, 17 | "strictFunctionTypes": false, 18 | "downlevelIteration": true, 19 | "noEmit": true, 20 | "esModuleInterop": true, 21 | "module": "esnext", 22 | "moduleResolution": "node", 23 | "resolveJsonModule": true, 24 | "isolatedModules": true, 25 | "jsx": "preserve", 26 | "allowSyntheticDefaultImports": true, 27 | "noImplicitReturns": true, 28 | "noImplicitAny": true, 29 | "noImplicitThis": true, 30 | "noUnusedLocals": true, 31 | "noUnusedParameters": true, 32 | "incremental": true, 33 | "forceConsistentCasingInFileNames": false 34 | }, 35 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 36 | "exclude": ["node_modules"] 37 | } 38 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/scripts/generate-plugins.ts: -------------------------------------------------------------------------------- 1 | import { 2 | generatePlugins, 3 | ModuleType, 4 | PluginDefinition, 5 | } from '@sitecore-jss/sitecore-jss-dev-tools'; 6 | 7 | /* 8 | PLUGINS GENERATION 9 | NOTE: pluginName: the name of the plugin in the src/lib folder 10 | Generates the `/src/temp/{pluginName}-plugins.ts` file, which exports list of plugins 11 | 12 | Generating the plugins is optional, and it can be maintained manually if preferred. 13 | 14 | The default convention uses the plugin's filename (without the extension) as the first part of the component 15 | name. For example, the file `/lib/page-props-factory/plugins/exampleName.ts` would map to plugin `exampleNamePlugin`. 16 | */ 17 | 18 | const pluginDefinitions: PluginDefinition[] = [ 19 | { 20 | distPath: 'scripts/temp/config-plugins.ts', 21 | rootPath: 'scripts/config/plugins', 22 | moduleType: ModuleType.ESM, 23 | }, 24 | { 25 | distPath: 'scripts/temp/generate-component-factory-plugins.ts', 26 | rootPath: 'scripts/generate-component-factory/plugins', 27 | moduleType: ModuleType.ESM, 28 | }, 29 | ]; 30 | 31 | pluginDefinitions.forEach((definition) => { 32 | generatePlugins(definition); 33 | }); 34 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/pages/feaas/render.tsx: -------------------------------------------------------------------------------- 1 | import { JSX } from 'react'; 2 | import { GetServerSideProps } from 'next'; 3 | import BYOC from 'src/byoc'; 4 | import * as FEAAS from '@sitecore-feaas/clientside/react'; 5 | 6 | /** 7 | * The FEAASRender page is responsible for: 8 | * - Rendering the FEAAS component if the "feaasSrc" is provided. 9 | * - Rendering all the registered components. 10 | * - The page is rendered only if it's requested by the api route (/api/editing/feaas/render) using the preview mode. 11 | */ 12 | const FEAASRender = ({ feaasSrc }: { feaasSrc: string }): JSX.Element => { 13 | return ( 14 | <> 15 | {/** Render the component if the "feaasSrc" is provided */} 16 | {feaasSrc && } 17 | {/** Render all the registered components */} 18 | 19 | 20 | ); 21 | }; 22 | 23 | export const getServerSideProps: GetServerSideProps = async (context) => { 24 | return { 25 | props: { 26 | feaasSrc: context.query.feaasSrc || null, 27 | }, 28 | // Don't show the page if it's not requested by the api route using the preview mode 29 | notFound: !context.preview, 30 | }; 31 | }; 32 | 33 | export default FEAASRender; 34 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/promo/_promo-shadow.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | 4 | .promo-shadow { 5 | max-width: 960px; 6 | padding: 0; 7 | border-top-width: 3px; 8 | border-top-color: $promo-shadow-border; 9 | border-style: solid; 10 | overflow: visible; 11 | position: relative; 12 | &.promo { 13 | float: left; 14 | } 15 | >.component-content { 16 | padding: 15px; 17 | margin: 0 0 30px 0; 18 | @include respond-to(all-mobile) { 19 | margin: 0 10px 30px 10px; 20 | } 21 | &:before, &:after { 22 | opacity: 0.7; 23 | box-shadow: 0 17px 10px rgba(0, 0, 0, 0.7); 24 | position: absolute; 25 | z-index: -1; 26 | height: 20%; 27 | max-height: 100px; 28 | max-width: 460px; 29 | width: 47%; 30 | content: ""; 31 | bottom: 10px; 32 | } 33 | &:before { 34 | left: 2%; 35 | transform: rotate(-3deg); 36 | } 37 | &:after { 38 | right: 2%; 39 | transform: rotate(3deg); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /xmcloud.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "renderingHosts": { 3 | "nextjsstarter": { 4 | "path": "./headapps/nextjs-starter", 5 | "nodeVersion": "22.11.0", 6 | "jssDeploymentSecret": "110F1C44A496B45478640DD36F80C18C9", 7 | "enabled": true, 8 | "type": "sxa", 9 | "buildCommand": "build", 10 | "runCommand": "next:start" 11 | }, 12 | "angularstarter": { 13 | "path": "./headapps/spa-starters", 14 | "nodeVersion": "22.11.0", 15 | "jssDeploymentSecret": "110F1C44A496B45478640DD36F80C18C9", 16 | "enabled": false, 17 | "type": "sxa", 18 | "buildCommand": "install-build:angular", 19 | "runCommand": "start:angular" 20 | } 21 | }, 22 | "postActions": { 23 | "actions":{ 24 | "warmUpCm": { 25 | "urls": [ 26 | "/sitecore/shell", 27 | "/sitecore/shell/Applications/Content%20Editor.aspx?sc_bw=1", 28 | "/sitecore/client/Applications/Launchpad" 29 | ] 30 | }, 31 | "populateSchema": { 32 | "indexNames": [] 33 | }, 34 | "reindex": { 35 | "indexNames": [] 36 | } 37 | } 38 | }, 39 | "authoringPath": "./authoring" 40 | } 41 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/routing/layout/layout.component.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 | 12 |
    13 |
    14 |
    15 | 20 |
    21 |
    22 |
    23 | 30 |
    31 |
    32 | 33 | 37 | 38 |
    39 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/sass/components/promo/_promo-shadow.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | 4 | .promo-shadow { 5 | max-width: 960px; 6 | padding: 0; 7 | border-top-width: 3px; 8 | border-top-color: $promo-shadow-border; 9 | border-style: solid; 10 | overflow: visible; 11 | position: relative; 12 | &.promo { 13 | float: left; 14 | } 15 | >.component-content { 16 | @include respond-to(all-mobile) { 17 | margin: 0 10px 30px 10px; 18 | } 19 | padding: 15px; 20 | margin: 0 0 30px 0; 21 | &:before, &:after { 22 | opacity: 0.7; 23 | box-shadow: 0 17px 10px rgba(0, 0, 0, 0.7); 24 | position: absolute; 25 | z-index: -1; 26 | height: 20%; 27 | max-height: 100px; 28 | max-width: 460px; 29 | width: 47%; 30 | content: ""; 31 | bottom: 10px; 32 | } 33 | &:before { 34 | left: 2%; 35 | transform: rotate(-3deg); 36 | } 37 | &:after { 38 | right: 2%; 39 | transform: rotate(3deg); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /local-containers/docker/build/cm/templates/modules_template/items/api-key/template.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ID: "" 3 | Parent: "59b41b5f-e22e-460b-941e-fb64fe8da8fc" 4 | Template: "a6868d65-d612-401f-a40a-cd5ba0857b81" 5 | Path: /sitecore/system/Settings/Services/API Keys/ 6 | SharedFields: 7 | - ID: "780c8e48-fe03-4a73-90dc-9bb5296b95d7" 8 | Hint: CORS Origins 9 | Value: * 10 | - ID: "99ba91ec-f0d3-4372-b638-67c2402a2484" 11 | Hint: AllowedControllers 12 | Value: * 13 | Languages: 14 | - Language: en 15 | Versions: 16 | - Version: 1 17 | Fields: 18 | - ID: "25bed78c-4957-4165-998a-ca1b52f67497" 19 | Hint: __Created 20 | Value: 20200526T202811Z 21 | - ID: "52807595-0f8f-4b20-8d2a-cb71d28c6103" 22 | Hint: __Owner 23 | Value: | 24 | sitecore\Admin 25 | - ID: "5dd74568-4d4b-44c1-b513-0af5f4cda34f" 26 | Hint: __Created by 27 | Value: | 28 | sitecore\Admin 29 | - ID: "8cdc337e-a112-42fb-bbb4-4143751e123f" 30 | Hint: __Revision 31 | Value: "2fb0590b-ba95-44c3-a2a7-de01c419d575" 32 | - ID: "badd9cf9-53e0-4d0c-bcc0-2d784c282f6a" 33 | Hint: __Updated by 34 | Value: | 35 | sitecore\Admin 36 | - ID: "d9cf14b1-fa16-4ba6-9288-e8a174d4d522" 37 | Hint: __Updated 38 | Value: 20200526T202815Z 39 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_container.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/mixins"; 2 | @import "variables"; 3 | 4 | body { 5 | font-family: Roboto; 6 | color: $main-color; 7 | } 8 | 9 | 10 | @media (min-width: 1400px) { 11 | .container { 12 | max-width: 1250px; 13 | } 14 | } 15 | 16 | main { 17 | .main-header { 18 | margin-top: 55px; 19 | margin-bottom: 30px; 20 | 21 | @include respond-to(mobile-large) { 22 | margin-bottom: 0; 23 | } 24 | 25 | h4 { 26 | font-size: $text-size-50; 27 | font-weight: 500; 28 | line-height: 70px; 29 | } 30 | } 31 | 32 | .main-news-header { 33 | margin-top: 60px; 34 | 35 | h2 { 36 | font-size: $text-size-36; 37 | line-height: 43px; 38 | } 39 | } 40 | 41 | @include respond-to(mobile-large) { 42 | padding-top: 0; 43 | margin-bottom: 0; 44 | 45 | .main-header { 46 | margin-top: 10px; 47 | 48 | h4 { 49 | font-size: $text-size-24; 50 | line-height: 32px; 51 | } 52 | } 53 | 54 | .main-news-header { 55 | padding-bottom: 35px; 56 | 57 | h2 { 58 | margin-top: 0; 59 | font-size: $text-size-18; 60 | line-height: 22px; 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_container.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/mixins"; 2 | @import "variables"; 3 | 4 | body { 5 | font-family: Roboto; 6 | color: $main-color; 7 | } 8 | 9 | 10 | @media (min-width: 1400px) { 11 | .container { 12 | max-width: 1250px; 13 | } 14 | } 15 | 16 | main { 17 | .main-header { 18 | margin-top: 55px; 19 | margin-bottom: 30px; 20 | 21 | @include respond-to(mobile-large) { 22 | margin-bottom: 0; 23 | } 24 | 25 | h4 { 26 | font-size: $text-size-50; 27 | font-weight: 500; 28 | line-height: 70px; 29 | } 30 | } 31 | 32 | .main-news-header { 33 | margin-top: 60px; 34 | 35 | h2 { 36 | font-size: $text-size-36; 37 | line-height: 43px; 38 | } 39 | } 40 | 41 | @include respond-to(mobile-large) { 42 | padding-top: 0; 43 | margin-bottom: 0; 44 | 45 | .main-header { 46 | margin-top: 10px; 47 | 48 | h4 { 49 | font-size: $text-size-24; 50 | line-height: 32px; 51 | } 52 | } 53 | 54 | .main-news-header { 55 | padding-bottom: 35px; 56 | 57 | h2 { 58 | margin-top: 0; 59 | font-size: $text-size-18; 60 | line-height: 22px; 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/sitemap-fetcher/plugins/graphql-sitemap-service.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MultisiteGraphQLSitemapService, 3 | StaticPath, 4 | constants, 5 | SiteInfo, 6 | } from '@sitecore-jss/sitecore-jss-nextjs'; 7 | import config from 'temp/config'; 8 | import { SitemapFetcherPlugin } from '..'; 9 | import { GetStaticPathsContext } from 'next'; 10 | import { siteResolver } from 'lib/site-resolver'; 11 | import clientFactory from 'lib/graphql-client-factory'; 12 | 13 | class GraphqlSitemapServicePlugin implements SitemapFetcherPlugin { 14 | _graphqlSitemapService: MultisiteGraphQLSitemapService; 15 | 16 | constructor() { 17 | this._graphqlSitemapService = new MultisiteGraphQLSitemapService({ 18 | clientFactory, 19 | sites: [...new Set(siteResolver.sites.map((site: SiteInfo) => site.name))], 20 | }); 21 | } 22 | 23 | async exec(context?: GetStaticPathsContext): Promise { 24 | if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) { 25 | return []; 26 | } 27 | return process.env.EXPORT_MODE 28 | ? this._graphqlSitemapService.fetchExportSitemap(config.defaultLanguage) 29 | : this._graphqlSitemapService.fetchSSGSitemap(context?.locales || []); 30 | } 31 | } 32 | 33 | export const graphqlSitemapServicePlugin = new GraphqlSitemapServicePlugin(); 34 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "importHelpers": true, 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "allowSyntheticDefaultImports": true, 11 | "experimentalDecorators": true, 12 | "resolveJsonModule": true, 13 | "skipLibCheck": true, 14 | "allowJs": true, 15 | "target": "es2022", 16 | "module": "es2022", 17 | "noImplicitAny": true, 18 | "noImplicitReturns": true, 19 | "noImplicitThis": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "newLine": "LF", 23 | "types": ["node"], 24 | // add additional type root in case of monorepo where dependencies are hoisted to root node_modules 25 | "typeRoots": ["node_modules/@types", "../node_modules/@types"], 26 | "lib": ["es2019", "dom", "esnext.asynciterable"], 27 | "paths": { 28 | "@angular/*": ["../node_modules/@angular/*"], 29 | "rxjs": ["node_modules/rxjs", "../node_modules/rxjs"], 30 | "lib/*": ["src/app/lib/*"], 31 | }, 32 | "baseUrl": "./", 33 | "esModuleInterop": true 34 | }, 35 | "ts-node": { 36 | "require": ["tsconfig-paths/register"] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/page-props-factory/plugins/personalize.ts: -------------------------------------------------------------------------------- 1 | import { GetServerSidePropsContext, GetStaticPropsContext } from 'next'; 2 | import { Plugin } from '..'; 3 | import { getPersonalizedRewriteData, personalizeLayout } from '@sitecore-jss/sitecore-jss-nextjs'; 4 | import { SitecorePageProps } from 'lib/page-props'; 5 | 6 | class PersonalizePlugin implements Plugin { 7 | order = 3; 8 | 9 | async exec(props: SitecorePageProps, context: GetServerSidePropsContext | GetStaticPropsContext) { 10 | if (context.preview) return props; 11 | 12 | const path = 13 | context.params === undefined 14 | ? '/' 15 | : Array.isArray(context.params.path) 16 | ? context.params.path.join('/') 17 | : context.params.path ?? '/'; 18 | 19 | // Get variant(s) for personalization (from path) 20 | const personalizeData = getPersonalizedRewriteData(path); 21 | 22 | // Modify layoutData to use specific variant(s) instead of default 23 | // This will also set the variantId on the Sitecore context so that it is accessible here 24 | personalizeLayout( 25 | props.layoutData, 26 | personalizeData.variantId, 27 | personalizeData.componentVariantIds 28 | ); 29 | 30 | return props; 31 | } 32 | } 33 | 34 | export const personalizePlugin = new PersonalizePlugin(); 35 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/common/_alignment.scss: -------------------------------------------------------------------------------- 1 | @import '~bootstrap/scss/functions'; 2 | @import '~bootstrap/scss/variables'; 3 | @import '~bootstrap/scss/mixins'; 4 | 5 | $breakpoints: sm, md, lg, xl, xxl; 6 | 7 | .position-left, 8 | .position-left * { 9 | text-align: left !important; 10 | } 11 | 12 | .position-right, 13 | .position-right * { 14 | text-align: right !important; 15 | } 16 | 17 | .position-center, 18 | .position-center * { 19 | text-align: center !important; 20 | } 21 | 22 | .position-left select { 23 | direction: ltr !important; 24 | } 25 | 26 | .position-right select { 27 | direction: rtl !important; 28 | } 29 | 30 | .position-center select { 31 | text-align-last: center !important; 32 | } 33 | 34 | @mixin auto-margins($breakpoint) { 35 | @include media-breakpoint-up(#{$breakpoint}) { 36 | .ms-#{$breakpoint}-auto { 37 | margin-left: auto !important; 38 | margin-right: 0 !important; 39 | } 40 | .me-#{$breakpoint}-auto { 41 | margin-right: auto !important; 42 | margin-left: 0 !important; 43 | } 44 | .mx-#{$breakpoint}-auto { 45 | margin-right: auto !important; 46 | margin-left: auto !important; 47 | } 48 | } 49 | } 50 | 51 | @each $breakpoint in $breakpoints { 52 | @include auto-margins($breakpoint); 53 | } 54 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/lib/middleware/index.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from 'next/server'; 2 | import type { NextFetchEvent, NextRequest } from 'next/server'; 3 | import { debug } from '@sitecore-jss/sitecore-jss-nextjs/middleware'; 4 | import * as plugins from 'temp/middleware-plugins'; 5 | 6 | export interface MiddlewarePlugin { 7 | /** 8 | * Detect order when the plugin should be called, e.g. 0 - will be called first (can be a plugin which data is required for other plugins) 9 | */ 10 | order: number; 11 | /** 12 | * A middleware to be called, it's required to return @type {NextResponse} for other middlewares 13 | */ 14 | exec(req: NextRequest, res?: NextResponse, ev?: NextFetchEvent): Promise; 15 | } 16 | 17 | export default async function middleware( 18 | req: NextRequest, 19 | ev: NextFetchEvent 20 | ): Promise { 21 | const response = NextResponse.next(); 22 | 23 | debug.common('next middleware start'); 24 | 25 | const start = Date.now(); 26 | 27 | const finalRes = await (Object.values(plugins) as MiddlewarePlugin[]) 28 | .sort((p1, p2) => p1.order - p2.order) 29 | .reduce((p, plugin) => p.then((res) => plugin.exec(req, res, ev)), Promise.resolve(response)); 30 | 31 | debug.common('next middleware end in %dms', Date.now() - start); 32 | 33 | return finalRes; 34 | } 35 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/scripts/config/plugins/multisite.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | import { GraphQLSiteInfoService, SiteInfo } from '@sitecore-jss/sitecore-jss-nextjs'; 3 | import { createGraphQLClientFactory } from 'lib/graphql-client-factory/create'; 4 | import { JssConfig } from 'lib/config'; 5 | import { ConfigPlugin } from '..'; 6 | 7 | /** 8 | * This plugin will set the "sites" config prop. 9 | * By default this will attempt to fetch site information directly from Sitecore (using the GraphQLSiteInfoService). 10 | * You could easily modify this to fetch from another source such as a static JSON file instead. 11 | */ 12 | class MultisitePlugin implements ConfigPlugin { 13 | order = 11; 14 | 15 | async exec(config: JssConfig) { 16 | let sites: SiteInfo[] = []; 17 | console.log('Fetching site information'); 18 | try { 19 | const siteInfoService = new GraphQLSiteInfoService({ 20 | clientFactory: createGraphQLClientFactory(config), 21 | }); 22 | sites = await siteInfoService.fetchSiteInfo(); 23 | } catch (error) { 24 | console.error(chalk.red('Error fetching site information')); 25 | console.error(error); 26 | } 27 | 28 | return Object.assign({}, config, { 29 | sites: JSON.stringify(sites), 30 | }); 31 | } 32 | } 33 | 34 | export const multisitePlugin = new MultisitePlugin(); 35 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/basic/_promo.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/vars"; 2 | @import "@sass/abstracts/mixins"; 3 | /**PROMO**/ 4 | 5 | .promo { 6 | &.main-promo-no-border { 7 | padding-left: 0; 8 | padding-right: 0; 9 | padding-bottom: 0; 10 | margin-bottom: 80px; 11 | 12 | @include respond-to(mobile-large) { 13 | margin-bottom: 0; 14 | } 15 | 16 | >.component-content { 17 | border: 0; 18 | max-width: 583px; 19 | margin-right: 50px; 20 | 21 | > div { 22 | padding-bottom: 0; 23 | } 24 | 25 | @include respond-to(mobile-large) { 26 | max-width: 100%; 27 | margin-right: 0; 28 | } 29 | 30 | .promo-text { 31 | .field-promotext { 32 | font-size: 14px; 33 | 34 | h3 { 35 | font-size: $text-size-18; 36 | margin: 15px 0; 37 | 38 | @include respond-to(mobile-large) { 39 | margin: 10px 0; 40 | } 41 | } 42 | p { 43 | margin: 10px 0; 44 | } 45 | } 46 | } 47 | @include respond-to(mobile-large) { 48 | > div { 49 | padding: 0; 50 | } 51 | 52 | .promo-text { 53 | padding: 15px 30px 5px 30px; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/assets/styles/basic/_promo.scss: -------------------------------------------------------------------------------- 1 | @import "sass/abstracts/vars"; 2 | @import "sass/abstracts/mixins"; 3 | /**PROMO**/ 4 | 5 | .promo { 6 | &.main-promo-no-border { 7 | padding-left: 0; 8 | padding-right: 0; 9 | padding-bottom: 0; 10 | margin-bottom: 80px; 11 | 12 | @include respond-to(mobile-large) { 13 | margin-bottom: 0; 14 | } 15 | 16 | >.component-content { 17 | border: 0; 18 | max-width: 583px; 19 | margin-right: 50px; 20 | 21 | > div { 22 | padding-bottom: 0; 23 | } 24 | 25 | @include respond-to(mobile-large) { 26 | max-width: 100%; 27 | margin-right: 0; 28 | } 29 | 30 | .promo-text { 31 | .field-promotext { 32 | font-size: 14px; 33 | 34 | h3 { 35 | font-size: $text-size-18; 36 | margin: 15px 0; 37 | 38 | @include respond-to(mobile-large) { 39 | margin: 10px 0; 40 | } 41 | } 42 | p { 43 | margin: 10px 0; 44 | } 45 | } 46 | } 47 | @include respond-to(mobile-large) { 48 | > div { 49 | padding: 0; 50 | } 51 | 52 | .promo-text { 53 | padding: 15px 30px 5px 30px; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting, 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 11 | declare const __karma__: { [key: string]: unknown; start: () => void }; 12 | declare const require: { 13 | [key: string]: unknown; 14 | context: ( 15 | directory: string, 16 | useSubdirectories: boolean, 17 | pattern: RegExp 18 | ) => { 19 | [key: string]: unknown; 20 | keys: () => { 21 | [key: string]: unknown; 22 | map: (context: { [key: string]: unknown }) => void; 23 | }; 24 | }; 25 | }; 26 | 27 | // Prevent Karma from running prematurely. 28 | __karma__.loaded = function() {}; 29 | 30 | // First, initialize the Angular testing environment. 31 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 32 | // Then we find all the tests. 33 | const context = require.context('./', true, /\.spec\.ts$/); 34 | // And load the modules. 35 | context.keys().map(context); 36 | // Finally, start Karma to run the tests. 37 | __karma__.start(); 38 | -------------------------------------------------------------------------------- /headapps/spa-starters/angular/src/app/components/page-content/page-content.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy, OnInit } from '@angular/core'; 2 | import { RichTextField } from '@sitecore-jss/sitecore-jss-angular'; 3 | import { JssContextService } from '../../jss-context.service'; 4 | import { SxaComponent } from './../sxa.component'; 5 | import { Subscription } from 'rxjs'; 6 | 7 | @Component({ 8 | selector: 'app-page-content', 9 | templateUrl: './page-content.component.html', 10 | host: { 11 | 'class': 'component content', 12 | '[class]': 'styles', 13 | '[id]': 'id', 14 | } 15 | }) 16 | export class PageContentComponent extends SxaComponent implements OnInit, OnDestroy { 17 | content?: RichTextField; 18 | contextContent?: RichTextField; 19 | private contextSubscription: Subscription; 20 | 21 | constructor(private jssContext: JssContextService) { 22 | super(); 23 | } 24 | ngOnInit() { 25 | super.ngOnInit(); 26 | 27 | this.content = this.rendering.fields?.Content as RichTextField; 28 | this.contextSubscription = this.jssContext.state.subscribe((newState) => { 29 | this.contextContent = 30 | newState.sitecore && (newState.sitecore.route.fields.Content as RichTextField); 31 | }); 32 | } 33 | 34 | ngOnDestroy() { 35 | if (this.contextSubscription) { 36 | this.contextSubscription.unsubscribe(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /headapps/nextjs-starter/src/assets/sass/components/_component-navigation.scss: -------------------------------------------------------------------------------- 1 | @import "@sass/abstracts/mixins"; 2 | @import "@sass/abstracts/vars"; 3 | 4 | .navigation { 5 | background: $nav-bg; 6 | ul { 7 | padding-left: 0; 8 | } 9 | .level0, .level1 { 10 | >.navigation-title>a { 11 | font-size: $navigation-font-basic; 12 | border-color: $nav-border-root; 13 | border-style: solid; 14 | border-width: 0 0 2px 0; 15 | padding-right: 10px; 16 | margin-right: 5px; 17 | &:hover { 18 | text-decoration: none; 19 | } 20 | } 21 | } 22 | a { 23 | color: $nav-color-root; 24 | .lt-ie9 &, .lt-ie9 & span { 25 | color: $nav-color-root; 26 | } 27 | &:focus, &:hover { 28 | color: $nav-color-root-active; 29 | } 30 | } 31 | li { 32 | &.submenu { 33 | margin-bottom: 0; 34 | } 35 | >.navigation-title { 36 | >a { 37 | padding: 3px 5px 3px 0; 38 | display: block; 39 | color: $nav-color-root; 40 | text-decoration: none; 41 | } 42 | } 43 | >ul a { 44 | font-size: $navigation-font-basic-submenu; 45 | } 46 | } 47 | .submenu>ul { 48 | padding-left: 10px; 49 | } 50 | } 51 | @import "@sass/components/navigation/"; 52 | --------------------------------------------------------------------------------