@ethlete/agent-rules 0.1.0-next.11 → 0.1.0-next.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +27 -25
  3. package/content/hooks/context-warning.py +25 -6
  4. package/content/rules/lint-and-format.md +5 -4
  5. package/content/rules/reactive-state.md +1 -1
  6. package/content/rules/styling.md +8 -6
  7. package/content/skills/angular-patterns/SKILL.md +6 -6
  8. package/content/skills/api-source/SKILL.md +33 -21
  9. package/content/skills/figma-export/SKILL.md +16 -18
  10. package/content/skills/git-flow/SKILL.md +2 -2
  11. package/content/skills/handoff/SKILL.md +4 -4
  12. package/content/skills/query/SKILL.md +23 -12
  13. package/content/skills/rxjs-signals/SKILL.md +9 -3
  14. package/content/skills/sdk-docs/SKILL.md +6 -5
  15. package/content/skills/sdk-local-build/SKILL.md +26 -8
  16. package/content/skills/sdk-local-build/sdk-local-baseline.mjs +64 -0
  17. package/content/skills/sdk-source/SKILL.md +36 -33
  18. package/content/skills/story-styling/SKILL.md +3 -2
  19. package/content/skills/styleguide/SKILL.md +11 -6
  20. package/content/skills/styleguide/assets.md +54 -0
  21. package/content/skills/styleguide/changesets.md +17 -0
  22. package/content/skills/styleguide/file-structure.md +73 -0
  23. package/content/skills/styleguide/lint-rule-lookup.md +50 -0
  24. package/content/skills/styleguide/storybook-structure.md +25 -0
  25. package/content/skills/theming/SKILL.md +11 -11
  26. package/content/skills/timetrack/SKILL.md +1 -1
  27. package/package.json +1 -1
  28. package/src/lib/config.d.ts +13 -7
  29. package/src/lib/config.js +14 -9
  30. package/src/lib/config.js.map +1 -1
  31. package/src/lib/plan.d.ts +6 -5
  32. package/src/lib/plan.js +66 -59
  33. package/src/lib/plan.js.map +1 -1
  34. package/src/lib/sync.js +1 -4
  35. package/src/lib/sync.js.map +1 -1
  36. package/src/lib/targets/agents-skills.js +1 -1
  37. package/src/lib/targets/agents-skills.js.map +1 -1
  38. package/src/lib/targets/claude.js +0 -1
  39. package/src/lib/targets/claude.js.map +1 -1
  40. package/src/lib/targets/codex.js +2 -2
  41. package/src/lib/targets/codex.js.map +1 -1
  42. package/src/lib/targets/copilot.js +1 -1
  43. package/src/lib/targets/copilot.js.map +1 -1
  44. package/src/lib/targets/cursor.js +1 -1
  45. package/src/lib/targets/cursor.js.map +1 -1
  46. package/src/lib/targets/shared.d.ts +1 -8
  47. package/src/lib/targets/shared.js +2 -7
  48. package/src/lib/targets/shared.js.map +1 -1
  49. package/content/skills/styleguide/STYLEGUIDE.md +0 -520
