Skip to content

Commit 5ddd04b

Browse files
docs: add agent readiness files (#296)
* docs: add agent readiness files RHCLOUD-46729 Add AGENTS.md with project structure, conventions, module federation table, tech stack, pitfalls, and doc index. Add docs/*-guidelines.md for testing, security, error handling, and integration. Prepend @AGENTS.md import and build commands to existing CLAUDE.md. * docs: add application parts section RHCLOUD-46729 Address reviewer feedback: add Application Parts section to AGENTS.md describing the 3 user-facing surfaces (all learning resources page, bundle-specific pages, help panel) plus the creator tool. Add missing npm run verify command to claude.md. * docs: document API call exceptions RHCLOUD-46729 Update convention #9 to acknowledge 5 legacy components with inline API calls. Mark as tech debt to migrate when touching those files. * docs: clarify Chrome API abstraction RHCLOUD-46729 Reword convention #7 to make clear that useChrome is the sole public interface — don't import other Chrome internals. Addresses coderabbit review nitpick.
1 parent 4c11a3c commit 5ddd04b

6 files changed

Lines changed: 733 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Agents Guide — learning-resources
2+
3+
## Non-Negotiable Conventions
4+
5+
1. **Always use npm scripts** — never call `jest`, `eslint`, `cypress`, `playwright`, or `npx` directly. Use `npm test`, `npm run lint`, etc.
6+
2. **PatternFly 6** — this repo uses PF6 (`@patternfly/react-core@^6.4.0`). Follow PF6 API conventions.
7+
3. **TypeScript strict mode** — all new code must be TypeScript. `noImplicitAny` is enforced.
8+
4. **Colocate tests with source** — unit tests go next to the file they test (e.g., `Foo.test.tsx` beside `Foo.tsx`).
9+
5. **Colocate stories with source** — Storybook stories use the `.stories.tsx` suffix next to the component.
10+
6. **SCSS scoping** — all styles must be scoped under `.learning-resources` or `.learningResources` (configured in `fec.config.js` `sassPrefix`).
11+
7. **Chrome API abstraction** — always access Chrome functionality via the `useChrome` hook from `@redhat-cloud-services/frontend-components/useChrome`. Never import Chrome internals or other Chrome packages directly.
12+
8. **Feature flags via Unleash** — use `useFlag` / `useFlags` from `@unleash/proxy-client-react`. Never hardcode feature availability.
13+
9. **No direct API calls in components** — new API calls go in `src/utils/fetch*.ts` or `src/utils/toggleFavorite.ts`. Components consume data via hooks or props. **Known exceptions** (legacy — migrate when touching these files): `GlobalLearningResourcesQuickstartItem.tsx`, `LearnPanel.tsx`, `SearchResultItem.tsx` have inline `axios.post` for favorites (should use `toggleFavorite.ts`); `SupportPanel.tsx` and `FeedbackForm.tsx` have inline `fetch` calls for support-cases/feedback APIs.
14+
10. **Sort imports** — ESLint enforces `sort-imports` (declaration sort is ignored, but member sort is enforced).
15+
16+
## Project Structure
17+
18+
```
19+
learning-resources/
20+
src/
21+
AppEntry.tsx # Root app entry, module federation mount
22+
Creator.tsx # Creator tool entry point
23+
Viewer.tsx # Main viewer entry point
24+
Messages.ts # react-intl message definitions
25+
components/
26+
GlobalLearningResourcesPage/ # Main catalog page
27+
HelpPanel/ # Help panel (loaded by insights-chrome)
28+
LearningResourcesWidget/ # Bookmarked widget (exposed via MF)
29+
creator/ # Creator wizard + YAML editor
30+
common/ # Shared components
31+
user-journeys/ # User journey components
32+
hooks/
33+
useFilterMap.ts # Filter state management
34+
useQuickStarts.ts # Quickstart data hook
35+
utils/
36+
fetchQuickstarts.ts # API: quickstarts service
37+
fetchAllData.ts # Orchestrates all API calls
38+
fetchFilters.ts # API: filter categories
39+
fetchBundleInfoAPI.ts # API: bundle metadata
40+
toggleFavorite.ts # Favorite/unfavorite operations
41+
bundleUtils.ts # Bundle URL/name mapping
42+
openQuickStartInHelpPanel.ts # Cross-component event
43+
store/
44+
openQuickstartInHelpPanelStore.ts # Scalprum shared store
45+
data/
46+
quickstart-templates.ts # YAML templates for creator
47+
types/
48+
index.d.ts # Global type declarations
49+
docs/ # Existing documentation
50+
CREATOR_GUIDE.md # Creator tool user guide
51+
TECHNICAL_REFERENCE.md # Comprehensive technical reference
52+
backend-fuzzy-search-integration.md # Fuzzy search integration
53+
playwright/ # E2E tests
54+
all-learning-resources.spec.ts
55+
help-panel.spec.ts
56+
test-utils.ts
57+
cypress/ # Component tests
58+
component/
59+
.storybook/ # Storybook configuration
60+
main.ts # Framework, addons, webpack aliases
61+
preview.tsx # Global setup, MSW init, chrome mock
62+
test-runner.ts # Automated story testing
63+
hooks/ # Mock hooks (useChrome, unleash, scalprum)
64+
mocks/ # Chrome API mock
65+
.tekton/ # Konflux/Tekton CI pipelines
66+
.github/workflows/ # GitHub Actions CI
67+
config/ # Jest setup, webpack config
68+
```
69+
70+
## Module Federation
71+
72+
This app exposes 6 federated modules consumed by insights-chrome and other HCC apps:
73+
74+
| Module | Entry Point | Description |
75+
|--------|-------------|-------------|
76+
| `./RootApp` | `src/AppEntry.tsx` | Main app shell |
77+
| `./BookmarkedLearningResourcesWidget` | `src/components/LearningResourcesWidget/LearningResourcesWidget` | Bookmarked resources widget |
78+
| `./GlobalLearningResourcesPage` | `src/components/GlobalLearningResourcesPage/GlobalLearningResourcesPage` | Full catalog page |
79+
| `./Creator` | `src/Creator.tsx` | Quickstart/resource creator tool |
80+
| `./HelpPanel` | `src/components/HelpPanel/index.ts` | Help panel content (loaded by chrome) |
81+
| `./HelpPanelLink` | `src/components/HelpPanel/HelpPanelLink.tsx` | Help panel link component |
82+
83+
**Shared singleton:** `react-router-dom` (singleton, any version)
84+
85+
**App URLs:** `/learning-resources`, `/learning-resources/creator`, and bundle-prefixed variants (`/settings/learning-resources`, `/ansible/learning-resources`, etc.)
86+
87+
## Application Parts
88+
89+
This application serves three distinct user-facing surfaces on console.redhat.com:
90+
91+
1. **All Learning Resources page** — The main catalog at `/learning-resources` showing all available learning resources (quickstarts, documentation, learning paths). Users can filter by product family, content type, and other categories. Component: `GlobalLearningResourcesPage`.
92+
93+
2. **Bundle-specific Learning Resources** — Each bundle (Ansible, OpenShift, Settings, Insights, Edge, IAM) has its own learning resources page at `/<bundle>/learning-resources`, pre-filtered to show only resources relevant to that bundle. Same component (`GlobalLearningResourcesPage`) with bundle context from the URL. Bundle mapping is handled by `src/utils/bundleUtils.ts`.
94+
95+
3. **Help Panel** — A side panel loaded by insights-chrome (not by this app directly) via the `./HelpPanel` federated module. It displays APIs, learning resources, support cases, and provides filtering/search capabilities. Controlled by feature flags (`help-panel_search`, `help-panel_knowledge-base`, `help-panel_direct-ask-redhat`). Component: `HelpPanel`.
96+
97+
Additionally, the **Creator tool** at `/learning-resources/creator` lets content authors build and preview quickstarts via a wizard or YAML editor. Gated by the `platform.chrome.quickstarts.creator` feature flag.
98+
99+
## Tech Stack
100+
101+
- **React** 18.3.1, **TypeScript** ^5.9.3 (strict mode)
102+
- **PatternFly** React Core/Table ^6.4.0
103+
- **Build:** FEC (frontend-components-config), Webpack Module Federation, SWC
104+
- **State:** React hooks/context + Scalprum shared store (no Redux/Jotai)
105+
- **API:** Axios ^1.13.2 → quickstarts backend service
106+
- **i18n:** react-intl ^6.6.2
107+
- **Feature flags:** Unleash proxy client ^4.5.2
108+
- **Editor:** Monaco Editor ^0.55.1 (for YAML creator)
109+
- **Forms:** Data Driven Forms ^4.1.4 (PF4 mapper for creator wizard)
110+
111+
## Key Feature Flags
112+
113+
| Flag | Controls |
114+
|------|----------|
115+
| `platform.chrome.help-panel_search` | Search tab in help panel |
116+
| `platform.chrome.help-panel_knowledge-base` | KB tab in help panel |
117+
| `platform.chrome.help-panel_direct-ask-redhat` | Virtual Assistant button |
118+
| `platform.chrome.quickstarts.creator` | Creator tool access |
119+
120+
## Common Pitfalls
121+
122+
1. **Case-insensitive filesystem**`claude.md` and `CLAUDE.md` map to the same file on macOS.
123+
2. **Playwright baseline counts** — e2e tests have intentional hardcoded count assertions with tolerances. Do NOT remove them (reviewer-enforced).
124+
3. **Storybook mocks** — Storybook aliases `useChrome`, `@unleash/proxy-client-react`, and `@scalprum/react-core` to local mocks in `.storybook/hooks/`. New external dependencies may need similar aliases.
125+
4. **SWC platform bindings** — CI requires `@swc/core` platform binding fixes (see `.github/workflows/test.yml`).
126+
5. **Playwright auth** — E2E tests use `@redhat-cloud-services/playwright-test-auth` for SSO login via global setup. Requires `E2E_USER` and `E2E_PASSWORD` env vars.
127+
6. **Jest CSS** — SCSS/CSS imports are mapped to `identity-obj-proxy` in jest.config.js. Do NOT import styles in test files expecting real CSS.
128+
7. **Data Driven Forms** — Creator wizard uses `@data-driven-forms/pf4-component-mapper` (PF4, NOT PF6). This is intentional — the DDF PF4 mapper works with PF6 at runtime.
129+
8. **No Error Boundary** — the repo has no explicit React Error Boundary. Error states are handled per-component via fallback components.
130+
131+
## Documentation Index
132+
133+
### Agent Guidelines (docs/)
134+
- `docs/testing-guidelines.md` — Testing patterns, frameworks, coverage
135+
- `docs/security-guidelines.md` — Auth, feature flags, data access
136+
- `docs/error-handling-guidelines.md` — Error patterns, fallback components
137+
- `docs/integration-guidelines.md` — Module federation, Chrome API, Storybook, CI/CD
138+
139+
### Existing Documentation (docs/)
140+
- `docs/TECHNICAL_REFERENCE.md` — Comprehensive technical documentation
141+
- `docs/CREATOR_GUIDE.md` — Creator tool user guide
142+
- `docs/backend-fuzzy-search-integration.md` — Fuzzy search API integration
143+
144+
### Architecture
145+
- `ARCHITECTURE.md` — High-level architecture overview
146+
147+
### Storybook Documentation (src/docs/)
148+
- `src/docs/Introduction.mdx` — Storybook introduction
149+
- `src/docs/ComponentReference.mdx` — Component reference
150+
- `src/docs/UserJourneys.mdx` — User journey documentation
151+
- `src/docs/HelpPanelArchitecture.mdx` — Help panel architecture

claude.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
@AGENTS.md
2+
3+
# Build / Test / Lint Commands
4+
5+
```bash
6+
npm install # Install dependencies
7+
npm run build # Production build (via FEC)
8+
npm start # Dev server with HMR (FEC dev-proxy)
9+
npm test # Jest unit tests
10+
npm test -- --watch # Jest watch mode
11+
npm run lint # ESLint
12+
npm run storybook # Storybook dev server (port 6006)
13+
npm run build-storybook # Build static Storybook
14+
npm run test-storybook # Storybook test runner (requires running server)
15+
npm run cypress:component # Cypress component tests (headless)
16+
npm run verify # Full CI check: build + lint + test
17+
```
18+
19+
---
20+
121
# Claude-Assisted Changes
222

323
This document tracks significant changes made with Claude Code assistance to help future maintainers understand the context and rationale.

docs/error-handling-guidelines.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Error Handling Guidelines — learning-resources
2+
3+
## Error Handling Architecture
4+
5+
This repo does **not** have a global React Error Boundary. Error handling is done per-component using fallback components, try/catch blocks, and conditional rendering.
6+
7+
## Fallback Components
8+
9+
### Pattern
10+
Components that load async data provide dedicated fallback variants:
11+
12+
| Component | Fallback |
13+
|-----------|----------|
14+
| `GlobalLearningResourcesContent.tsx` | `GlobalLearningResourcesContentFallback.tsx` |
15+
| `GlobalLearningResourcesFilters.tsx` | `GlobalLearningResourcesFiltersFallback.tsx` |
16+
17+
Fallback components render skeleton/loading states and are used with `React.Suspense`.
18+
19+
### Empty States
20+
The `EmptyState.tsx` component handles scenarios where no data is available after a successful API call. This is distinct from error states — empty state means the API succeeded but returned zero results.
21+
22+
## API Error Handling
23+
24+
### fetch* Utilities
25+
API call utilities in `src/utils/` throw errors that bubble up to the consuming component:
26+
27+
```typescript
28+
// src/utils/fetchQuickstarts.ts
29+
const user = await getUser();
30+
if (!user) {
31+
throw new Error('User not logged in');
32+
}
33+
```
34+
35+
### Component-Level Catch
36+
Components that call APIs wrap them in try/catch:
37+
38+
```typescript
39+
// HelpPanelCustomTabs.tsx
40+
try {
41+
const quickstarts = await fetchQuickstarts(getUser, options);
42+
setData(quickstarts);
43+
} catch (err) {
44+
console.error('Help Panel: failed to load quickstarts', err);
45+
// Render empty/error state
46+
}
47+
```
48+
49+
### Rules
50+
- Always log errors with `console.error()` — the Storybook test runner detects critical errors
51+
- Never silently swallow errors — at minimum log them
52+
- Show user-friendly error states, not raw error messages
53+
- API errors should result in graceful degradation, not crashes
54+
55+
## Storybook Error Stories
56+
57+
Components with API dependencies should include error story variants to demonstrate error handling:
58+
59+
```typescript
60+
export const ApiError: Story = {
61+
parameters: {
62+
msw: {
63+
handlers: [
64+
http.get('/api/endpoint', () => {
65+
return new HttpResponse(null, { status: 500 });
66+
}),
67+
],
68+
},
69+
},
70+
};
71+
```
72+
73+
Existing error stories:
74+
- `APIPanel.stories.tsx``ApiError` variant
75+
- `SupportPanel.stories.tsx``ApiError` variant
76+
77+
## Console Error Detection
78+
79+
The Storybook test runner (`.storybook/test-runner.ts`) automatically fails stories that emit:
80+
- React warnings (e.g., `Warning: Each child in a list...`)
81+
- JavaScript errors
82+
- React Router errors
83+
- react-intl errors
84+
85+
### Ignored Patterns (Not Errors)
86+
- MSW mock API responses
87+
- Storybook informational warnings
88+
- Testing Library async logs
89+
90+
### Skipping Error Detection
91+
For stories that intentionally produce errors:
92+
```typescript
93+
export const IntentionalError: Story = {
94+
parameters: {
95+
testRunner: { ignoreConsoleErrors: true },
96+
},
97+
};
98+
```
99+
100+
## Loading States
101+
102+
### Suspense Boundaries
103+
Components loaded lazily or with async data use `React.Suspense` with fallback components:
104+
105+
```tsx
106+
<Suspense fallback={<ContentFallback />}>
107+
<GlobalLearningResourcesContent />
108+
</Suspense>
109+
```
110+
111+
### useSuspenseLoader
112+
The app uses `useSuspenseLoader` from Chrome for data loading:
113+
```typescript
114+
const { fetchAllData } = useSuspenseLoader(fetchAllData);
115+
```
116+
This integrates with React Suspense for seamless loading states.
117+
118+
## Feature Flag Error Handling
119+
120+
Feature flags can fail silently. Components using `useFlag` / `useFlags` should handle the case where a flag is undefined:
121+
122+
```typescript
123+
const flags = useFlags();
124+
const flag = flags.find(({ name }) => name === 'feature.name');
125+
const isEnabled = flag?.enabled ?? false; // Default to false if flag is missing
126+
```
127+
128+
This ensures the UI degrades gracefully if the Unleash proxy is unavailable.

0 commit comments

Comments
 (0)