Skip to content

Fix frontend documentation and Angular skill drift after the Angular 22 / TypeScript 6 upgrade #37009

Description

@oidacra

Description

The Angular 21 → 22 / TypeScript 6 upgrade (#35930, delivered via PR #36838 and PR #36907) changed framework behavior and workspace tooling, but the frontend documentation was never updated to match. docs/frontend/ANGULAR_STANDARDS.md — described in its own header as "the single source of truth for Angular development in the dotCMS frontend" — now contains guidance that is factually wrong against origin/main.

The same drift extends to the sibling frontend docs, the root CLAUDE.md, and the angular-developer agent skill.

This is not cosmetic. Both developers and AI coding agents read these files as authoritative, so every stale rule actively produces incorrect code: the docs instruct yarn install in a pnpm-only workspace, they mandate an explicit OnPush line that Angular 22 made redundant, and the Angular skill ships an example that sets standalone: true — something ANGULAR_STANDARDS.md:16 explicitly forbids.

Verified drift in docs/frontend/ANGULAR_STANDARDS.md

Line numbers as of origin/main (d111b5d).

Line Doc currently says Actual state
3 "Angular v20+" Angular 22
6 **Angular**: 22.0.7 22.1.0 — drifted within one patch release
19, 32, 149 "Always use OnPush change detection strategy" OnPush is the framework default since v22; ChangeDetectionStrategy.Eager (renamed from Default) is the opt-in mode and is used in 219 places. The doc never mentions Eager
33 vs 111 L33: "Prefer inline templates for small components" L111: "Every component MUST have three separate files" and marks inline templates as forbidden. Direct self-contradiction — and the doc's own "Required" example at L215 uses an inline template
151–179 implements OnDestroy with a destroy$ Subject and takeUntil No mention of DestroyRef / takeUntilDestroyed()
278–284 Bare nx run … commands Nx is not installed globally; commands must be prefixed pnpm nx …
287 yarn install # NOT npm install packageManager is pnpm@10.17.1; only pnpm-lock.yaml exists in the repo
Nothing about TypeScript 6 "ignoreDeprecations": "6.0" sits undocumented in core-web/tsconfig.base.json:18

Source for the change detection default: Angular — Advanced component configuration"ChangeDetectionStrategy.OnPush is the default strategy (since v22)." This default flip is why PR #36907 had to add an explicit Eager to ~40 legacy components that had been relying on the old default.

The rest of the stack table (L7–L12) was verified correct: PrimeNG 21.1.3, NgRx Signals 21.1.1, Tailwind 4.1.17, Nx 23.1.1, TypeScript 6.0.3, Node 22.22.3.

Verified drift in sibling documentation

The workspace migrated from @ngneat/spectator to @openng/spectator@1.0.1. 528 source files import @openng; zero import @ngneat. Three docs still reference the old package:

File Stale references
docs/frontend/TESTING_FRONTEND.md 6 (lines 7, 14, 66, 67, 99, 304)
docs/frontend/STATE_MANAGEMENT.md 1 (line 238)
docs/frontend/TESTING_REVIEW_RULES.md 1 (line 7)

Verified drift in CLAUDE.md

File Line Issue
CLAUDE.md (root) 48 cd core-web && yarn nx serve dotcms-ui # ... (use yarn nx, not nx) — must be pnpm nx
CLAUDE.md (root) 102 **Frontend**: Angular 21+ — must be Angular 22+
core-web/CLAUDE.md Verified clean. Already uses pnpm and @openng/spectator, and carries no change detection guidance. No changes required

Verified drift in the Angular skill

.agents/skills/angular-developer/, symlinked into .claude/skills/angular-developer. Added in #35237 and vendored from upstream: license: MIT, author: Copyright 2026 Google LLC, version: '1.0'. .claude/skills/CATALOG.md lists it under "External skills (symlinked, not governed here)".

File Line Issue
references/signal-forms.md 556 Sets standalone: true explicitly — contradicts the Angular default and ANGULAR_STANDARDS.md:16, which forbids it
references/signal-forms.md 559 Sets changeDetection: ChangeDetectionStrategy.OnPush explicitly — redundant under the v22 default
references/components.md 115 Standalone guidance still framed around "since Angular 19 / for older versions"
SKILL.md 16 Instructs "run ng build to ensure there are no build errors … Do not skip this step". There is no angular.json in core-web; builds run through pnpm nx build
SKILL.md 25–42 ng new / npx @angular/cli@latest new project-creation rules — not applicable inside an Nx monorepo
references/cli.md 21–75 Assumes angular.json, ng serve / ng build / ng test, and Karma. The workspace uses nx.json and Jest 30.2.0

There are 15 ng CLI invocations across the skill. Because the skill is vendored and explicitly ungoverned, hand-editing it in place would silently fork it from upstream — the resolution needs to be a deliberate choice, captured in the criteria below.

The nx-* skills (nx-generate, nx-plugins, nx-run-tasks, nx-workspace) and link-workspace-packages were also checked: no yarn or @ngneat references. No changes required.

Acceptance Criteria

Change detection guidance (ANGULAR_STANDARDS.md)

  • The doc states that OnPush is the Angular framework default as of v22, and links to the official reference
  • The rule for new components is: do NOT set changeDetection in the @Component decorator — the default already is OnPush
  • The rule for legacy components is: components explicitly marked ChangeDetectionStrategy.Eager keep Eager, and must NOT be converted to OnPush when the file is touched for unrelated work
  • ChangeDetectionStrategy.Eager is documented as the opt-in eager mode renamed from Default in v22, with a note that PR Fix Angular 22 change detection and dialog visibility bugs #36907 applied it to legacy components during the upgrade
  • The three existing directives to set OnPush explicitly (L19, L32, L149) are updated or removed; no remaining text instructs adding a changeDetection line to a new component
  • The component example at L143–150 no longer carries a changeDetection: ChangeDetectionStrategy.OnPush line

Version references (ANGULAR_STANDARDS.md)

  • Hardcoded patch versions are removed from the Tech Stack Configuration block; versions are expressed as major-only (for example "Angular 22.x") with core-web/package.json named as the source of truth
  • The header at L3 no longer says "Angular v20+"
  • No version string in the file contradicts core-web/package.json on origin/main

Commands and package manager

  • Every command block in ANGULAR_STANDARDS.md uses pnpm nx …; no bare nx … invocations remain
  • yarn install at L287 is replaced with pnpm install
  • Root CLAUDE.md:48 uses pnpm nx serve dotcms-ui and the trailing parenthetical no longer says "use yarn nx, not nx"
  • Root CLAUDE.md:102 says Angular 22+
  • grep -rn "yarn " docs/frontend/ CLAUDE.md returns no results referring to the package manager

Spectator package rename

  • All @ngneat/spectator references in docs/frontend/TESTING_FRONTEND.md, docs/frontend/STATE_MANAGEMENT.md, and docs/frontend/TESTING_REVIEW_RULES.md are updated to @openng/spectator
  • grep -rn "@ngneat" docs/ CLAUDE.md core-web/CLAUDE.md returns no results

Internal consistency (ANGULAR_STANDARDS.md)

  • The inline-template contradiction is resolved: L33 and the "File Structure Requirements" section at L108–138 state one consistent rule
  • The "Standalone Component Pattern (Required)" example at L210–239 conforms to whichever rule is chosen — it currently uses an inline template while the doc forbids them
  • The component example at L151–179 uses DestroyRef / takeUntilDestroyed(), or explicitly documents why the destroy$ Subject pattern is still preferred in this codebase

TypeScript 6

  • The doc notes the "ignoreDeprecations": "6.0" flag in core-web/tsconfig.base.json, that it is transitional, and that new code must not rely on the deprecated APIs it unblocks

Angular skill (angular-developer)

  • A decision is recorded on how to handle the vendored skill: re-sync from upstream if a v22-aware release exists, or add a thin dotCMS overlay — rather than silently hand-editing the vendored files into an undocumented fork
  • Whichever route is taken, an Angular-coding agent working in this repo is told: do not set standalone: true, do not set changeDetection on new components, build and test through pnpm nx rather than ng, and use Jest with @openng/spectator
  • The two concrete contradictions at references/signal-forms.md:556 and :559 no longer instruct agents to write code that violates ANGULAR_STANDARDS.md
  • The ng build / ng new / ng test guidance is either scoped as not-applicable-here or replaced with the pnpm nx equivalents
  • If the vendored skill is edited in place, the divergence from upstream is documented inside the skill directory so a future re-sync does not silently revert it
  • If an overlay skill is added, it is registered in .claude/skills/CATALOG.md and satisfies .claude/skills/skills.config.json governance (dot- prefix, owner, status)

Verification

  • Every claim remaining in the touched files is checked against origin/main — no version, command, package name, or API reference contradicts the actual workspace
  • Internal relative links in the touched files still resolve
  • docs/frontend/ANGULAR_STANDARDS.md contains no rule that contradicts another rule in the same file

Priority

Low

Additional Context

Follow-up to #35930 (Migrate Angular 21 → Angular 22 (TypeScript 6) across the core-web Nx workspace), which is closed and shipped in release 26.08.07-01.

Out of scope, tracked separately:

  • Code-level change detection cleanup. The 219 ChangeDetectionStrategy.Eager occurrences stay as they are. Per the rule above they are deliberate, and reverting them would re-break what PR Fix Angular 22 change detection and dialog visibility bugs #36907 fixed. This issue only documents the policy.
  • nx.json:20. The @nx/angular:component generator is configured with "changeDetection": "OnPush", so newly generated components receive an explicit OnPush line that is now redundant under the v22 default. Removing it is a config change, not a docs change, and needs its own issue.
  • ignoreDeprecations removal. Migrating the deprecated usages so the flag can be dropped from tsconfig.base.json is code work; this issue only documents that the flag exists and is transitional.

Metadata

Metadata

Assignees

Type

Projects

Status
New

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions