Add Angular 21 + Spartacus 221121.15.1 storefront with Contentstack CMS connector - #1
Conversation
… of a committed file
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
There was a problem hiding this comment.
Pull request overview
This PR scaffolds a new Angular 21 + SAP Composable Storefront (Spartacus 221121.15.1) application and wires in a Contentstack-driven CMS layer (hybrid mode with OCC fallback), with build-time generation of a gitignored Contentstack environment file from env vars.
Changes:
- Added Angular/Spartacus storefront bootstrap (standalone app config + Spartacus feature module composition).
- Integrated Contentstack connector configuration and a prebuild/prestart env generator script.
- Added global and feature SCSS imports plus project tooling configs (Angular CLI, TS configs, Prettier/EditorConfig, VS Code tasks).
Reviewed changes
Copilot reviewed 49 out of 54 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.spec.json | Adds spec TS config (extends base) with vitest globals type declarations. |
| tsconfig.json | Defines base TypeScript + Angular compiler strictness and project references. |
| tsconfig.app.json | Adds app TS config and excludes spec files from app compilation. |
| src/styles/spartacus/user.scss | Imports Spartacus user feature styles. |
| src/styles/spartacus/storefinder.scss | Imports storefinder styles plus required Bootstrap SCSS utilities. |
| src/styles/spartacus/product.scss | Imports product styles plus required Bootstrap SCSS utilities. |
| src/styles/spartacus/order.scss | Imports Spartacus order feature styles. |
| src/styles/spartacus/checkout.scss | Imports checkout styles plus required Bootstrap SCSS utilities. |
| src/styles/spartacus/cart.scss | Imports cart styles plus required Bootstrap SCSS utilities. |
| src/styles/spartacus/asm.scss | Imports ASM feature styles. |
| src/styles.scss | Sets global stylesheet import order (Spartacus core → Bootstrap copies → Spartacus index). |
| src/styles-config.scss | Defines Spartacus style version variable. |
| src/main.ts | Bootstraps the standalone Angular application with bootstrapApplication. |
| src/index.html | Adds the base HTML shell for the Angular app. |
| src/app/spartacus/spartacus.module.ts | Composes the top-level Spartacus module imports/exports. |
| src/app/spartacus/spartacus-features.module.ts | Registers Spartacus core/storefront modules and feature toggles, plus feature modules. |
| src/app/spartacus/spartacus-configuration.module.ts | Provides Spartacus configuration (layout/media/CMS providers, OCC/site context/i18n/features). |
| src/app/spartacus/features/user/user-feature.module.ts | Configures lazy-loaded user account/profile feature modules + i18n resources. |
| src/app/spartacus/features/tracking/personalization-feature.module.ts | Configures lazy-loaded personalization feature module. |
| src/app/spartacus/features/storefinder/store-finder-feature.module.ts | Configures lazy-loaded store finder feature module + i18n resources. |
| src/app/spartacus/features/smartedit/smart-edit-feature.module.ts | Configures lazy-loaded SmartEdit feature module and SmartEdit config placeholders. |
| src/app/spartacus/features/product/product-variants-feature.module.ts | Configures lazy-loaded product variants feature module + i18n resources. |
| src/app/spartacus/features/product/product-image-zoom-feature.module.ts | Configures lazy-loaded product image zoom feature module + i18n resources. |
| src/app/spartacus/features/order/order-feature.module.ts | Configures lazy-loaded order feature module + i18n resources. |
| src/app/spartacus/features/contentstack/contentstack-feature.module.ts | Adds Contentstack CMS connector configuration (hybrid CMS override with OCC fallback). |
| src/app/spartacus/features/checkout/checkout-feature.module.ts | Configures lazy-loaded checkout feature module + i18n resources. |
| src/app/spartacus/features/cart/wish-list-feature.module.ts | Configures wish list + add-to-wishlist feature modules + i18n resources. |
| src/app/spartacus/features/cart/cart-saved-cart-feature.module.ts | Configures saved cart feature module + i18n resources. |
| src/app/spartacus/features/cart/cart-quick-order-feature.module.ts | Configures quick order feature module + i18n resources. |
| src/app/spartacus/features/cart/cart-import-export-feature.module.ts | Configures import/export feature module + i18n resources. |
| src/app/spartacus/features/cart/cart-base-feature.module.ts | Configures base cart + mini cart + add-to-cart feature modules + i18n resources. |
| src/app/spartacus/features/asm/asm-feature.module.ts | Configures ASM feature module + i18n resources. |
| src/app/spartacus/features/asm/asm-customer360-feature.module.ts | Configures ASM Customer 360 feature module + i18n resources. |
| src/app/app.routes.ts | Introduces an (currently empty) Angular Router route list. |
| src/app/app.module.ts | Adds NgRx root + Spartacus AppRoutingModule and feature composition via SpartacusModule. |
| src/app/app.config.ts | Configures standalone app providers (router, HttpClient, imported NgModule providers). |
| src/app/app.component.ts | Declares the root standalone component that hosts StorefrontComponent. |
| src/app/app.component.spec.ts | Adds basic unit tests for the root component. |
| src/app/app.component.scss | Adds component stylesheet placeholder. |
| src/app/app.component.html | Hosts the Spartacus storefront element. |
| scripts/generate-contentstack-env.js | Generates src/environments/contentstack.environment.ts from env vars at build/start time. |
| README.md | Documents setup, RBSC registry access, and Contentstack env generation. |
| package.json | Defines Angular/Spartacus/Contentstack dependencies and npm scripts. |
| angular.json | Configures Angular build/serve/test targets and global feature styles. |
| .vscode/tasks.json | Adds VS Code tasks for npm start and npm test. |
| .vscode/mcp.json | Configures Angular CLI MCP server for VS Code. |
| .vscode/launch.json | Adds debug launch configs for serve/test. |
| .vscode/extensions.json | Recommends Angular extension. |
| .prettierrc | Adds Prettier configuration with Angular HTML parser override. |
| .gitignore | Ignores build outputs, IDE artifacts, and generated Contentstack env + .env files. |
| .env.example | Provides example Contentstack environment variables for local development. |
| .editorconfig | Adds formatting conventions across file types. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| it('should render title', async () => { | ||
| const fixture = TestBed.createComponent(App); | ||
| await fixture.whenStable(); | ||
| const compiled = fixture.nativeElement as HTMLElement; | ||
| expect(compiled.querySelector('h1')?.textContent).toContain('Hello, electronics-spa'); | ||
| }); |
| "@angular/platform-browser": "^21.2.0", | ||
| "@angular/router": "^21.2.0", | ||
| "@angular/service-worker": "^21.2.14", | ||
| "@contentstack/contentstack-spartacus-connector": "file:../../contentstack-spartacus-connector/dist/contentstack-contentstack-spartacus-connector-0.1.0.tgz", |
| "scripts": { | ||
| "ng": "ng", | ||
| "generate-env": "node scripts/generate-contentstack-env.js", | ||
| "prestart": "npm run generate-env", | ||
| "start": "ng serve", | ||
| "prebuild": "npm run generate-env", | ||
| "build": "ng build", | ||
| "watch": "ng build --watch --configuration development", | ||
| "test": "ng test" | ||
| }, |
| provideConfig(<OccConfig>{ | ||
| backend: { | ||
| occ: { | ||
| baseUrl: 'https://40.76.109.9:9002', | ||
| }, | ||
| }, |
| const content = `import { Region } from '@contentstack/delivery-sdk'; | ||
|
|
||
| // AUTO-GENERATED by scripts/generate-contentstack-env.js — do not edit by hand, | ||
| // your changes will be overwritten on the next build. Edit .env instead. | ||
| export const contentstackDelivery = { | ||
| apiKey: '${process.env.CS_API_KEY}', | ||
| deliveryToken: '${process.env.CS_DELIVERY_TOKEN}', | ||
| environment: '${environment}', | ||
| region: Region.${region}, | ||
| livePreview: ${livePreview}, | ||
| }; | ||
| `; |
| ## Development server | ||
|
|
||
| ```bash | ||
| ng serve |
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 53 out of 58 changed files in this pull request and generated 2 comments.
Suppressed comments (7)
src/app/app.component.spec.ts:21
- This test asserts an
h1with "Hello, electronics-spa", but the component template only renders<cx-storefront>, so the assertion will always fail.
it('should render title', async () => {
const fixture = TestBed.createComponent(App);
await fixture.whenStable();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, electronics-spa');
package.json:13
npm testrunsng testwithout generatingsrc/environments/contentstack.environment.ts, but the app imports that file (and thesrc/environmentsfolder is not present in the repo). This will fail compilation unless the env generator runs first.
"prebuild": "npm run generate-env",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
scripts/generate-contentstack-env.js:45
- The env generator interpolates raw env var values into a TS file using single quotes. If an env var contains a quote, backslash, or newline, the generated TypeScript becomes invalid (and can be code-injected). Use
JSON.stringifyto safely emit string literals.
apiKey: '${process.env.CS_API_KEY}',
deliveryToken: '${process.env.CS_DELIVERY_TOKEN}',
environment: '${environment}',
region: Region.${region},
livePreview: ${livePreview},
src/app/spartacus/spartacus-configuration.module.ts:28
- The OCC backend base URL is hardcoded to a specific IP. This makes local/dev/prod configuration difficult and risks accidentally pointing builds at the wrong backend. Prefer reading this from an Angular environment/config file or an injected runtime config.
.github/workflows/issues-jira.yml:21 - Pin GitHub Actions to a tag or (preferably) a commit SHA rather than
@masterto avoid supply-chain risk from unexpected upstream changes.
uses: atlassian/gajira-create@master
package.json:24
- The Contentstack connector dependency points to a local tarball path outside this repository (
file:../../...). Fresh clones/CI installs will fail unless that tarball exists at the same relative path. Use a published package version or vendor the tarball inside this repo.
"@contentstack/contentstack-spartacus-connector": "file:../../contentstack-spartacus-connector/dist/contentstack-contentstack-spartacus-connector-0.1.0.tgz",
README.md:57
- The README instructs running
ng serve, but that bypasses theprestarthook that generatessrc/environments/contentstack.environment.ts. For a fresh clone this will fail unless you run the generator manually.
```bash
ng serve
</details>
| selector: 'app-root', | ||
| imports: [StorefrontComponent], | ||
| templateUrl: './app.component.html', | ||
| styleUrl: './app.component.scss', |
| steps: | ||
|
|
||
| - name: Login to Jira | ||
| uses: atlassian/gajira-login@master |
Verifies the connector is actually wired end-to-end (not just that the app builds): Delivery API calls fire and return real entries, a CS-owned slot renders the asset Contentstack returned rather than falling back silently, Live Preview tags stay off the public DOM, and locale switches re-fetch the mapped locale's content.
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 65 changed files in this pull request and generated no new comments.
Suppressed comments (5)
src/app/app.component.ts:9
bootstrapApplication()and the component metadata useimports, which requires a standalone component. Withoutstandalone: true, Angular will error thatimportsis only valid on standalone components and the app won't compile.
@Component({
selector: 'app-root',
imports: [StorefrontComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
src/app/app.component.spec.ts:21
- This spec asserts an
<h1>with "Hello, electronics-spa", but the component template only renders<cx-storefront>so this test will fail.
it('should render title', async () => {
const fixture = TestBed.createComponent(App);
await fixture.whenStable();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, electronics-spa');
.github/workflows/issues-jira.yml:25
- Use consistent casing for the platform name: "GitHub" (not "Github").
summary: Github | Issue | ${{ github.event.repository.name }} | ${{ github.event.issue.title }}
package.json:26
- This dependency points to a tarball outside the repository (
file:../../contentstack-spartacus-connector/...). A clean clone of this repo will failnpm installunless the user happens to have that sibling path available.
"@contentstack/contentstack-spartacus-connector": "file:../../contentstack-spartacus-connector/dist/contentstack-contentstack-spartacus-connector-0.1.0.tgz",
.github/workflows/issues-jira.yml:1
- Use consistent casing for the platform name: "GitHub" (not "Github").
This issue also appears on line 25 of the same file.
name: Create Jira Ticket for Github Issue
Updated CODEOWNERS to simplify workflow ownership.
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
1 similar comment
🔒 Security Scan Results
⏱️ SLA Breach Summary
✅ BUILD PASSED - All security checks passed |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 59 out of 64 changed files in this pull request and generated no new comments.
Suppressed comments (9)
src/app/app.component.ts:9
@Componentuses theimportsfield (standalone-only API) and the app is bootstrapped withbootstrapApplication, but the component isn't markedstandalone: true. This will fail to compile/run as a standalone app.
@Component({
selector: 'app-root',
imports: [StorefrontComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
src/app/app.component.spec.ts:22
- This spec asserts an
h1with "Hello, electronics-spa", but the component template only renders<cx-storefront>so the test will always fail.
it('should render title', async () => {
const fixture = TestBed.createComponent(App);
await fixture.whenStable();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, electronics-spa');
});
scripts/generate-contentstack-env.js:46
- The generated TS file interpolates env var values directly into single-quoted strings. If any value contains
', newlines, or backslashes, the output becomes invalid TypeScript (and it also enables accidental code injection via env vars). Serialize values safely when generating code.
const content = `import { Region } from '@contentstack/delivery-sdk';
// AUTO-GENERATED by scripts/generate-contentstack-env.js — do not edit by hand,
// your changes will be overwritten on the next build. Edit .env instead.
export const contentstackDelivery = {
apiKey: '${process.env.CS_API_KEY}',
deliveryToken: '${process.env.CS_DELIVERY_TOKEN}',
environment: '${environment}',
region: Region.${region},
livePreview: ${livePreview},
};
package.json:27
@contentstack/contentstack-spartacus-connectoris referenced via afile:../../...tarball path outside this repo. Fresh clones/CI won't have that tarball, sonpm installwill fail unless the developer happens to have the sibling repo layout.
"@angular/router": "^21.2.0",
"@angular/service-worker": "^21.2.14",
"@contentstack/contentstack-spartacus-connector": "file:../../contentstack-spartacus-connector/dist/contentstack-contentstack-spartacus-connector-0.1.0.tgz",
"@contentstack/delivery-sdk": "^4.11.2",
src/app/spartacus/spartacus-configuration.module.ts:29
- The OCC
baseUrlis hard-coded to a specific IP address. That makes the app non-portable and forces everyone to use the same backend (and a potentially self-signed cert). Prefer reading this from an environment-specific config (Angular environment file / runtime config / env generator).
package.json:14 - The env generator is only wired into
prestart/prebuild. Runningnpm testornpm run e2edirectly can fail becausesrc/environments/contentstack.environment.tswon't exist yet (it is gitignored but imported by app code). Consider addingpretest(andpree2eif you wantnpm run e2eto be runnable without relying on the Playwright webServer hook).
"prestart": "npm run generate-env",
"start": "ng serve",
"prebuild": "npm run generate-env",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"e2e": "playwright test",
"e2e:ui": "playwright test --ui"
package.json:62
@angular/compileris declared in bothdependenciesanddevDependencies(with different versions). This can produce non-deterministic installs and hard-to-debug Angular version skew; keep it in a single section and ensure versions match the rest of@angular/*.
"devDependencies": {
"@angular-devkit/core": "^21.2.13",
"@angular-devkit/schematics": "^21.2.13",
"@angular/build": "^21.2.19",
"@angular/cli": "^21.2.19",
"@angular/compiler": "^21.2.14",
"@angular/compiler-cli": "^21.2.0",
"@playwright/test": "^1.62.1",
e2e/README.md:25
- This README links to
../../../../contentstack-spartacus-connector/..., but that path doesn't exist in this repository so the link will be broken on GitHub. Use an absolute link to the connector repo instead.
**Known gap, not fixed here:** `scripts/generate-contentstack-env.js` never writes a
`previewToken` into `contentstack.environment.ts`, so `CS_LIVE_PREVIEW=true` alone can't
actually turn Live Preview on ([contentstack-client.service.ts](../../../../contentstack-spartacus-connector/src/client/contentstack-client.service.ts)
requires `livePreview` + `previewToken` + dev mode together). The live-preview spec is written
against that reality — it only asserts the on-state when explicitly told to expect it.
src/app/spartacus/features/contentstack/contentstack-feature.module.ts:14
- This module comment references
GETTING_STARTED.mdandCONTENT-MODEL.md, but those files aren't present in this repo, so new users will hit dead links. Either add the docs or update the references to existing documentation (e.g., the root README or the connector repo docs).
Summary
221121.15.1), wired to OCC base siteelectronics-spa@contentstack/contentstack-spartacus-connector, pointed at a live, fully-seeded Contentstack stack (hybrid mode: Contentstack overrides homepage/nav/footer/product/category slots, OCC serves everything else and all commerce data)CS_API_KEY/CS_DELIVERY_TOKEN) are generated intosrc/environments/contentstack.environment.tsat build time from env vars viascripts/generate-contentstack-env.js(wired through npm'sprestart/prebuildhooks) — nothing credential-bearing is committed; see.env.example/faq, product, and category pages all confirmed rendering live Contentstack content in a real browserTest plan
npm run buildsucceedsnpm startrenders homepage with Contentstack-sourced banners/carousel (images.contentstack.ioassets confirmed in DOM)/faq,/contact,/salerender Contentstacklanding_pagecontentgitleaks+trufflehogscanned clean (0 leaks / 0 verified secrets) across full git history