diff --git a/.changeset/angular-deterministic-cd.md b/.changeset/angular-deterministic-cd.md new file mode 100644 index 0000000..6334e12 --- /dev/null +++ b/.changeset/angular-deterministic-cd.md @@ -0,0 +1,10 @@ +--- +'@formio/ai': minor +--- + +`formio-angular` skill: generate deterministic Angular apps under modern change detection. + +- The skill now always targets the latest Angular `@formio/angular` supports and **pins zoneless change detection explicitly** (`provideZonelessChangeDetection()`, no `zone.js`) in BOOTSTRAP Step 6, instead of force-re-adding `zone.js` and inheriting the CLI's drifting default. No specific Angular version is named in the skill. +- CONFIG/AUTH/app-integration keep the simple `{ provide: FormioAppConfig, useValue: AppConfig }` provider — no app-level wiring change is needed because `@formio/angular` reads that config in the `FormioModule` constructor and configures the SDK (`Formio.setBaseUrl`/`setProjectUrl`) at bootstrap. +- BOOTSTRAP notes one Form.io-specific caveat for zoneless apps (the SDK's promises resolve outside Angular's zone, so refresh views with signals/`markForCheck`, not `NgZone.run`). +- Corrected stale guidance that claimed zone-based CD was required. diff --git a/plugin/skills/formio-angular/AUTH.md b/plugin/skills/formio-angular/AUTH.md index dfb4840..ee0f0b6 100644 --- a/plugin/skills/formio-angular/AUTH.md +++ b/plugin/skills/formio-angular/AUTH.md @@ -107,6 +107,7 @@ import { AuthModule, AuthConfig } from './auth/auth.module'; AuthModule ], providers: [ + // provideZonelessChangeDetection() is added by BOOTSTRAP — see BOOTSTRAP.md Step 6. provideBrowserGlobalErrorListeners(), { provide: FormioAppConfig, useValue: AppConfig }, { provide: FormioAuthConfig, useValue: AuthConfig }, @@ -118,6 +119,8 @@ import { AuthModule, AuthConfig } from './auth/auth.module'; export class AppModule { } ``` +**Config wiring:** the `{ provide: FormioAppConfig, useValue: AppConfig }` provider is all that is needed — `FormioModule` reads it in its constructor and configures the SDK (`Formio.setBaseUrl`/`setProjectUrl`) at bootstrap. See CONFIG.md. + **Why `FormioAuthRoutes()` matters.** Without it, the `AuthModule` registers the providers + components but does NOT map any URL to the login/register form — so `router.navigate(['/auth/login'])` from `app.component.ts` (or `app/app.ts`) resolves to an empty outlet and the user sees a blank page. `FormioAuthRoutes()` returns a pre-built `Routes` array that wires `login` → `FormioAuthLoginComponent`, `register` → `FormioAuthRegisterComponent`, and `logout` → a redirect, which is why mounting it via `RouterModule.forChild(...)` is required, not optional. Customization (override login/register components, tweak the redirect target) is handled by passing an options object to the function — see the optional "Customizing the login and register components" section below. **Worked example** — default user resource with planner-emitted `template.json.forms` containing `{ name: 'userLogin', path: 'user/login' }` and `{ name: 'userRegister', path: 'user/register' }`: diff --git a/plugin/skills/formio-angular/BOOTSTRAP.md b/plugin/skills/formio-angular/BOOTSTRAP.md index ce54b64..08d9a67 100644 --- a/plugin/skills/formio-angular/BOOTSTRAP.md +++ b/plugin/skills/formio-angular/BOOTSTRAP.md @@ -35,14 +35,14 @@ unpkg resolves an unpinned package path to the latest published version automati What to read from it: 1. **The resolved `@formio/angular` version.** The returned JSON has a top-level `"version"` field (e.g., `"10.0.1"`). Capture it as `FORMIO_ANGULAR_VERSION` — this is what you will install in Step 4 and cite in the approval summary. -2. **Supported Angular major.** Look under `peerDependencies` for an entry like `@angular/core`. The range (e.g., `^18.0.0`, `>=18 <19`, `~18.2.0`) names the supported major — in this example, Angular `18`. If `peerDependencies` is absent or ambiguous, fall back to `dependencies` for the same key. If neither is present, stop and tell the user — do NOT guess. -3. **Latest patch within that major.** Query the npm registry for the newest published version of `@angular/core` that matches the supported major. The simplest way is: +2. **Highest supported Angular major.** Look under `peerDependencies` for `@angular/core`. The range typically lists several majors (e.g. `^17.0.0 || ^18.0.0 || … || ^N.0.0`). Take the **highest** major in that range — that is the newest Angular `@formio/angular` supports, and always the one to target. Capture it as `FORMIO_ANGULAR_SUPPORTED_MAJOR`. If `peerDependencies` is absent, fall back to `dependencies` for the same key; if neither is present, stop and tell the user — do NOT guess. (The goal is always the latest supported Angular — never an older major, and never a major newer than `@formio/angular` declares.) +3. **Latest patch within that major.** Query the npm registry for the newest published version of `@angular/core` in that major: ```bash npm view @angular/core@.x.x version ``` - e.g., `npm view @angular/core@18.x.x version` prints the latest `18.*.*` release (something like `18.2.13`). Capture that full `MAJOR.MINOR.PATCH` string — that is the version you will pin the new workspace to in Step 3. + This prints the latest patch in that major. Capture the full `MAJOR.MINOR.PATCH` string as `FORMIO_ANGULAR_TARGET_VERSION` — the version you pin the new workspace to in Step 3. Then do the same resolution for `@formio/js`, the core Form.io SDK that `@formio/angular` wraps. Fetch its unpinned `package.json` from unpkg: @@ -63,12 +63,12 @@ Read the top-level `"version"` field from each and capture them as `BOOTSTRAP_VE Stash the six results for later phases: -- `FORMIO_ANGULAR_VERSION` — e.g., `10.0.1` (resolved latest from unpkg) -- `FORMIO_JS_VERSION` — e.g., `5.3.3` (resolved latest from unpkg, constrained to `@formio/angular`'s declared range) -- `FORMIO_ANGULAR_SUPPORTED_MAJOR` — e.g., `18` -- `FORMIO_ANGULAR_TARGET_VERSION` — e.g., `18.2.13` -- `BOOTSTRAP_VERSION` — e.g., `5.3.3` (must be a Bootstrap 5 major) -- `BOOTSTRAP_ICONS_VERSION` — e.g., `1.11.3` +- `FORMIO_ANGULAR_VERSION` — the latest `@formio/angular`, resolved from unpkg +- `FORMIO_JS_VERSION` — the latest `@formio/js`, resolved from unpkg (constrained to `@formio/angular`'s declared range) +- `FORMIO_ANGULAR_SUPPORTED_MAJOR` — the highest Angular major in `@formio/angular`'s peer range +- `FORMIO_ANGULAR_TARGET_VERSION` — the latest `MAJOR.MINOR.PATCH` within that major +- `BOOTSTRAP_VERSION` — the latest Bootstrap (must be a Bootstrap 5 major) +- `BOOTSTRAP_ICONS_VERSION` — the latest Bootstrap Icons If unpkg is unreachable (offline / proxied environment), fall back to `npm view @formio/angular version` / `npm view @formio/js version` / `npm view bootstrap@5 version` / `npm view bootstrap-icons version` + `npm view @formio/angular peerDependencies` to read the same fields from the npm registry directly. If the npm registry is also unreachable for `@angular/core@.x.x`, fall back to the **highest version listed** in `@formio/angular`'s own `dependencies` for `@angular/core`, and tell the user you could not confirm a newer patch was available. Never silently pick a major the `@formio/angular` package has not declared support for. @@ -99,7 +99,7 @@ What to pass to `angular-new-app`: - **Working directory:** the absolute path where the workspace should be created. Usually the cwd, or the `workspacePath` from `formio-application`'s handoff context. - **Project name (if asked):** offer a name derived from the Form.io `Project URL`'s subdomain if the user gave one (e.g., `https://foo.form.io` → `foo`). Otherwise let `angular-new-app` default to the directory name. -- **Angular version (critical):** pass the `FORMIO_ANGULAR_TARGET_VERSION` resolved in Step 1 (e.g., `18.2.13`). This pins the generated workspace to the exact Angular major `@formio/angular` supports at its latest patch. If `angular-new-app` exposes a version / CLI-version option, use it; if it shells out to `@angular/cli` and takes CLI flags, pass `@angular/cli@` so `npx` resolves the matching CLI major before running `ng new`. Do NOT let the skill default to "latest" — a newer Angular major than `@formio/angular` declares support for will break `npm install` at Step 4. +- **Angular version (critical):** pass the `FORMIO_ANGULAR_TARGET_VERSION` resolved in Step 1 — the latest patch of the highest Angular major `@formio/angular` supports. If `angular-new-app` exposes a version / CLI-version option, use it; if it shells out to `@angular/cli` and takes CLI flags, pass `@angular/cli@` so `npx` resolves the matching CLI major before running `ng new`. Always target the newest Angular `@formio/angular` supports; the only thing to avoid is an even-newer Angular major that `@formio/angular` has not yet declared, which would break `npm install` at Step 4. - **Intent note:** "This workspace will be wired against `@formio/angular@`, which supports Angular ``. The Form.io integration (config, auth, resource NgModules) is generated in subsequent phases by `formio-angular` and its nested Resources sub-skill at `./resources/SKILL.md`." The Angular skill does not need this for correctness, but surfacing it keeps the flow transparent to the user watching the transcript. Do not override `angular-new-app`'s approval gates — it runs its own, and layering a second one on top is confusing. When `angular-new-app` reports success and the workspace exists on disk, BOOTSTRAP is done. @@ -175,67 +175,39 @@ Do NOT add Bootstrap's JavaScript bundle (`bootstrap.bundle.min.js` via `angular After editing `angular.json`, re-run a clean `npm install` (or `ng build --configuration=development` as a smoke check) to confirm the new style paths resolve. If either path 404s, verify the package version in `node_modules` — a Bootstrap 5+ major always ships `dist/css/bootstrap.min.css`, and Bootstrap Icons always ships `font/bootstrap-icons.css`, so a 404 means the install did not land. -## Step 6 — ensure `zone.js` is registered as a polyfill +## Step 6 — pin zoneless change detection explicitly -Angular's change-detection machinery depends on Zone.js. Older `@angular/cli` versions preconfigured it automatically; newer versions (and certain `angular-new-app` flag combinations such as zoneless or `--no-zone`) can omit it. When it is missing at runtime, the application boots with errors like `Zone is not defined` or `NG0908: In this configuration Angular requires Zone.js`, which is what the Form.io integration will hit if we do not guard against it here. +A generated app must **pin its change-detection mode explicitly** rather than inherit whatever `angular-new-app` / the CLI happened to default to — that default has drifted across Angular releases, which would make generated apps non-deterministic. Because the skill always targets the latest Angular `@formio/angular` supports (Step 1), the app uses **zoneless** change detection. `@formio/angular` is change-detection-mode agnostic, so pinning zoneless is safe; pinning it *explicitly* is what makes the result deterministic. -Because `@formio/angular` relies on the default zone-based change-detection model, BOOTSTRAP must guarantee the Zone.js polyfill is present — regardless of what `angular-new-app` decided. +### 6a. Wire zoneless -### 6a. Verify the package is installed +Add the provider to the generated `AppModule` `providers` array (alongside `provideBrowserGlobalErrorListeners()`): -Zone.js ships as a peer / transitive dependency of Angular and should already be present in `node_modules/zone.js`. Confirm with: - -```bash -npm ls zone.js -``` - -If the output shows `zone.js` missing (empty / not-installed), install it explicitly, using the caret range so patch updates flow through automatically: - -```bash -npm install --save zone.js@^ -``` - -Resolve `ZONE_JS_VERSION` the same way Step 1 resolves the other versions — fetch `https://unpkg.com/zone.js/package.json` and read its top-level `version` field. Fall back to `npm view zone.js version` if unpkg is unreachable. Do NOT hard-code a version in the skill. - -### 6b. Register the polyfill in `angular.json` - -Open `/angular.json` and find the same `projects..architect.build.options` block you edited for styles. There are two accepted shapes depending on the Angular major `angular-new-app` generated: - -**Shape A — `polyfills` is an array (Angular 15+ / application builder):** - -```json -"polyfills": [ - "zone.js" -] +```ts +// app-module.ts +import { provideZonelessChangeDetection } from '@angular/core'; +// ...providers: [ provideZonelessChangeDetection(), ... ] ``` -If the array is already present and includes `zone.js`, leave it alone. If the array exists but does NOT include `"zone.js"`, add the entry (keep any existing entries — e.g., `@angular/localize/init`). If the `polyfills` key is missing entirely, add the array with `"zone.js"` as its first entry. - -**Shape B — `polyfills` is a string pointing at `src/polyfills.ts` (older Angular majors):** +`zone.js` is not needed; leave the `angular.json` `polyfills` array empty on both `build` and `test` targets: ```json -"polyfills": "src/polyfills.ts" -``` - -In this shape, open `/src/polyfills.ts` and make sure it contains the side-effect import: - -```ts -import 'zone.js'; +"polyfills": [] ``` -If the file does not exist (`angular-new-app` generated Shape A instead), prefer Shape A above — do NOT create a parallel `src/polyfills.ts` just to satisfy an older convention. Match whatever the generated workspace uses. +For the `test` target, add `provideZonelessChangeDetection()` to the `TestBed.configureTestingModule({ providers: [...] })` of generated specs so unit tests run in the same mode. -Apply the same edit to the `test` target's `polyfills` entry (it lives immediately below `build` in most generated configs). Unit tests run in the same zone-based model as the app; skipping the test-target edit produces identical `Zone is not defined` failures in `ng test`. +### 6b. One Form.io-specific caveat -### 6c. Smoke-check that the polyfill resolves +The Form.io SDK's promises (`loadSubmissions`, `loadForms`, …) resolve outside Angular's zone. Do not reach for `NgZone.run(...)` to refresh the view after them — it is a no-op under zoneless. Update state the standard zoneless way (a `signal()` write, or `ChangeDetectorRef.markForCheck()`). No other special handling is needed — `@formio/angular`'s own components already do this internally. -After editing, run: +### 6c. Smoke-check ```bash ng build --configuration=development ``` -A clean build confirms both that `zone.js` is resolvable in `node_modules` and that the `polyfills` entry shape you wrote matches what the builder expects. If the build errors with `Module not found: zone.js` or `Cannot find module 'zone.js'`, the install in 6a did not land — re-run it. If the build succeeds but the running app still logs `Zone is not defined`, the edit to `angular.json` hit the wrong project / target pair; open `angular.json` again and confirm the `defaultProject` (or the project the user is running) points at the same block you edited. +A clean build confirms the `polyfills` shape matches the builder and the CD provider import resolves. If the app logs `NG0908` / `Zone is not defined` at runtime, a dependency still expects `zone.js` — re-check that no generated code imports `zone.js` and that `provideZonelessChangeDetection()` is actually registered. ## Step 7 — confirm Claude's `frontend-design` skill is available diff --git a/plugin/skills/formio-angular/CONFIG.md b/plugin/skills/formio-angular/CONFIG.md index 76d4263..4f40ce2 100644 --- a/plugin/skills/formio-angular/CONFIG.md +++ b/plugin/skills/formio-angular/CONFIG.md @@ -81,6 +81,8 @@ Add the provider registration to `@NgModule({ providers: [...] })`: export class AppModule {} ``` +This `useValue` form is all that is needed: `FormioModule` reads the provided `FormioAppConfig` in its constructor and calls `Formio.setBaseUrl`/`setProjectUrl` at bootstrap, so the SDK is configured even though `useValue` skips the `FormioAppConfig` constructor. No `forRoot` / `FORMIO_CONFIG` wiring is required. + ## The approval gate — preview then approve Before writing or editing any files, print a diff-style preview: diff --git a/plugin/skills/formio-angular/SKILL.md b/plugin/skills/formio-angular/SKILL.md index 10b667d..06da301 100644 --- a/plugin/skills/formio-angular/SKILL.md +++ b/plugin/skills/formio-angular/SKILL.md @@ -1,7 +1,7 @@ --- name: formio-angular description: >- - Angular framework implementor for the Form.io skill library — turns an approved `template.json` plus a target Form.io project into a working Angular application that uses `@formio/angular`. Invoked either (a) as a handoff from `formio-application` after it has captured URLs and imported the template, or (b) directly when the user explicitly names Angular. Claims ONLY Angular-explicit triggers — phrases that name Angular or `@formio/angular` verbatim. Example triggers this skill claims include "build it in Angular", "scaffold an Angular front-end for this Form.io project", "generate the Angular CRUD", "Angular front-end", "use Angular", "use `@formio/angular`", "the Angular skill", and "wire up `FormioAppConfig` in my Angular workspace". Does NOT claim framework-agnostic triggers (those go through `formio-application`). Runs a five-phase flow with an approval gate between each — (1) SETUP — capture the Form.io Project URL and Base URL via batched interview, UNLESS URLs are handed in by `formio-application` (in which case SETUP confirms and skips ahead); (2) BOOTSTRAP — when no Angular workspace is present in the working directory, install the Angular team's skill library (`npx skills add https://github.com/angular/skills --all -a claude-code -y`) and delegate to the installed `angular-new-app` skill to scaffold the workspace (with the Angular major pinned to whatever `@formio/angular`'s `peerDependencies` supports, resolved from `https://unpkg.com/@formio/angular/package.json`), then install `@formio/angular` + `@formio/js` + (unless the user opts out) Bootstrap 5 + Bootstrap Icons into it, register the Bootstrap stylesheets in `angular.json`'s build target, and ensure `zone.js` is present in `node_modules` and listed in `angular.json`'s `polyfills` entry (build + test targets) so the Form.io renderer's zone-based change detection does not crash with `Zone is not defined`; skipped when `angular.json` is already present; (3) CONFIG — generate `src/app/config.ts` exporting a typed `AppConfig` (of type `FormioAppConfig`) and wire it into `AppModule` per the `@formio/angular` demo; (4) AUTH — generate `src/app/auth/auth.module.ts` with `FormioAuthConfig` derived from the `template.json` user resource, login form, register form, and roles; (5) Resources — load the nested Resources sub-skill file at `./resources/SKILL.md` (a sub-folder of this skill, NOT a separate top-level skill) and follow its two-phase cadence for per-resource NgModule scaffolding. Does NOT scaffold the Angular workspace itself (that is `angular-new-app`'s job, invoked from the BOOTSTRAP phase), does NOT run its own planner-inference phase (planning is `formio-resource-planner`'s job, called by `formio-application`), and does NOT run its own template-import phase (template import into a Form.io project is `formio-application`'s job via the `project_import` MCP tool). Not for: generic, framework-agnostic app-construction requests — see `formio-application`. Not for: adding a single feature to an already-running Angular app when the user uses generic, framework-agnostic phrasing — that goes through `formio-application`'s modify-existing branch, which loads the nested `formio-angular-resources` sub-skill file at `./resources/SKILL.md` (a sub-folder of THIS skill, NOT a separately-registered top-level skill). Not for: Angular-explicit extension requests against an already-running Angular app — those are handled by loading the nested `formio-angular-resources` sub-skill file at `./resources/SKILL.md` under this skill. Not for: planning a data model in isolation — see `formio-resource-planner`. Not for: Form.io REST endpoint lookups — see the `formio-api` skill. + Angular framework implementor for the Form.io skill library — turns an approved `template.json` plus a target Form.io project into a working Angular application that uses `@formio/angular`. Invoked either (a) as a handoff from `formio-application` after it has captured URLs and imported the template, or (b) directly when the user explicitly names Angular. Claims ONLY Angular-explicit triggers — phrases that name Angular or `@formio/angular` verbatim. Example triggers this skill claims include "build it in Angular", "scaffold an Angular front-end for this Form.io project", "generate the Angular CRUD", "Angular front-end", "use Angular", "use `@formio/angular`", "the Angular skill", and "wire up `FormioAppConfig` in my Angular workspace". Does NOT claim framework-agnostic triggers (those go through `formio-application`). Runs a five-phase flow with an approval gate between each — (1) SETUP — capture the Form.io Project URL and Base URL via batched interview, UNLESS URLs are handed in by `formio-application` (in which case SETUP confirms and skips ahead); (2) BOOTSTRAP — when no Angular workspace is present in the working directory, install the Angular team's skill library (`npx skills add https://github.com/angular/skills --all -a claude-code -y`) and delegate to the installed `angular-new-app` skill to scaffold the workspace (with the Angular major pinned to whatever `@formio/angular`'s `peerDependencies` supports, resolved from `https://unpkg.com/@formio/angular/package.json`), then install `@formio/angular` + `@formio/js` + (unless the user opts out) Bootstrap 5 + Bootstrap Icons into it, register the Bootstrap stylesheets in `angular.json`'s build target, and pin zoneless change detection explicitly (`provideZonelessChangeDetection()`) so generated apps are deterministic rather than inheriting the CLI's drifting default; skipped when `angular.json` is already present; (3) CONFIG — generate `src/app/config.ts` exporting a typed `AppConfig` (of type `FormioAppConfig`) and wire it into `AppModule` per the `@formio/angular` demo; (4) AUTH — generate `src/app/auth/auth.module.ts` with `FormioAuthConfig` derived from the `template.json` user resource, login form, register form, and roles; (5) Resources — load the nested Resources sub-skill file at `./resources/SKILL.md` (a sub-folder of this skill, NOT a separate top-level skill) and follow its two-phase cadence for per-resource NgModule scaffolding. Does NOT scaffold the Angular workspace itself (that is `angular-new-app`'s job, invoked from the BOOTSTRAP phase), does NOT run its own planner-inference phase (planning is `formio-resource-planner`'s job, called by `formio-application`), and does NOT run its own template-import phase (template import into a Form.io project is `formio-application`'s job via the `project_import` MCP tool). Not for: generic, framework-agnostic app-construction requests — see `formio-application`. Not for: adding a single feature to an already-running Angular app when the user uses generic, framework-agnostic phrasing — that goes through `formio-application`'s modify-existing branch, which loads the nested `formio-angular-resources` sub-skill file at `./resources/SKILL.md` (a sub-folder of THIS skill, NOT a separately-registered top-level skill). Not for: Angular-explicit extension requests against an already-running Angular app — those are handled by loading the nested `formio-angular-resources` sub-skill file at `./resources/SKILL.md` under this skill. Not for: planning a data model in isolation — see `formio-resource-planner`. Not for: Form.io REST endpoint lookups — see the `formio-api` skill. --- # Form.io + Angular — Framework Implementor @@ -66,7 +66,7 @@ Pause for acknowledgement, then proceed. ## Phase 2 — BOOTSTRAP -**Goal:** when the working folder does not yet contain an Angular workspace, install the Angular team's official skill library and delegate workspace creation to its `angular-new-app` skill. Then install `@formio/angular` + `@formio/js` into the freshly-scaffolded workspace so CONFIG can import from them, and — unless the user explicitly opted out — install Bootstrap 5 + Bootstrap Icons and register their stylesheets in `angular.json`'s build `styles` array so the Form.io renderer's default Bootstrap 5 template renders correctly. Finally, ensure `zone.js` is installed and listed in `angular.json`'s `polyfills` entry (on both `build` and `test` targets) — `@formio/angular` depends on Angular's zone-based change detection, and a workspace without the Zone.js polyfill boots with `Zone is not defined`. +**Goal:** when the working folder does not yet contain an Angular workspace, install the Angular team's official skill library and delegate workspace creation to its `angular-new-app` skill. Then install `@formio/angular` + `@formio/js` into the freshly-scaffolded workspace so CONFIG can import from them, and — unless the user explicitly opted out — install Bootstrap 5 + Bootstrap Icons and register their stylesheets in `angular.json`'s build `styles` array so the Form.io renderer's default Bootstrap 5 template renders correctly. Finally, **pin zoneless change detection explicitly** (BOOTSTRAP Step 6): add `provideZonelessChangeDetection()` and leave `zone.js` out of `polyfills`. `@formio/angular` is change-detection-mode agnostic; pinning the mode explicitly — rather than inheriting the CLI default — is what makes generated apps deterministic. **How:** read [`BOOTSTRAP.md`](./BOOTSTRAP.md) for the exact `npx skills add https://github.com/angular/skills --all -a claude-code -y` invocation, the handoff shape to `angular-new-app` (working directory, suggested project name derived from the Form.io Project URL, intent note), the post-scaffold verification checks (`angular.json`, `src/app/app-module.ts`, `package.json` with `@angular/core`), the `npm install --save @formio/angular` step, and the skip-if-already-scaffolded detection logic. diff --git a/plugin/skills/formio-angular/resources/SKILL.md b/plugin/skills/formio-angular/resources/SKILL.md index 6fcd62d..e0e93e1 100644 --- a/plugin/skills/formio-angular/resources/SKILL.md +++ b/plugin/skills/formio-angular/resources/SKILL.md @@ -21,7 +21,13 @@ You are a code generator that plans before it writes. Two distinct phases with a - **Batch your questions.** When integration choices come up (base URL, app name, existing-vs-new workspace, design language), ask them together in one `AskUserQuestion`. Do not pepper. - **Gate on approval.** Phase A (Scaffolding Plan) is for review. Do not write files or emit Phase B until the user has explicitly approved the plan. The plan must sketch what the `ViewComponent` looks like for each resource — not pixel-precise, but enough that the user can sanity-check the design direction before files get generated. - **NgModules with `standalone: false`.** `FormioResource` is itself an NgModule and its `ResourceComponent`/`ViewComponent` overrides expect NgModule-based declaration. Matches the Form.io docs and the official angular-demo. Do not generate standalone components. -- **Consult Claude's `frontend-design` skill for every UI surface — always briefed with the Bootstrap 5 stack.** This is the UI-heavy phase of the `formio-angular` pipeline: every resource produces a `resource.component.html` (nav chrome around `:id/*` children), a `view/view.component.html` (the detail page — the biggest design surface in the skill), optional per-resource SCSS, and sometimes custom index components for joins. ALL of that must be shaped by loading Claude's built-in `frontend-design` skill first and following its guidance — same rule as the parent `formio-angular` skill's Stance. When invoking `frontend-design`, always prepend the `FRONTEND_DESIGN_BRIEF` that BOOTSTRAP Step 7d stashed so the skill knows the stack is Bootstrap 5 + Bootstrap Icons (pre-wired through `angular.json`), uses Bootstrap utility classes instead of Tailwind, and extends Bootstrap's CSS variables instead of introducing parallel design tokens. The patterns in `references/resource-module-patterns.md` give you the Angular plumbing (route shape, component base class, signal plumbing); `frontend-design` (briefed with BOOTSTRAP's preamble) gives you the visual-design decisions (layout, hierarchy, spacing, color, typography, affordances) — all expressed in Bootstrap 5 vocabulary. Do not ship a Phase B output that was not reviewed against `frontend-design` with the brief applied. The Phase A plan must explicitly confirm both happened — see "Phase A" below. +- **Consult Claude's `frontend-design` skill for every UI surface — always briefed with the Bootstrap 5 stack.** This is the UI-heavy phase of the `formio-angular` pipeline: Resource templates are fully extendable and can be easily customized to meet any UI requirements. Extended resource components can provide their own `html` templates, and optional per-resource SCSS. ALL of that must be shaped by loading Claude's built-in `frontend-design` skill first and following its guidance — same rule as the parent `formio-angular` skill's Stance. When invoking `frontend-design`, always prepend the `FRONTEND_DESIGN_BRIEF` that BOOTSTRAP Step 7d stashed so the skill knows the stack is Bootstrap 5 + Bootstrap Icons (pre-wired through `angular.json`), uses Bootstrap utility classes instead of Tailwind, and extends Bootstrap's CSS variables instead of introducing parallel design tokens. The patterns in `references/resource-module-patterns.md` give you the Angular plumbing (route shape, component base class, override pairs); `frontend-design` (briefed with BOOTSTRAP's preamble) gives you the visual-design decisions (layout, hierarchy, spacing, color, typography, affordances) — all expressed in Bootstrap 5 vocabulary. Do not ship a Phase B output that was not reviewed against `frontend-design` with the brief applied. The Phase A plan must explicitly confirm both happened — see "Phase A" below. Extended resource components can provide the following to fully customize UI experience. + - A `resource.component.html`: Nav chrome around `:id/*` children) + - A `view/view.component.html`: The resource detail page — the biggest design surface in the skill) + - A `edit/edit.component.html`: (optional) The resource edit page - must include the same `` and options found in the `FormioResourceEditComponent` base component template. + - A `create/create.component.html`: (optional) Page used to create a new resource - must include the same `` and options found in the `FormioResourceCreateComponent` base component template. + - A `delete/delete.component.html`: (optional) Delete a component page - Confirm must call `onDelete()` and Cancel must call `onCancel()` + - A `index/index.component.html`: (optional) The resource "list" page - Any "grid" UI can be used, but refer to the `FormioResourceIndexComponent` base class for API fetch logic for Resource index data ## Inputs you expect diff --git a/plugin/skills/formio-angular/resources/references/app-integration.md b/plugin/skills/formio-angular/resources/references/app-integration.md index 9c1cab4..7ea2acf 100644 --- a/plugin/skills/formio-angular/resources/references/app-integration.md +++ b/plugin/skills/formio-angular/resources/references/app-integration.md @@ -42,6 +42,7 @@ import { HomeComponent } from './home/home.component'; declarations: [AppComponent, HomeComponent], imports: [BrowserModule, CommonModule, FormioModule, FormioGrid, AppRoutingModule], providers: [ + // provideZonelessChangeDetection() is added by BOOTSTRAP (see BOOTSTRAP.md Step 6). FormioAuthService, FormioResources, { provide: FormioAppConfig, useValue: AppConfig }, @@ -52,7 +53,7 @@ import { HomeComponent } from './home/home.component'; export class AppModule {} ``` -Three provider lines are doing the heavy lifting. `FormioResources` (plural!) is the registry every nested resource module looks up its parents through. `FormioAuthService` is what makes `currentUser` available as an object-parent to any resource that wants to auto-fill a user field. `FormioAppConfig` carries `appUrl` (project URL) — every `FormioResourceService` reads it at init time. +The heavy lifting: `FormioAppConfig` carries `appUrl` (project URL) — every `FormioResourceService` reads it at init time, and `FormioModule` configures the SDK (`Formio.setBaseUrl`/`setProjectUrl`) from it in its constructor at bootstrap, so the plain `useValue` provider is sufficient. `FormioResources` (plural!) is the registry every nested resource module looks up its parents through. `FormioAuthService` is what makes `currentUser` available as an object-parent to any resource that wants to auto-fill a user field. If the user has an existing AppModule, **merge** these declarations/imports/providers rather than overwriting. See section 10.