Streamline agent instructions
This commit is contained in:
@@ -1,182 +1,123 @@
|
||||
# AGENTS.md — Aeroflot.Flights.Web
|
||||
# AGENTS.md - Aeroflot.Flights.Web
|
||||
|
||||
## Quick Start
|
||||
## Read First
|
||||
|
||||
React 18 SSR app on Modern.js 2.70.8 with Rspack and Module Federation 2.3.3. It is deployed both as a standalone SSR app and as a remote frontend component for customer Web/PWA hosts.
|
||||
|
||||
Work in `src/`. Treat `ClientApp/` as legacy Angular 12 reference only unless the user explicitly asks otherwise.
|
||||
|
||||
Prefer small, local changes that match the existing architecture. Do not widen dependencies across layers, and do not introduce browser-only imports into SSR paths.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Development servers
|
||||
pnpm dev # Modern.js on :8081
|
||||
pnpm dev:full # Proxy on :8080 (API forwarding via curl to bypass WAF)
|
||||
pnpm dev:full # Proxy on :8080; forwards API via curl
|
||||
|
||||
# Build targets
|
||||
pnpm build:standalone # SSR server at dist/standalone/
|
||||
pnpm build:remote # MF remote at dist/remote/ (with mf-manifest.json)
|
||||
pnpm build:both # Both targets
|
||||
|
||||
# Quality checks (run in order)
|
||||
pnpm typecheck
|
||||
pnpm lint
|
||||
pnpm test
|
||||
pnpm test:coverage
|
||||
pnpm bundle-size # CI gate: total gzip ≤ 2000 kB
|
||||
pnpm check-coverage # CI gate: line coverage ≥ 65%
|
||||
pnpm bundle-size # remote gzip budget: <= 2000 kB
|
||||
pnpm check-coverage # line coverage gate: >= 65%
|
||||
|
||||
# E2E tests
|
||||
pnpm test:e2e # React app (port 8080)
|
||||
pnpm test:e2e:angular # Angular app (port 4203)
|
||||
pnpm build:standalone # dist/standalone/
|
||||
pnpm build:remote # dist/remote/ with mf-manifest.json
|
||||
pnpm build:both
|
||||
|
||||
pnpm test:e2e # React app, baseURL http://localhost:8080
|
||||
pnpm test:e2e:angular # Legacy Angular app, port 4203
|
||||
```
|
||||
|
||||
## Current State
|
||||
## Critical Rules
|
||||
|
||||
React 18 SSR application built with **Modern.js 2.70.8** (Rspack bundler) and **Module Federation 2.3.3**. The app is a remote frontend component embeddable in the customer's channel apps (Web, PWA).
|
||||
|
||||
**Stack:** Modern.js 2.70.8, React 18.2, Rspack, Module Federation 2.3.3, i18next (9 languages), PrimeReact, Leaflet, SignalR, OpenTelemetry, Vitest, Playwright.
|
||||
|
||||
**Source:** `src/` (file-based routing under `src/routes/`). Legacy Angular 12 SPA in `ClientApp/` (read-only reference, not deployed).
|
||||
|
||||
**Builds:** `pnpm build:standalone` (SSR server at `dist/standalone/`), `pnpm build:remote` (MF remote at `dist/remote/` with `mf-manifest.json`).
|
||||
|
||||
**Dev:** `pnpm dev` (Modern.js on :8081), `pnpm dev:full` (proxy on :8080 with API forwarding via curl to bypass WAF).
|
||||
|
||||
**Known constraint:** Modern.js 3.x upgrade is blocked by `@module-federation/modern-js` ESM incompatibilities (broken `__filename`/`require` in ESM bundles, missing `api.modifyWebpackConfig` in Rsbuild 2.0). React Router v7 future flags are enabled to suppress deprecation warnings.
|
||||
|
||||
## Contractual Requirements
|
||||
|
||||
The following are contractual hard constraints for the remote frontend component.
|
||||
|
||||
### 1. Tech Stack
|
||||
|
||||
- **ModernJS (SSR)** for the frontend framework.
|
||||
- **Module Federation 2.0**. Any bundler with MF 2.0 support is acceptable: Webpack 5, Rsbuild, Rspack, or Vite.
|
||||
- Must emit `mf-manifest.json` at `https://<domain>/mf-manifest.json` exposing components and logic. Reference: https://module-federation.io/guide/basic/webpack.html.
|
||||
- **React 18+**, Concurrent Mode compatible.
|
||||
- `<Suspense>` support required when async loading is used.
|
||||
- Component bodies must be side-effect free — **no `fetch` outside `useEffect`**.
|
||||
- Dynamic imports must use `React.lazy()`.
|
||||
|
||||
### 2. Data & Integrations
|
||||
|
||||
- Consumes customer REST APIs, JSON payloads only.
|
||||
- Rendered data must stay consistent with API responses (no stale state leaking into the UI).
|
||||
|
||||
### 3. Performance
|
||||
|
||||
- Must sustain **100 RPS**.
|
||||
|
||||
### 4. Availability & Fault Tolerance
|
||||
|
||||
- VMs hosting the component must be geographically distributed.
|
||||
- 24/7/365 availability; recovery time ≤ 6 hours after infra is restored.
|
||||
|
||||
### 5. Security
|
||||
|
||||
- Component must be isolated — no attack surface exposed to other components of the host site.
|
||||
|
||||
### 6. SEO & Accessibility
|
||||
|
||||
- SEO optimization required.
|
||||
- Render microdata: **JSON-LD** and **OpenGraph**.
|
||||
- Web analytics integrations: **Yandex.Metrica, CTM, Variocube, Key-Astrom (Dynatrace)**.
|
||||
|
||||
### 7. Cross-Platform
|
||||
|
||||
- Embeddable in multiple channel apps (Web, PWA).
|
||||
- Fully responsive ("fluid") layout across all screen sizes.
|
||||
|
||||
### 8. Logging & Monitoring
|
||||
|
||||
- Frontend log collection in a customer-specified format, shipped to the customer's log aggregation system.
|
||||
- System event monitoring with export to a metrics aggregator.
|
||||
|
||||
### 9. Module Structure
|
||||
|
||||
- Must conform to the customer's standard remote frontend module structure for uniform deployment.
|
||||
|
||||
### 10. Design
|
||||
|
||||
- Implement against customer-provided mockups using the customer's design system.
|
||||
- Must embed other customer remote components when available.
|
||||
- Components must be side-effect free: no `fetch` outside `useEffect`; use the API client from context.
|
||||
- Use `React.lazy()` for dynamic imports. Wrap browser-only UI such as Leaflet in `ClientOnly`.
|
||||
- SignalR must stay out of SSR bundles; import `@microsoft/signalr` dynamically only.
|
||||
- Read env through `getEnv()` from `@/env/index.ts`; SSR injects `window.__ENV__`.
|
||||
- Keep rendered state consistent with API responses; avoid stale state leaking into UI.
|
||||
- Preserve SEO/accessibility requirements, including JSON-LD and OpenGraph where relevant.
|
||||
- Keep layouts fluid and responsive across screen sizes.
|
||||
|
||||
## Architecture
|
||||
|
||||
**Source structure:**
|
||||
- `src/routes/` — File-based routing (React Router v7)
|
||||
- `src/features/` — Feature modules (online-board, schedule, flights-map, popular-requests)
|
||||
- `src/ui/` — Reusable UI primitives (never import routes/mf from here)
|
||||
- `src/shared/` — Cross-cutting concerns (API client, SignalR, storage, hooks)
|
||||
- `src/observability/` — Logger, metrics (OTel), analytics
|
||||
- `src/i18n/` — Internationalization (9 languages)
|
||||
Top-level source areas:
|
||||
|
||||
**Entry points:**
|
||||
- `src/routes/page.tsx` — Root redirect to `/{lang}/onlineboard`
|
||||
- `src/routes/layout.tsx` — Root layout with global providers
|
||||
- `src/routes/[lang]/layout.tsx` — Locale-scoped layout with i18n
|
||||
- `src/routes/` - file-based routing and layouts.
|
||||
- `src/features/` - feature modules: online board, schedule, flights map, popular requests.
|
||||
- `src/ui/` - shared UI primitives only.
|
||||
- `src/shared/` - API client, storage, hooks, SignalR helpers.
|
||||
- `src/observability/` - logging, metrics, analytics.
|
||||
- `src/i18n/` - i18n provider and translations.
|
||||
|
||||
**Module Federation:**
|
||||
- Remote name: `aeroflot_flights`
|
||||
- Exposes: `./OnlineBoard`, `./Schedule`, `./FlightsMap`, `./PopularRequests`
|
||||
- mf-manifest.json at `https://<domain>/mf-manifest.json`
|
||||
Entry points:
|
||||
|
||||
## Critical Constraints
|
||||
- `src/routes/page.tsx` redirects to `/{lang}/onlineboard`.
|
||||
- `src/routes/layout.tsx` owns global providers.
|
||||
- `src/routes/[lang]/layout.tsx` owns locale-scoped i18n.
|
||||
|
||||
1. **Side-effect-free components** — No `fetch` outside `useEffect`. API calls via `ApiClient` from context.
|
||||
Module Federation:
|
||||
|
||||
2. **Dynamic imports** — Use `React.lazy()` for code splitting. Wrap browser-only components (Leaflet) in `ClientOnly`.
|
||||
- Remote name: `aeroflot_flights`.
|
||||
- Exposes: `./OnlineBoard`, `./Schedule`, `./FlightsMap`, `./PopularRequests`.
|
||||
- Remote build must emit `dist/remote/mf-manifest.json`, served as `/mf-manifest.json`.
|
||||
|
||||
3. **SSR safety** — SignalR (`@microsoft/signalr`) is dynamically imported. Never import in SSR bundle (routes/, server/).
|
||||
## Layer Boundaries
|
||||
|
||||
4. **Layered architecture** — Enforced by ESLint:
|
||||
- `features/` → cannot import `routes/` or `mf/`
|
||||
- `ui/` → cannot import `features/`, `routes/`, `mf/`
|
||||
- `shared/` → cannot import `features/`, `routes/`, `mf/`, `observability/`
|
||||
- `observability/` → cannot import `features/`, `routes/`, `mf/`
|
||||
ESLint enforces these boundaries:
|
||||
|
||||
5. **Restricted imports** (ESLint rules):
|
||||
- OTel SDK → use `@/observability/metrics/otel` (getMeter/getTracer)
|
||||
- react-i18next → use `@/i18n/provider`
|
||||
- localStorage/sessionStorage → use `@/shared/storage`
|
||||
- `features/` must not import `routes/` or `mf/`.
|
||||
- `ui/` must not import `features/`, `routes/`, or `mf/`.
|
||||
- `shared/` must not import `features/`, `routes/`, `mf/`, or `observability/`.
|
||||
- `observability/` must not import `features/`, `routes/`, or `mf/`.
|
||||
|
||||
6. **Environment variables** — Read via `getEnv()` from `@/env/index.ts`. SSR injects `window.__ENV__`.
|
||||
Restricted imports:
|
||||
|
||||
## Dev Server Details
|
||||
- Use `@/observability/metrics/otel` instead of importing OTel SDKs directly.
|
||||
- Use `@/i18n/provider` instead of importing `react-i18next` directly.
|
||||
- Use `@/shared/storage` instead of direct `localStorage` or `sessionStorage`.
|
||||
|
||||
- **Port 8081** — Modern.js dev server (SSR + HMR)
|
||||
- **Port 8080** — `pnpm dev:full` proxy with:
|
||||
- `/api/*` and `/flights/*` → `https://flights.test.aeroflot.ru` (via curl to bypass WAF)
|
||||
- `/*` → Modern.js on 8081
|
||||
## Progressive Detail
|
||||
|
||||
## Testing
|
||||
Reach for the sections below only when the task needs them.
|
||||
|
||||
- **Unit tests** — Vitest (globals enabled, V8 coverage)
|
||||
- **E2E tests** — Playwright (baseURL: `http://localhost:8080`)
|
||||
- **Angular E2E** — Separate config for legacy app (port 4203)
|
||||
### Contractual Requirements
|
||||
|
||||
**Coverage gates:**
|
||||
- Line coverage ≥ 65%
|
||||
- Bundle size (gzip) ≤ 2000 kB for remote target
|
||||
- Modern.js SSR, React 18+, Module Federation 2.0 compatible output.
|
||||
- `mf-manifest.json` must expose components and logic at `https://<domain>/mf-manifest.json`.
|
||||
- Customer REST APIs use JSON payloads only.
|
||||
- Target capacity: 100 RPS.
|
||||
- Remote component must remain isolated from host components.
|
||||
- Required analytics/monitoring integrations include Yandex.Metrica, CTM, Variocube, and Key-Astrom/Dynatrace.
|
||||
- Frontend logs and system events must be exportable to customer aggregators.
|
||||
- Implementation must follow customer mockups, design system, and standard remote module structure.
|
||||
|
||||
## Build Artifacts
|
||||
### Dev Server
|
||||
|
||||
- `dist/standalone/` — SSR server (Node entrypoint)
|
||||
- `dist/remote/` — MF remote with `mf-manifest.json`
|
||||
- `dist/remote/static/js/` — JS bundles for bundle-size gate
|
||||
- `pnpm dev` serves Modern.js SSR/HMR on port 8081.
|
||||
- `pnpm dev:full` serves port 8080 and proxies:
|
||||
- `/api/*` and `/flights/*` to `https://flights.test.aeroflot.ru` via curl.
|
||||
- all other paths to Modern.js on 8081.
|
||||
|
||||
## Deployment
|
||||
### Build And Deploy
|
||||
|
||||
- **Standalone** — Dockerfile.react (Node 24-slim, serves SSR)
|
||||
- **Remote** — Dockerfile.remote (nginx serving static files)
|
||||
- CI/CD: `.github/workflows/ci.yml`, `.github/workflows/deploy.yml`
|
||||
- `dist/standalone/` is the Node SSR server, deployed with `Dockerfile.react`.
|
||||
- `dist/remote/` is the static MF remote, deployed with `Dockerfile.remote`.
|
||||
- CI/CD lives in `.github/workflows/ci.yml` and `.github/workflows/deploy.yml`.
|
||||
|
||||
## Commit Rules
|
||||
### Current Constraints
|
||||
|
||||
- Never add `Co-Authored-By` lines to commit messages.
|
||||
- Commit messages in English, concise, focused on "why" not "what".
|
||||
- Commit autonomously when changes are complete and stable — no need to ask for permission. Group related edits into logical commits. Still ask before pushing, force-pushing, or any destructive git operation.
|
||||
- Modern.js 3.x upgrade is currently blocked by `@module-federation/modern-js` ESM incompatibilities.
|
||||
- React Router v7 future flags are enabled to suppress deprecation warnings.
|
||||
|
||||
## Gitea / Tea Command Rules
|
||||
## Git And CI
|
||||
|
||||
- Use `tea` command to check Gitea workflow runs: `tea run list --limit 5` to see last 5 runs
|
||||
- Use `tea run view <run-id>` to inspect a specific run
|
||||
- Use `tea run rerun <run-id>` to re-run a failed workflow
|
||||
- Do not add `Co-Authored-By` lines.
|
||||
- Commit messages must be English, concise, and focused on why.
|
||||
- Commit completed stable work autonomously. Ask before pushing, force-pushing, or destructive git operations.
|
||||
- Use Gitea `tea` for workflow runs:
|
||||
- `tea run list --limit 5`
|
||||
- `tea run view <run-id>`
|
||||
- `tea run rerun <run-id>`
|
||||
|
||||
Reference in New Issue
Block a user