@@ -1,520 +0,0 @@
1
- # Style Guide v0.21.0
2
-
3
- This document outlines the coding style guide for Angular applications at Braune Digital.
4
-
5
- **This guide is a work in progress and will be updated regularly.**
6
-
7
- > **Enforcement:** most rules below are enforced automatically by
8
- > `@ethlete/eslint-plugin` - run your lint task with `--fix` and fix what it reports,
9
- > rather than hand-checking. The `styleguide` guide that ships alongside this file
10
- > distills the judgment calls lint can't check.
11
-
12
- ## TL;DR
13
-
14
- Key standards at a glance. **Most are enforced by lint** (see [Enforced by lint](#enforced-by-lint)); the rest are judgment calls documented in the sections below. Not exhaustive.
15
-
16
- - **Types**: `unknown` not `any`; `type` not `interface`; `as const` objects not `enum`; `T`-prefixed descriptive generics; regular value imports (no `import type`); narrow with type guards.
17
- - **Code**: `const` by default (`let` only to reassign, never `var`); one declaration per statement; `===` / `!==`; arrow fns standalone, methods in classes; max two params (object param beyond that).
18
- - **State**: signals for synchronous state, RxJS for async - always unsubscribe; effects for signal-driven side effects.
19
- - **Angular**: `ViewEncapsulation.None`; `inject()` not constructor injection; no legacy lifecycle hooks - prefer `constructor` + `afterNextRender` + `DestroyRef.onDestroy`; no function calls in templates except signal reads.
20
- - **Naming & structure**: name things after what they do; routing components end in `-view`; mirror routes in folders; keep related files together.
21
- - **Changesets**: one focused, imperative-mood entry per change (see the `changeset` skill).
22
-
23
- ---
24
-
25
- ## Enforced by lint
26
-
27
- Run your lint task with `--fix` - the rules below are enforced (and mostly auto-fixed) by `@ethlete/eslint-plugin`. This table is a lookup for _why_ a fix was applied; don't hand-check these.
28
-
29
- | Rule | Enforced by |
30
- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
31
- | No `any` / `$any()`; use `unknown` + type guards | `@typescript-eslint/no-explicit-any`, `@angular-eslint/template/no-any` |
32
- | No property bindings for static strings/booleans (`[etIcon]="'foo'"`, `[isReadonly]="true"`) - use static attributes | `@angular-eslint/template/prefer-static-string-properties`, `ethlete/prefer-static-boolean-properties` |
33
- | No `interface` - use `type` | `@typescript-eslint/consistent-type-definitions` |
34
- | No `enum` - use an `as const` object + derived union | `no-restricted-syntax` |
35
- | No `var`; prefer `const`; one declaration per statement | `no-var`, `prefer-const`, `one-var` |
36
- | `===` / `!==` only | `eqeqeq` |
37
- | Max two function parameters | `max-params` |
38
- | No `import type` / inline `type` specifiers | `ethlete/no-type-only-import` |
39
- | Generic params `T`-prefixed (`TValue`), never bare `T` | `@typescript-eslint/naming-convention` |
40
- | No `async`/`await` - use RxJS | `ethlete/no-async-await` |
41
- | Arrow fns standalone; methods in classes; no arrow-fn class props; no `function` keyword | `no-restricted-syntax` |
42
- | Blank line before `return` in multi-line guard clauses | `ethlete/guard-return-newline` |
43
- | No trivially-inferable explicit return types | `ethlete/no-trivial-return-type` |
44
- | camelCase / PascalCase / UPPER*CASE; no `#` or `*` member prefixes | `@typescript-eslint/naming-convention`, `ethlete/no-leading-underscore-class-member` |
45
- | No SCREAMING_CASE locals; class constants `readonly` + SCREAMING_CASE | `ethlete/no-screaming-case-local`, `ethlete/class-constant-property` |
46
- | No `readonly` on reactive members (signals, inputs, computed, inject) | `ethlete/no-readonly-signal` |
47
- | No `static` members (except `ngTemplateContextGuard`, which Angular requires to be static) | `no-restricted-syntax` |
48
- | Injected providers `private` by default, `protected` only when template/host-visible; explicit accessibility on reachable members | `ethlete/inject-member-accessibility`, `ethlete/template-member-accessibility` |
49
- | No `inject(X).member` chaining; no pure member aliases | `ethlete/no-inject-chain`, `ethlete/no-member-alias` |
50
- | No module-scope destructuring of a factory call; `@__PURE__` on module-scope calls in library source | `ethlete/no-impure-top-level-provider` |
51
- | No redundant `@internal` on `private`/`protected` members | `ethlete/no-redundant-internal` |
52
- | Observable vars/props end with `$` | `ethlete/require-dollar-suffix` |
53
- | No body in `subscribe()`; no `subscribe` in `pipe()`; no RxJS in `effect()`/`computed()` | `ethlete/no-subscribe-with-body`, `ethlete/no-subscribe-in-pipe`, `ethlete/no-rxjs-in-effect` |
54
- | Effect teardown goes through `onCleanup` (or `DestroyRef`), never a returned cleanup function | `ethlete/no-effect-cleanup-return` |
55
- | `ViewEncapsulation.None` | `ethlete/require-view-encapsulation-none` |
56
- | No legacy lifecycle hooks; no legacy Angular decorators (`@HostBinding`, `@Input`, …) | `no-restricted-syntax`, `ethlete/no-legacy-angular-decorators` |
57
- | No `@Injectable` / `@Service`; no route guards; no resolvers | `no-restricted-syntax` |
58
- | Outputs: no `on` prefix, no native event names, present-tense naming (`playerSelect`, not `playerSelected`) | `@angular-eslint/no-output-on-prefix`, `@angular-eslint/no-output-native`, `ethlete/prefer-present-tense-output` |
59
- | Inputs/models not named after a global HTML attribute (`title`, `id`, `hidden`, `role`, …) - collides with the host element | `ethlete/no-native-html-input-name` |
60
- | No logic in pipe `transform` | `ethlete/no-pipe-logic` |
61
- | Consistent class-member + decorator-metadata order; concise host-directive / style metadata | `ethlete/class-member-order`, `ethlete/angular-decorator-property-order`, `ethlete/prefer-concise-angular-host-directives`, `ethlete/prefer-concise-angular-style-metadata` |
62
- | No interpolated template literal above an inline `template:` - it kills Angular language service completions in that file | `ethlete/no-template-literal-before-inline-template` |
63
- | Routing components: `-view` path + `ViewComponent` class name | `ethlete/enforce-routing-view-naming` |
64
- | No direct `document` / `window` / DOM query / observers / cookies / `window.location` | `no-restricted-globals`, `ethlete/no-direct-dom-manipulation`, `ethlete/no-dom-query`, `ethlete/no-native-observers`, `ethlete/no-document-cookie`, `ethlete/no-window-location` |
65
- | No barrel (index) imports - import from the source file | `no-restricted-syntax` |
66
- | Prefer `@ethlete/core` utils over raw APIs (clone/equal, rxjs timers, media query, viewport size, SEO, locale, router state) | `ethlete/prefer-clone-equal`, `ethlete/prefer-rxjs-timer`, `ethlete/prefer-match-media`, `ethlete/prefer-viewport-size`, `ethlete/no-angular-seo-services`, `ethlete/no-locale-id`, `ethlete/no-angular-router-api` |
67
-
68
- ## Accessibility & visibility
69
-
70
- Lint auto-fixes injected providers to `private` and flags template/host-visible members, but the _intent_ is yours:
71
-
72
- - Injected provider → `private` by default; `protected` **only** when referenced from the HTML template or a `host:` binding expression; **drop the modifier entirely** if keeping it `private` would force a member alias (a property whose sole purpose is re-exposing a nested member - expose the injected symbol directly instead).
73
- - Never add a member that only **aliases** another member's nested property (`foo = this.thing.foo`) - widen the source member's visibility and use it directly.
74
- - For a member that must stay technically public purely for cross-class/DI use (e.g. a self-registration method called by a sub-directive), keep it `public` and tag `/** @internal */` so build tooling strips it from the published `.d.ts`. Never put `@internal` on `private`/`protected` members.
75
-
76
- ## Naming & functions with intent
77
-
78
- Case conventions, the `T` generic prefix, arrow-vs-method, and the two-param limit are all lint-enforced. What lint can't judge:
79
-
80
- - **Name things after what they do**, not after the mechanism. `onChange` that posts a form → `sendFormValueToApi`. Descriptive generics (`TValue`, `TResult`), descriptive constant/variable names.
81
- - When a function needs more than two parameters, take a single **object parameter** with a named `type` rather than widening the signature.
82
-
83
- ```ts
84
- // ❌ name describes the trigger, not the behaviour
85
- const onChange = () => sendToApi(myForm.getRawValue());
86
-
87
- // ✅ name describes the behaviour
88
- const sendFormValueToApi = () => sendToApi(myForm.getRawValue());
89
-
90
- // ✅ object param instead of a third positional arg
91
- type LogMessageConfig = { scope: string; logLevel: string };
92
- const logMessage = (message: string, config: LogMessageConfig) => {};
93
- ```
94
-
95
- ## TypeScript Config
96
-
97
- - Ensure `strict` is set to `true`.
98
- - Ensure `noUncheckedIndexedAccess` is set to `true`.
99
- - Keep the remaining defaults provided by NX
100
- - Set `resolveJsonModule` to `true` only if necessary. JSON files should be fetched via HTTP requests.
101
- - Set `esModuleInterop` to `true` only if necessary.
102
-
103
- ## Signals vs RxJS
104
-
105
- - **Synchronous state → signals. Asynchronous work → RxJS.** Never model sync state with a `BehaviorSubject`; never use RxJS just to read a value back synchronously. Bridge with `toSignal()` / `toObservable()` instead of copying values across with `.subscribe()`.
106
- - **Always unsubscribe.** Prefer `takeUntilDestroyed()`; otherwise `take` / `takeUntil` / `takeWhile`, and place the limiting operator **last** in the pipe. Side effects go in `tap()`, not the `subscribe()` callback. (Lint blocks bodies in `subscribe()` but cannot prove you unsubscribe.)
107
- - Don't reach for RxJS inside `effect()` / `computed()` - model the stream with `toObservable(signal).pipe(switchMap(...))` instead of subscribing per run.
108
-
109
- ```ts
110
- // ❌ sync state as a subject // ✅ signal
111
- const count$ = new BehaviorSubject(0);
112
- const count = signal(0);
113
-
114
- // ✅ react to a signal without subscribing inside an effect
115
- toObservable(page)
116
- .pipe(
117
- switchMap((p) => fetchPage(p)),
118
- tap(handle),
119
- takeUntilDestroyed(),
120
- )
121
- .subscribe();
122
- ```
123
-
124
- ## Angular patterns
125
-
126
- Lint covers the mechanical Angular rules (`ViewEncapsulation.None`, no legacy hooks/decorators, no native DOM/`window`, output naming, class-member + decorator-metadata order, no `@Injectable` / `@Service` / guards / resolvers). The judgment calls:
127
-
128
- - **No function calls in template value bindings except signal reads** - a method in a binding re-runs every change-detection cycle. Move it into a `computed()` and bind that. Event bindings (`(click)="save()"`) are fine.
129
- - **Prefer the `constructor`** (runs in the injection context) over `ngOnInit` / `ngOnDestroy`: `afterNextRender()` for first-render work, `inject(DestroyRef).onDestroy(...)` for cleanup.
130
- - **Prefer utility functions + provider factories over services** - `createProvider` / `createRootProvider` and the `injectX()` helper pattern from `@ethlete/core`, not an `@Injectable` (or its Angular 22 `@Service` shorthand).
131
- - **Most directives can be plain functions.** Move the logic into a function so it's reusable without applying a directive; keep a directive only when a host element genuinely needs it. Avoid common input/output names that clash with the host component.
132
- - **Pipes carry no logic** - put it in a utility function called from a `computed()`; most pipes can be replaced by a `computed` outright.
133
- - **Components**: inline template/styles for small components, external `.html` / `.css` files for complex ones.
134
-
135
- ```html
136
- <!-- ❌ runs every CD cycle -->
137
- <button [disabled]="isDisabled()">
138
- <!-- ✅ computed signal -->
139
- <button [disabled]="disabled()"></button>
140
- </button>
141
- ```
142
-
143
- ## General File Structure
144
-
145
- Given are the following routes:
146
-
147
- ```ts
148
- import { Routes } from '@angular/router';
149
-
150
- export const SHOP_ROUTES: Routes = [
151
- {
152
- path: 'items',
153
- loadComponent: () => import('./items-list-view/items-list-view.component').then((m) => m.ItemsListViewComponent),
154
- },
155
- {
156
- path: 'items/:id',
157
- loadComponent: () => import('./item-detail-host-view/item-detail-host-view.component').then((m) => m.ItemDetailHostViewComponent),
158
- children: [
159
- {
160
- path: '',
161
- loadComponent: () => import('./item-detail-host-view/item-detail-view/item-detail-view.component').then((m) => m.ItemDetailViewComponent),
162
- }
163
- {
164
- path: 'reviews',
165
- loadComponent: () => import('./item-detail-host-view/item-reviews-view/item-reviews-view.component').then((m) => m.ItemReviewsViewComponent),
166
- }
167
- ]
168
- }
169
- ];
170
- ```
171
-
172
- - Organize folder and file structure to mirror Angular routes.
173
- - Name routing components with the suffix `view` (e.g., `settings-view.component.ts`).
174
- - Place reusable components in a `components` directory.
175
- - Always include an `index.ts` file to export components.
176
- - For components with inline templates, place them directly in the `components` directory without nesting.
177
- - Place child components specific to a parent component in a `partials` directory.
178
- - Restrict the usage of partial components to their parent component only. For example, the `item-image` and `item-price` components should only be used within the `item-card` component.
179
- - Similarly, components like `item-card` should only be used within their parent view (`items-list-view`). If needed elsewhere, move them higher in the directory structure.
180
- - Create and place directives, pipes, and utilities in the same directory as the component that uses them. For example, place `item-status.pipe.ts` in the `item-card` directory.
181
- - Position services and providers in the directory of the view component that includes them in its `providers` array. For example, place `item-detail-api.service.ts` in the `item-detail-host-view` directory.
182
- - Use simple file names for utility files without the `.utils.ts` suffix. For example, use `items-list-filter-form.ts` for files containing form configurations.
183
- - Always put storybook files in a `storybook` directory within the component directory. This directory should contain the storybook component and any dummy data needed for the storybook.
184
-
185
- ```plaintext
186
- shop/
187
- ├── items-list-view/
188
- │ ├── components/
189
- │ │ ├── item-card/
190
- │ │ │ ├── partials/
191
- │ │ │ │ ├── item-image/
192
- │ │ │ │ │ ├── item-image.component.ts
193
- │ │ │ │ │ ├── item-image.component.html
194
- │ │ │ │ │ ├── index.ts ✅ (exports the item image component)
195
- │ │ │ │ ├── item-price/
196
- │ │ │ │ │ ├── item-price.component.ts
197
- │ │ │ │ │ ├── item-price.component.html
198
- │ │ │ │ │ ├── index.ts ✅ (exports the item price component)
199
- │ │ │ ├── storybook/
200
- │ │ │ │ ├── item-card.component.stories.ts
201
- │ │ │ │ ├── item-card-storybook-data.ts
202
- │ │ │ ├── item-card.component.ts
203
- │ │ │ ├── item-card.component.html
204
- │ │ │ ├── item-status.pipe.ts
205
- │ │ │ ├── index.ts ✅ (exports the item card component)
206
- │ ├── items-list-view.component.ts
207
- │ ├── items-list-view.component.html
208
- │ ├── items-list-filter-form.ts
209
- ├── items-detail-host-view/
210
- │ ├── item-detail-host-view.component.ts
211
- │ ├── item-detail-host-view.component.html
212
- │ ├── item-detail-api.service.ts
213
- │ ├── item-data.provider.ts
214
- │ ├── item-detail-view/
215
- │ │ ├── item-detail-view.component.ts
216
- │ │ ├── item-detail-view.component.html
217
- │ ├── item-reviews-view/
218
- │ │ ├── item-reviews-view.component.ts
219
- │ │ ├── item-reviews-view.component.html
220
- ```
221
-
222
- #### Miscellaneous
223
-
224
- - Super generic components and other logic (e.g., buttons, inputs, etc.) should be placed in a uikit directory.
225
- - Things placed in the uikit directory should be as generic as possible and should not contain any business logic (dumb components).
226
- - Components and logic needed for the app shell (e.g., header, footer, etc.) should be placed in a shell directory.
227
- - To reduce the risk of circular dependencies, avoid importing from the parent directory in a subdirectory.
228
-
229
- ### NX Workspace
230
-
231
- - Apps should be placed in the `apps` directory. They should contain the main application logic and should be as slim as possible. No business logic should be placed in the app directory besides the app component.
232
- - Libraries should be placed in the `libs` directory.
233
- - They should be `buildable`.
234
- - They should have a clear import path (e.g., `@org/domain/my-app` or `@org/uikit`). The import path can be found in the project.json file and should be checked after generation.
235
- - They should have a clear name (e.g. `domain-my-app` or `uikit`). The name can be found in the project.json file and should also be checked after generation.
236
-
237
- The following abstract example shows a correct file structure:
238
-
239
- ```plaintext
240
- apps/
241
- │ ├── my-app/
242
- │ │ ├── src/...
243
- │ ├── other-app/
244
- │ │ ├── src/...
245
- libs/
246
- │ ├── assets/
247
- │ │ ├── src/...
248
- │ ├── domain/
249
- │ │ ├── my-app/
250
- │ │ │ ├── src/...
251
- │ │ ├── other-app/
252
- │ │ │ ├── src/...
253
- │ ├── env/
254
- | │ ├── src/...
255
- │ ├── queries/
256
- │ │ ├── src/...
257
- │ ├── types/
258
- │ │ ├── src/...
259
- │ ├── uikit/
260
- │ │ ├── src/...
261
- ```
262
-
263
- - The `assets` library should contain all assets used across applications.
264
- - The `domain` library should contain all domain-specific logic. Each domain should have its own library.
265
- - The `env` library should contain the `environment` files. This way they can be shared across applications and libraries.
266
- - The `queries` library should contain all queries used across applications.
267
- - The `types` library should contain common types used across applications and libraries (e.g. API types).
268
- - The `uikit` library should contain all shared components and logic.
269
-
270
- ### Assets
271
-
272
- - Place all assets in the `assets` library.
273
- - Given the apps `my-app` and `other-app`, the assets library should be structured as follows:
274
-
275
- ```plaintext
276
- assets/
277
- │ ├── my-app/
278
- │ │ ├── build/
279
- │ │ ├── serve/
280
- │ │ ├── storybook/
281
- │ ├── other-app/
282
- │ │ ├── build/
283
- │ │ ├── serve/
284
- │ │ ├── storybook/
285
- │ ├── shared/
286
- │ │ ├── build/
287
- │ │ ├── serve/
288
- │ │ ├── storybook/
289
- ```
290
-
291
- - The storybook directory is optional and can be used for assets that are only needed in Storybook (e.g., dummy data, storybook-specific assets).
292
- - The serve directory is optional and can be used for assets that are only needed during development (e.g., placeholder assets). These assets are not included in the build process.
293
- - The build directory should contain all assets that are needed in production.
294
- - Adjust each app's `project.json` file to include the assets as follows:
295
-
296
- ```json
297
- {
298
- "build": {
299
- "executor": "@angular/build:application",
300
- "outputs": ["{options.outputPath}"],
301
- "options": {
302
- // ...
303
- "assets": [
304
- {
305
- "input": "libs/assets/src/APP_NAME_HERE/build",
306
- "glob": "**/*",
307
- "output": "assets" // There should be no separate build directory for build assets.
308
- },
309
- {
310
- "input": "libs/assets/src/APP_NAME_HERE/serve",
311
- "glob": "**/*",
312
- "output": "assets/serve"
313
- },
314
- // If shared assets are needed, include them as well
315
- {
316
- "input": "libs/assets/src/shared/build",
317
- "glob": "**/*",
318
- "output": "assets/shared"
319
- },
320
- {
321
- "input": "libs/assets/src/shared/serve",
322
- "glob": "**/*",
323
- "output": "assets/shared/serve"
324
- }
325
- ]
326
- // ...
327
- },
328
- "configurations": {
329
- "production": {
330
- "assets": [
331
- {
332
- "input": "libs/assets/src/APP_NAME_HERE/build",
333
- "glob": "**/*",
334
- "output": "assets"
335
- },
336
- // If shared assets are needed, include them as well
337
- {
338
- "input": "libs/assets/src/shared/build",
339
- "glob": "**/*",
340
- "output": "assets/shared"
341
- }
342
- ]
343
- },
344
- // If you have a Storybook setup, you can add configurations for development and production environments.
345
- // Make sure to add zone.js as a polyfill. This is currently still required for Storybook to work properly.
346
- "storybook-development": {
347
- "polyfills": ["zone.js"],
348
- "assets": [
349
- {
350
- "input": "libs/assets/src/APP_NAME_HERE/serve",
351
- "glob": "**/*",
352
- "output": "assets/serve"
353
- },
354
- {
355
- "input": "libs/assets/src/APP_NAME_HERE/storybook",
356
- "glob": "**/*",
357
- "output": "assets"
358
- },
359
- {
360
- "input": "libs/assets/src/APP_NAME_HERE/build",
361
- "glob": "**/*",
362
- "output": "assets"
363
- },
364
- // If shared assets are needed, include them as well
365
- {
366
- "input": "libs/assets/src/shared/build",
367
- "glob": "**/*",
368
- "output": "assets/shared"
369
- },
370
- {
371
- "input": "libs/assets/src/shared/serve",
372
- "glob": "**/*",
373
- "output": "assets/shared/serve"
374
- },
375
- {
376
- "input": "libs/assets/src/shared/storybook",
377
- "glob": "**/*",
378
- "output": "assets/shared/storybook"
379
- }
380
- ]
381
- },
382
- "storybook-production": {
383
- "polyfills": ["zone.js"],
384
- "assets": [
385
- {
386
- "input": "libs/assets/src/APP_NAME_HERE/storybook",
387
- "glob": "**/*",
388
- "output": "assets"
389
- },
390
- {
391
- "input": "libs/assets/src/APP_NAME_HERE/build",
392
- "glob": "**/*",
393
- "output": "assets"
394
- },
395
- // If shared assets are needed, include them as well
396
- {
397
- "input": "libs/assets/src/shared/build",
398
- "glob": "**/*",
399
- "output": "assets/shared"
400
- },
401
- {
402
- "input": "libs/assets/src/shared/storybook",
403
- "glob": "**/*",
404
- "output": "assets/shared/storybook"
405
- }
406
- ]
407
- }
408
- }
409
- }
410
- }
411
- ```
412
-
413
- #### Asset examples
414
-
415
- - Given the `cat.jpg` image used in the `my-app` application, the asset should be placed in the `libs/assets/src/my-app/build` directory.
416
- - Subdirectories can be used to organize assets further, such as `libs/assets/src/my-app/build/images/cat.jpg`.
417
-
418
- ```plaintext
419
- assets/
420
- │ ├── my-app/
421
- │ │ ├── build/
422
- │ │ │ ├── images/
423
- │ │ │ │ ├── cat.jpg
424
- ```
425
-
426
- This way, the asset can be accessed in the application as follows:
427
-
428
- ```html
429
- <img src="assets/images/cat.jpg" alt="Cat Image" />
430
- ```
431
-
432
- - If the asset is only needed during development (e.g., as a mock placeholder image)
433
- - Place it in the `libs/assets/src/my-app/serve/images/cat.jpg`.
434
- - The asset can then be accessed in the application as follows:
435
-
436
- ```html
437
- <img src="assets/serve/images/cat.jpg" alt="Cat Image" />
438
- ```
439
-
440
- **Keep in mind** that the `serve` directory is optional and can be used for assets that are only needed during development. These assets are not included in the build process.
441
-
442
- ### Storybook
443
-
444
- - If extra components are needed to render a component in Storybook, they should be placed in a `storybook` directory within the component directory.
445
- - **Never** export storybook specific logic from the component directory.
446
-
447
- ```plaintext
448
- settings-form/
449
- │ ├── storybook/
450
- │ │ ├── settings-form.storybook.component.ts
451
- │ │ ├── settings-form.storybook.component.html
452
- │ │ ├── settings-form-dummy-data.ts
453
- │ │ ├── index.ts ✅ (exports the storybook component for use in the .stories.ts file + dummy data if needed)
454
- │ ├── settings-form.component.ts
455
- │ ├── settings-form.component.stories.ts
456
- │ ├── settings-form.component.html
457
- │ ├── index.ts ✅ (exports the form component)
458
- ```
459
-
460
- ## Changesets
461
-
462
- - Use `@changesets` to manage changelogs.
463
- - **Do not** create a changeset for irrelevant changes (e.g., formatting, comments, internal refactoring).
464
- - **Do not** create a changeset for fixes to features that have not yet been released.
465
- - **Do not** include multiple changes in a single changeset. Each changeset should contain only one change.
466
- - **A changeset note is a TL;DR: one sentence, two at most, under 40 words.** Never a second paragraph, no matter how much work the change took. It is the line a consumer skims to decide whether the release affects them - not a summary of your work. Mechanism, API inventories, caveats and rationale belong in the docs or the commit body, never here.
467
- - Create changesets for dependency updates if they are relevant to the project (e.g., major version updates).
468
- - Write changesets in the imperative mood. For example:
469
- - Add button component
470
- - Fix spacing issues inside buttons
471
- - Update to Angular 20
472
-
473
- ### Examples
474
-
475
- Use the following legend to determine the type of changeset you should create.
476
- **Do not** include the emoji in your changeset message; it is only used here for clarity.
477
-
478
- - ✨ **Major Change**: For breaking changes that require updates or modifications by consumers of the project.
479
- - Example: Remove settings view from the app.
480
-
481
- - 🚀 **Minor Change**: For adding new features or functionality in a backward-compatible way.
482
- - Example: Add support for dark mode in components.
483
-
484
- - 🐛 **Patch Change**: For bug fixes or small adjustments that do not introduce breaking changes.
485
- - Example: Fix button alignment issue.
486
-
487
- #### Valid Changesets
488
-
489
- The following changesets are valid and should be created:
490
-
491
- - ✨ Migrate to NX 20
492
- - 🚀 Add button component
493
- - 🚀 Add text input component
494
- - 🚀 Add settings view
495
- - 🚀 Add uikit library
496
- - 🚀 Add login app
497
- - 🚀 Update TypeScript configurations to allow usage of ES2027
498
- - 🚀 Make CI pipelines faster by caching `node_modules`
499
-
500
- #### Special Cases
501
-
502
- For these types of changesets, ensure that the feature you are working on has already been released (and can be found in the changelog). If the feature is not yet released, **do not** create a changeset for it.
503
-
504
- - ✨ Change route of settings view from `/settings` to `/user/settings`
505
- - ✨ Rename `MatchComponent` to `MatchupComponent`
506
- - 🚀 Add general tab to settings view
507
- - 🐛 Fix issue with settings view not loading on mobile devices
508
- - 🐛 Enhance button component rendering to improve performance
509
- - 🐛 Fix typo in settings view headline
510
- - 🐛 Fix linting issues inside progress bar component
511
-
512
- #### Invalid Changesets
513
-
514
- The following changesets are generally invalid and should **not** be created:
515
-
516
- - Cleanup code inside button component (no changeset needed).
517
- - Update Angular to 19.1.1 from 19.1.0 (it's a patch update and does not require a changeset).
518
- - Move button component to a new directory (if it remains in the same NX library, no changeset is needed. Otherwise, it's a ✨).
519
- - Run Prettier on all files (no changeset needed).
520
- - Fix button style on hover **and** update slider component bar thickness (two changes should not be combined into one changeset).