gravitee-api-management / gravitee-apim-portal-webui-next
AGENTS.md469 starsChanged 5 months agoApache-2.0View on GitHub
Root conventions also apply: read ../AGENTS.md; where they disagree, the closest file wins for its directory and below. If your tool cannot read it, restart it from the repository root. Angular-specific conventions for Gravitee repositories. Global engineering, security, accessibility, TypeScript, and TDD rules still apply.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,542 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository31 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .ai/AGENTS.mdAGENTS.md
- gravitee-apim-common/AGENTS.mdAGENTS.md
- gravitee-apim-console-webui/AGENTS.mdAGENTS.md
- gravitee-apim-definition/AGENTS.mdAGENTS.md
- gravitee-apim-distribution/AGENTS.mdAGENTS.md
- gravitee-apim-gateway/AGENTS.mdAGENTS.md
- gravitee-apim-plugin/AGENTS.mdAGENTS.md
- gravitee-apim-portal-webui/AGENTS.mdAGENTS.md
- gravitee-apim-reporter/AGENTS.mdAGENTS.md
- gravitee-apim-repository/AGENTS.mdAGENTS.md
- gravitee-apim-rest-api/AGENTS.mdAGENTS.md
- .ai/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- gravitee-apim-common/CLAUDE.mdCLAUDE.md
- gravitee-apim-console-webui/CLAUDE.mdCLAUDE.md
- gravitee-apim-definition/CLAUDE.mdCLAUDE.md
- gravitee-apim-distribution/CLAUDE.mdCLAUDE.md
- gravitee-apim-gateway/CLAUDE.mdCLAUDE.md
- gravitee-apim-plugin/CLAUDE.mdCLAUDE.md
- gravitee-apim-portal-webui/CLAUDE.mdCLAUDE.md
- gravitee-apim-portal-webui-next/CLAUDE.mdCLAUDE.md
- gravitee-apim-reporter/CLAUDE.mdCLAUDE.md
- gravitee-apim-repository/CLAUDE.mdCLAUDE.md
- gravitee-apim-rest-api/CLAUDE.mdCLAUDE.md
- .cursor/rules/graphene.mdCursor rule
- .cursor/rules/graphene-snippets/context-sidebar-detail-page.tsxCursor rule
- .cursor/rules/graphene-snippets/creation-wizard-page.tsxCursor rule
- .cursor/rules/graphene-snippets/data-table-list-page.tsxCursor rule
- .cursor/rules/graphene-snippets/json-schema-form-simple.tsxCursor rule
- .cursor/rules/graphene-snippets/json-schema-form-with-meta.tsxCursor rule
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
27 rules. About 0 are common, 20 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈20
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
Use the repo's documented scripts for build, test, lint, and serve.
- Distinctive: line 22
Prefer the Angular patterns already established in the repo.
- Distinctive: line 26
Keep components focused. Containers orchestrate data and side effects.
- Distinctive: line 27
Prefer typed inputs, outputs, forms, services, and API models.
- Distinctive: line 28
Prefer signals or template async binding for UI state.
- Distinctive: line 31
Do not create nested subscriptions.
- Distinctive: line 36
Use the repo's established Angular template syntax.
- Distinctive: line 37
Avoid method calls in templates for derived state.
- Distinctive: line 38
Use semantic HTML and accessible interactions before adding ARIA-only custom widgets.
- Distinctive: line 39
Use design-system tokens, CSS variables, and existing component APIs.
- Distinctive: line 40
Do not use ::ng-deep / :ng-deep unless there is no supported component API, token, or documented styling hook.
- Distinctive: line 44
Use typed reactive forms where the repo supports them.
- Distinctive: line 49
Use the repo's existing Angular test stack and utilities.
- Distinctive: line 50
Test behaviour, not implementation details.
- Distinctive: line 51
Prefer component harnesses or stable user-facing selectors such as roles, labels, and data-testid where available.
- Distinctive: line 54
Keep async tests deterministic.
- Distinctive: line 64
Treat changes to any of these as compatibility-sensitive — call them out explicitly in the PR description and final response summary:
- Distinctive: line 86
Keep each id on the control or value it identifies.
- Distinctive: line 87
Write an id as a string literal.
- Distinctive: line 107
When no existing design-system component or pattern fits, suggest collaborating with UX rather than inventing a new one.
- Very specific: line 122
Use lodash for common transforms (kebabCase, isEmpty, isEqual, merge, ...) before writing a new utility.
- Very specific: line 123
Use fixture.destroy() instead of discardPeriodicTasks.
- Very specific: line 131
Always use the app theme via @use '.../scss/theme' as app-theme.
- Very specific: line 137
Use the typography classes from typography.scss (.next-gen-h1, .next-gen-body, ...) as the single source for type styles.
- Very specific: line 149
All user-facing text in portal components is localized.
- Very specific: line 176
Use the gmd-* prefix for elements or components on the Gravitee Markdown (GMD) surface (wrappers, overrides).
- Very specific: line 177
Use the gd-* prefix only for elements or components belonging to the gravitee-dashboard library (charts, dashboard widgets) — never for …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!--
Generated by gravitee-ai. Do not edit directly.
Edit the source rules and re-run: gbuddy setup
Source rules:
- context/rules/tech/angular.md
- context/rules/tech/typescript.md
- context/rules/tech/ui-test-ids.md
- .ai/rules/apim-angular.md
- .ai/rules/portal-webui-next.md
-->Root conventions also apply: read ../AGENTS.md; where they disagree, the closest file wins for its directory and below. If your tool cannot read it, restart it from the repository root.
Angular Conventions
Angular-specific conventions for Gravitee repositories. Global engineering, security, accessibility, TypeScript, and TDD rules still apply.
Follow the repo
- Match the repository's Node version, package manager, lockfile, Angular version, formatter, lint rules, folder structure, naming style, and test stack. Do not introduce a second convention.
- Use the repo's documented scripts for build, test, lint, and serve. Do not invent new entrypoints unless explicitly required.
- Prefer the Angular patterns already established in the repo. Use standalone components, signals, and modern control flow where the repo has adopted them.
Components, state, and RxJS
- Keep components focused. Containers orchestrate data and side effects; presentational components receive inputs and emit outputs.
- Prefer typed inputs, outputs, forms, services, and API models.
- Prefer signals or template async binding for UI state. Avoid duplicate reactive state for the same value.
- For async data, prefer rxResource or the repo's equivalent where available, because it co-locates loading/error/value. Fall back to the async pipe for template-only values, and to toSignal() when the class needs a signal.
- Reserve subscribe() for side effects such as navigation, dialogs, analytics, or toasts, using the repo's existing destroy pattern.
- Do not create nested subscriptions. Use the appropriate RxJS flattening operator instead.
- On Angular code using dependency injection, prefer the repo's established style. In modern Angular code, prefer inject() where it improves clarity.
Templates, styling, and accessibility
- Use the repo's established Angular template syntax. Prefer modern control flow (@if, @for, @switch) where the repo has adopted it.
- Avoid method calls in templates for derived state. Use computed values, signals, observables, or pipes.
- Use semantic HTML and accessible interactions before adding ARIA-only custom widgets.
- Use design-system tokens, CSS variables, and existing component APIs. Do not hard-code colours, spacing, or one-off visual patterns unless already local convention.
- Do not use ::ng-deep / :ng-deep unless there is no supported component API, token, or documented styling hook.
Forms
- Use typed reactive forms where the repo supports them.
- Validate at the boundary and surface errors with accessible, user-visible messaging.
Testing
- Use the repo's existing Angular test stack and utilities.
- Test behaviour, not implementation details. Do not assert private state, framework internals, or ng-reflect-*.
- Prefer component harnesses or stable user-facing selectors such as roles, labels, and data-testid where available.
- For HTTP and service wiring, prefer the repo's existing HTTP testing utilities rather than mocking away request/response behaviour.
- Exception to Follow the repo: for components using
rxResource(or other resource-based async data), use the provider-style HTTP testing setup (provideHttpClient+provideHttpClientTesting), even where the repo's other tests use the module style. Module-style setups such asHttpClientTestingModulehave hung such tests onwhenStable(). - Keep async tests deterministic. Await async work explicitly; avoid sleeps, wall-clock assumptions, real network calls, and order-dependent assertions.
- For bug fixes, add or update a regression test where practical.
Shared UI and design system
- Reuse existing project utilities, design-system components, and Angular Material/Gio patterns before creating new helpers or UI components.
- Extend the design system; do not fork or duplicate it inside feature code.
Compatibility-sensitive surfaces
Treat changes to any of these as compatibility-sensitive — call them out explicitly in the PR description and final response summary:
- Public routes, navigation behaviour, guards, and permissions.
- Generated API models, DTOs, and on-wire data shapes.
- Form field names, validation behaviour, and submitted payloads.
- Design-system components, tokens, shared styles, and global theme behaviour.
- Accessibility semantics, keyboard behaviour, and focus management.
- Build configuration, environment files, package manager files, and CI configuration.
TypeScript Conventions
TypeScript-specific conventions; the general engineering rules (clean code, fail-loud boundaries) still apply.
- Match the repository's module system and
tsconfig.jsonstrictness. In an existing package, do not loosen or tighten these settings unless asked. A new package inside an existing repository follows the repository; default to ESM withstrictandnoUncheckedIndexedAccessonly where the repository has no established setting. - No
any— useunknownand narrow with type guards. - Type the boundaries (function signatures, exported types); let inference handle the rest.
UI Test Ids
Automated tests, including end-to-end suites in other repositories, select elements by data-testid. A changed or removed id breaks them without failing any test here. This holds whether or not a suite covers the screen today.
- Every element your change adds, or whose markup it rewrites, that reads or writes data carries a
data-testid: form controls, toggles, selects, displayed application data (status, names, counts), and the buttons that create, save, delete or change state. A styling, formatting or mechanical change does not require ids on elements it does not otherwise touch. - Keep each id on the control or value it identifies; an id on a wrapper does not count. Replacing a component that keeps the same job is not a removal: its id stays. Do not strip ids from production builds.
- Write an id as a string literal. Where it must vary per item, keep a literal prefix and vary only the suffix, taken from a stable key, not the position or display text.
- While its element stays in the product, never rename or remove an existing
data-testidvalue, built at run time or not, even when its name is poor, its case is inconsistent, or it no longer fits its context. Cleaning up the code around it does not extend to the id. - When you move markup into a shared component, the original screen keeps rendering its original ids. A reusable component takes the id or prefix from its caller (an input or prop) and hard-codes none; when the caller passes none, the inner control renders without one. The original caller passes the old value, new callers may use new ones.
- Remove an id only when its element leaves the product. Name each removed id, or the prefix of a removed family, with the reason, in the pull request description (the commit message when there is no pull request yet) and in your final summary, as a compatibility-sensitive change.
APIM Angular Conventions
Absolutes
The shared Angular rule's "where the repo has adopted them" conditions are settled here — these are binary:
- Standalone: new components, directives, and pipes are standalone — on this Angular version that is the default, so do not write
standalone: true. Do not convert existingstandalone: falsedeclarations as a side effect of an unrelated change. - Signals first: signals for local state (
signal()), derived state (computed()), inputs (input()/input.required()), and outputs (output()). - New control flow strictly:
@if,@for,@switch— never*ngIfor*ngFor.
Components
- Class member order: 1.
private readonlyinjections (inject()), 2. inputs, 3. outputs, 4. state, 5. computed (computed(),toSignal(),rxResource()), 6. methods (public then private). - DI: always
private readonly service = inject(ServiceName);— never constructor injection, and no constructor orngOnInitsubscription setup. - The destroy pattern the shared Angular rule refers to is
takeUntilDestroyed(this.destroyRef)— every.subscribe()gets it. - When no existing design-system component or pattern fits, suggest collaborating with UX rather than inventing a new one.
- The consuming-observables decision table,
rxResourcepatterns, and exemplar components live in.ai/guides/angular-async-patterns.md(a repository-root path) — read it before wiring async data.
Dialogs
- Strictly type dialog opens:
this.matDialog.open<ComponentType, InputType, OutputType>(...).
Naming
- Functions: verb + noun that reflects the operation (extract, collect, derive, compute, find).
- Variables: name the concept they hold, not the type; no contractions (
comp,el,attr) unless established in the file. - Booleans:
is/has/can/shouldprefixes. Observables:$suffix.
Utilities and testing
- Use lodash for common transforms (
kebabCase,isEmpty,isEqual,merge, ...) before writing a new utility. - Use
fixture.destroy()instead ofdiscardPeriodicTasks.
Portal Web UI Conventions
Design-system rules for the main portal app; the gravitee-apim-webui-libs libraries carry their own rules.
SCSS theme
- Always use the app theme via
@use '.../scss/theme' as app-theme;(path adjusted to the file location) and reference variables asapp-theme.$variable-name. Keepapp-themethe single entry point for theme tokens. - No hard-coded color values for any property — the shared Angular rule's "unless already local convention" escape is closed here. Find an existing variable in
variables.scssthat semantically matches the use case, even when its value is not exactly what a screenshot shows. Suggest a new variable only for a reusable property, never an ad-hoc one. - Layout: use the mixins and variables from
layout.scssfor spacing, breakpoints, and grid — no ad-hoc layout values.
Typography
- Use the typography classes from
typography.scss(.next-gen-h1,.next-gen-body, ...) as the single source for type styles. No ad-hoc classes duplicating typography and no hard-coded font-size, font-weight, or line-height.
Accessibility
- Decorative icons are hidden from screen readers (
aria-hidden="true"); meaningful icons carry accessible labels oraria-label. - Associate labels with inputs (id/label, or
aria-label/aria-labelledby). Announce errors and hints to screen readers. - Trees use proper roles and aria attributes (
role="tree",role="treeitem",aria-expanded,aria-selected) and keyboard navigation. - Screen-reader-only text uses a consistent pattern (
.sr-onlyor equivalent); neverdisplay: nonefor content that should be announced. - No toasts or snackbars (
MatSnackBaror similar transient notifications) for errors or confirmations — they are easily missed by screen readers. Display inline error or success messages near the relevant action or form withrole="alert"oraria-live="polite".
Localization
All user-facing text in portal components is localized. HTML uses the i18n attribute for text content and i18n-aria-label for aria-label; TypeScript uses $localize with @@messageId, adding placeholder metadata for interpolated strings:
<mat-card-title i18n="@@logInTitle">Login</mat-card-title>
<button i18n-aria-label="@@themeSelectorAriaLabel" aria-label="Theme">...</button>{ path: 'subscriptions', title: $localize`:@@subscriptionsTitle:Subscriptions` }
getGoToPageLabel(page: number): string {
return $localize`:@@paginationGoToPage:Go to page ${page}:page:`;
}GMD theming from the main app
- GMD components are themed from the main app via
gmd-overrides.scss— keep all GMD visual overrides (tokens, component overrides) in that file so the main app remains the single source of GMD theming in the portal. - Custom CSS in GMD content (e.g. homepage, subscription form) targets dark mode with
:host(.dark-mode) .selector— the gmd-viewer adds.dark-modeto its host when thedarkModeinput is true (Console preview) or the Portal theme is dark.
Testing
- Portal's
AppTestingModulewrapsHttpClientTestingModule, so the shared Angular rule'srxResourcetesting exception applies to it: inrxResourcespecs, default to the provider-style setup in.ai/guides/angular-async-patterns.md(a repository-root path) rather than copying a neighbouring spec — the module style hangs unless every data service is mocked directly, and the guide names the one working exception. - One
init(params)helper when a spec needs 2+ different TestBed configurations (providers, flags, stubs): give it default params soawait init()works with no arguments, and callawait init({ ... })only to override. Do not duplicateconfigureTestingModuleblocks or add nesteddescribes just to change config — nesteddescribes remain fine for logical grouping. Canonical example:src/app/log-in/log-in.component.spec.ts.
Naming: gmd-* vs gd-* in the main app
- Use the
gmd-*prefix for elements or components on the Gravitee Markdown (GMD) surface (wrappers, overrides). - Use the
gd-*prefix only for elements or components belonging to the gravitee-dashboard library (charts, dashboard widgets) — never for general app UI.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

